aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build.xml2
-rw-r--r--findbugs-exclude.xml36
-rw-r--r--src/documentation/intermediate-format-ng/fop-intermediate-format-ng.xsd15
-rw-r--r--src/java/org/apache/fop/accessibility/Accessibility.java54
-rw-r--r--src/java/org/apache/fop/accessibility/AccessibilityPreprocessor.java95
-rw-r--r--src/java/org/apache/fop/accessibility/DummyStructureTreeEventHandler.java63
-rw-r--r--src/java/org/apache/fop/accessibility/StructureTree.java102
-rw-r--r--src/java/org/apache/fop/accessibility/StructureTree2SAXEventAdapter.java123
-rw-r--r--src/java/org/apache/fop/accessibility/StructureTreeBuilder.java95
-rw-r--r--src/java/org/apache/fop/accessibility/StructureTreeElement.java28
-rw-r--r--src/java/org/apache/fop/accessibility/StructureTreeEventHandler.java79
-rw-r--r--src/java/org/apache/fop/accessibility/addPtr.xsl88
-rw-r--r--src/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java491
-rw-r--r--src/java/org/apache/fop/accessibility/fo/FOEventRecorder.java508
-rw-r--r--src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java410
-rw-r--r--src/java/org/apache/fop/apps/FOUserAgent.java31
-rw-r--r--src/java/org/apache/fop/apps/Fop.java7
-rw-r--r--src/java/org/apache/fop/area/AreaTreeHandler.java9
-rw-r--r--src/java/org/apache/fop/area/AreaTreeModel.java8
-rw-r--r--src/java/org/apache/fop/area/AreaTreeParser.java69
-rw-r--r--src/java/org/apache/fop/area/RenderPagesModel.java6
-rw-r--r--src/java/org/apache/fop/area/Trait.java6
-rw-r--r--src/java/org/apache/fop/fo/Constants.java8
-rw-r--r--src/java/org/apache/fop/fo/DelegatingFOEventHandler.java404
-rw-r--r--src/java/org/apache/fop/fo/FOElementMapping.java5
-rw-r--r--src/java/org/apache/fop/fo/FOEventHandler.java88
-rw-r--r--src/java/org/apache/fop/fo/FONode.java10
-rw-r--r--src/java/org/apache/fop/fo/FOPropertyMapping.java6
-rw-r--r--src/java/org/apache/fop/fo/FOText.java34
-rw-r--r--src/java/org/apache/fop/fo/FOTreeBuilder.java5
-rw-r--r--src/java/org/apache/fop/fo/PropertyList.java10
-rw-r--r--src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java5
-rw-r--r--src/java/org/apache/fop/fo/extensions/InternalElementMapping.java14
-rw-r--r--src/java/org/apache/fop/fo/flow/AbstractGraphics.java34
-rw-r--r--src/java/org/apache/fop/fo/flow/AbstractListItemPart.java14
-rw-r--r--src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java27
-rw-r--r--src/java/org/apache/fop/fo/flow/BasicLink.java19
-rw-r--r--src/java/org/apache/fop/fo/flow/Block.java20
-rw-r--r--src/java/org/apache/fop/fo/flow/Character.java17
-rw-r--r--src/java/org/apache/fop/fo/flow/Footnote.java16
-rw-r--r--src/java/org/apache/fop/fo/flow/FootnoteBody.java17
-rw-r--r--src/java/org/apache/fop/fo/flow/InitialPropertySet.java16
-rw-r--r--src/java/org/apache/fop/fo/flow/Inline.java10
-rw-r--r--src/java/org/apache/fop/fo/flow/InlineLevel.java11
-rw-r--r--src/java/org/apache/fop/fo/flow/InstreamForeignObject.java8
-rw-r--r--src/java/org/apache/fop/fo/flow/Leader.java12
-rw-r--r--src/java/org/apache/fop/fo/flow/ListBlock.java12
-rw-r--r--src/java/org/apache/fop/fo/flow/ListItem.java12
-rw-r--r--src/java/org/apache/fop/fo/flow/ListItemBody.java4
-rw-r--r--src/java/org/apache/fop/fo/flow/ListItemLabel.java4
-rw-r--r--src/java/org/apache/fop/fo/flow/PageNumber.java28
-rw-r--r--src/java/org/apache/fop/fo/flow/Wrapper.java12
-rw-r--r--src/java/org/apache/fop/fo/flow/table/Table.java13
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableAndCaption.java23
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableCaption.java16
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableCell.java12
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableCellContainer.java19
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableFObj.java10
-rw-r--r--src/java/org/apache/fop/fo/pagination/Root.java42
-rw-r--r--src/java/org/apache/fop/fo/pagination/StaticContent.java4
-rw-r--r--src/java/org/apache/fop/fo/pagination/bookmarks/Bookmark.java14
-rw-r--r--src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTitle.java19
-rw-r--r--src/java/org/apache/fop/fo/properties/CommonAccessibility.java65
-rw-r--r--src/java/org/apache/fop/fo/properties/CommonAccessibilityHolder.java (renamed from src/java/org/apache/fop/fo/properties/StructurePointerPropertySet.java)15
-rw-r--r--src/java/org/apache/fop/fo/properties/StructureTreeElementHolder.java38
-rw-r--r--src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java1
-rw-r--r--src/java/org/apache/fop/layoutmgr/TraitSetter.java15
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java2
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java2
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java2
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java2
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java8
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java18
-rw-r--r--src/java/org/apache/fop/pdf/PDFDocument.java19
-rw-r--r--src/java/org/apache/fop/pdf/PDFProfile.java6
-rw-r--r--src/java/org/apache/fop/pdf/PDFRoot.java18
-rw-r--r--src/java/org/apache/fop/pdf/PDFStructElem.java114
-rw-r--r--src/java/org/apache/fop/render/AbstractRenderer.java5
-rw-r--r--src/java/org/apache/fop/render/Renderer.java7
-rw-r--r--src/java/org/apache/fop/render/intermediate/AbstractIFDocumentHandler.java17
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFConstants.java2
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFContext.java33
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFDocumentHandler.java16
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFParser.java123
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFRenderer.java33
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFSerializer.java78
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFSerializerMaker.java3
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFStructureTreeBuilder.java239
-rw-r--r--src/java/org/apache/fop/render/intermediate/extensions/AbstractAction.java14
-rw-r--r--src/java/org/apache/fop/render/intermediate/extensions/DocumentNavigationHandler.java24
-rw-r--r--src/java/org/apache/fop/render/intermediate/util/IFDocumentHandlerProxy.java16
-rw-r--r--src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java37
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java59
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFDocumentHandlerMaker.java3
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFDocumentNavigationHandler.java8
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java145
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFPainter.java21
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java116
-rw-r--r--src/java/org/apache/fop/render/rtf/RTFHandler.java56
-rw-r--r--src/java/org/apache/fop/render/xml/XMLRenderer.java30
-rw-r--r--src/java/org/apache/fop/util/LanguageTags.java66
-rw-r--r--src/java/org/apache/fop/util/XMLUtil.java36
-rw-r--r--status.xml3
-rw-r--r--test/accessibility/README29
-rw-r--r--test/accessibility/background-image_jpg_repeat.fo4
-rw-r--r--test/accessibility/background-image_jpg_single.fo4
-rw-r--r--test/accessibility/background-image_png_repeat.fo4
-rw-r--r--test/accessibility/background-image_png_single.fo4
-rw-r--r--test/accessibility/background-image_svg_repeat.fo4
-rw-r--r--test/accessibility/background-image_svg_single.fo4
-rw-r--r--test/accessibility/complete.fo6
-rw-r--r--test/accessibility/config-renderer.xconf24
-rw-r--r--test/accessibility/fop.xconf (renamed from test/accessibility/config-painter.xconf)0
-rw-r--r--test/accessibility/image_jpg.fo4
-rw-r--r--test/accessibility/image_png.fo4
-rw-r--r--test/accessibility/image_svg.fo4
-rw-r--r--test/accessibility/image_wmf.fo4
-rw-r--r--test/accessibility/leader.fo4
-rw-r--r--test/accessibility/links.fo4
-rw-r--r--test/accessibility/pdf/background-image_jpg_repeat.pdf (renamed from test/accessibility/pdf/background-image_jpg_repeat_painter_orig.pdf)bin12767 -> 12806 bytes
-rw-r--r--test/accessibility/pdf/background-image_jpg_repeat_renderer_orig.pdfbin12678 -> 0 bytes
-rw-r--r--test/accessibility/pdf/background-image_jpg_single.pdf (renamed from test/accessibility/pdf/background-image_jpg_single_painter_orig.pdf)bin12606 -> 12645 bytes
-rw-r--r--test/accessibility/pdf/background-image_jpg_single_renderer_orig.pdfbin12517 -> 0 bytes
-rw-r--r--test/accessibility/pdf/background-image_png_repeat.pdf (renamed from test/accessibility/pdf/background-image_png_repeat_painter_orig.pdf)bin35390 -> 35429 bytes
-rw-r--r--test/accessibility/pdf/background-image_png_repeat_renderer_orig.pdfbin35301 -> 0 bytes
-rw-r--r--test/accessibility/pdf/background-image_png_single.pdfbin0 -> 58309 bytes
-rw-r--r--test/accessibility/pdf/background-image_png_single_painter_orig.pdfbin58601 -> 0 bytes
-rw-r--r--test/accessibility/pdf/background-image_png_single_renderer_orig.pdfbin58512 -> 0 bytes
-rw-r--r--test/accessibility/pdf/background-image_svg_repeat.pdf (renamed from test/accessibility/pdf/background-image_svg_repeat_painter_orig.pdf)bin17431 -> 17096 bytes
-rw-r--r--test/accessibility/pdf/background-image_svg_repeat_renderer_orig.pdfbin17342 -> 0 bytes
-rw-r--r--test/accessibility/pdf/background-image_svg_single.pdf (renamed from test/accessibility/pdf/background-image_svg_single_painter_orig.pdf)bin9988 -> 9935 bytes
-rw-r--r--test/accessibility/pdf/background-image_svg_single_renderer_orig.pdfbin9899 -> 0 bytes
-rw-r--r--test/accessibility/pdf/complete.pdfbin0 -> 96722 bytes
-rw-r--r--test/accessibility/pdf/complete_painter_orig.pdfbin96966 -> 0 bytes
-rw-r--r--test/accessibility/pdf/complete_renderer_orig.pdfbin96880 -> 0 bytes
-rw-r--r--test/accessibility/pdf/image_jpg.pdf (renamed from test/accessibility/pdf/image_jpg_painter_orig.pdf)bin9031 -> 9070 bytes
-rw-r--r--test/accessibility/pdf/image_jpg_renderer_orig.pdfbin8942 -> 0 bytes
-rw-r--r--test/accessibility/pdf/image_png.pdfbin0 -> 57780 bytes
-rw-r--r--test/accessibility/pdf/image_png_painter_orig.pdfbin58072 -> 0 bytes
-rw-r--r--test/accessibility/pdf/image_png_renderer_orig.pdfbin57983 -> 0 bytes
-rw-r--r--test/accessibility/pdf/image_svg.pdf (renamed from test/accessibility/pdf/image_svg_painter_orig.pdf)bin14045 -> 14284 bytes
-rw-r--r--test/accessibility/pdf/image_svg_renderer_orig.pdfbin13956 -> 0 bytes
-rw-r--r--test/accessibility/pdf/image_wmf.pdfbin0 -> 304960 bytes
-rw-r--r--test/accessibility/pdf/image_wmf_painter_orig.pdfbin177205 -> 0 bytes
-rw-r--r--test/accessibility/pdf/image_wmf_renderer_orig.pdfbin177116 -> 0 bytes
-rw-r--r--test/accessibility/pdf/leader.pdf (renamed from test/accessibility/pdf/leader_painter_orig.pdf)bin9334 -> 9371 bytes
-rw-r--r--test/accessibility/pdf/leader_renderer_orig.pdfbin9257 -> 0 bytes
-rw-r--r--test/accessibility/pdf/links.pdf (renamed from test/accessibility/pdf/links_painter_orig.pdf)bin9666 -> 9704 bytes
-rw-r--r--test/accessibility/pdf/links_renderer_orig.pdfbin9534 -> 0 bytes
-rw-r--r--test/accessibility/pdf/role.pdf (renamed from test/accessibility/pdf/role_painter_orig.pdf)bin18924 -> 18968 bytes
-rw-r--r--test/accessibility/pdf/role_non-standard.pdf (renamed from test/accessibility/pdf/role_non-standard_painter_orig.pdf)bin18938 -> 18982 bytes
-rw-r--r--test/accessibility/pdf/role_non-standard_renderer_orig.pdfbin18849 -> 0 bytes
-rw-r--r--test/accessibility/pdf/role_renderer_orig.pdfbin18835 -> 0 bytes
-rw-r--r--test/accessibility/pdf/text_1.pdf (renamed from test/accessibility/pdf/text_1_painter_orig.pdf)bin7458 -> 7496 bytes
-rw-r--r--test/accessibility/pdf/text_1_renderer_orig.pdfbin7369 -> 0 bytes
-rw-r--r--test/accessibility/pdf/text_2.pdf (renamed from test/accessibility/pdf/text_2_painter_orig.pdf)bin10296 -> 10338 bytes
-rw-r--r--test/accessibility/pdf/text_2_renderer_orig.pdfbin10207 -> 0 bytes
-rw-r--r--test/accessibility/pdf/text_font-embedding.pdf (renamed from test/accessibility/pdf/text_font-embedding_painter_orig.pdf)bin19781 -> 19777 bytes
-rw-r--r--test/accessibility/pdf/text_font-embedding_renderer_orig.pdfbin19692 -> 0 bytes
-rw-r--r--test/accessibility/role.fo4
-rw-r--r--test/accessibility/role_non-standard.fo4
-rw-r--r--test/accessibility/text_1.fo4
-rw-r--r--test/accessibility/text_2.fo4
-rw-r--r--test/accessibility/text_font-embedding.fo4
-rw-r--r--test/java/org/apache/fop/StandardTestSuite.java3
-rw-r--r--test/java/org/apache/fop/accessibility/fo/DOMResultUtil.java54
-rw-r--r--test/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverterTestCase.java223
-rw-r--r--test/java/org/apache/fop/accessibility/fo/fo2StructureTree.xsl (renamed from src/java/org/apache/fop/accessibility/reduceFOTree.xsl)47
-rw-r--r--test/java/org/apache/fop/accessibility/fo/table-footers.fo195
-rw-r--r--test/java/org/apache/fop/accessibility/fo/wrapCompleteDocumentInTableFooter.xsl66
-rw-r--r--test/java/org/apache/fop/fo/DelegatingFOEventHandlerTestCase.java531
-rw-r--r--test/java/org/apache/fop/fo/FODocumentParser.java161
-rw-r--r--test/java/org/apache/fop/fo/FONodeMocks.java88
-rw-r--r--test/java/org/apache/fop/fo/LoadingException.java34
-rw-r--r--test/java/org/apache/fop/fo/complete_document.fo176
-rw-r--r--test/java/org/apache/fop/fo/extract-events.xsl62
-rw-r--r--test/java/org/apache/fop/fo/flow/table/AbstractTableTest.java28
-rw-r--r--test/java/org/apache/fop/fo/flow/table/CollapsedConditionalBorderTestCase.java7
-rw-r--r--test/java/org/apache/fop/fo/flow/table/ErrorCheckTest.java11
-rw-r--r--test/java/org/apache/fop/fo/flow/table/IllegalRowSpanTestCase.java4
-rw-r--r--test/java/org/apache/fop/fo/flow/table/RowGroupBuilderTestCase.java4
-rw-r--r--test/java/org/apache/fop/fo/flow/table/TableColumnColumnNumberTestCase.java7
-rw-r--r--test/java/org/apache/fop/fo/flow/table/TooManyColumnsTestCase.java4
-rw-r--r--test/java/org/apache/fop/fo/flow/table/UnimplementedWarningNeutralizer.java38
-rw-r--r--test/java/org/apache/fop/fo/properties/AltTextHolderTestCase.java77
-rw-r--r--test/java/org/apache/fop/fo/properties/CommonAccessibilityHolderTestCase.java128
-rw-r--r--test/java/org/apache/fop/fo/properties/PropertyListMocks.java94
-rw-r--r--test/java/org/apache/fop/fo/properties/PropertyMocks.java80
-rw-r--r--test/java/org/apache/fop/fotreetest/FOTreeTestSuite.java6
-rw-r--r--test/java/org/apache/fop/fotreetest/FOTreeUnitTester.java96
-rw-r--r--test/java/org/apache/fop/intermediate/IFParserTestCase.java17
-rw-r--r--test/java/org/apache/fop/render/intermediate/IFStructureTreeBuilderTestCase.java169
-rw-r--r--test/java/org/apache/fop/render/intermediate/SAXEventRecorderTestCase.java131
-rw-r--r--test/java/org/apache/fop/util/LanguageTagsTestCase.java (renamed from test/java/org/apache/fop/util/XMLUtilTestCase.java)34
194 files changed, 6182 insertions, 1414 deletions
diff --git a/build.xml b/build.xml
index 4f0bd0173..9790aceac 100644
--- a/build.xml
+++ b/build.xml
@@ -548,6 +548,7 @@ list of possible build targets.
<!-- General classes -->
<patternset>
<include name="org/apache/fop/Version.class"/>
+ <include name="org/apache/fop/accessibility/StructureTreeElement.class"/>
<include name="org/apache/fop/apps/Fop.class"/>
<include name="org/apache/fop/apps/FOPException.class"/>
<include name="org/apache/fop/fo/Constants.class"/>
@@ -705,6 +706,7 @@ list of possible build targets.
<include name="**/*.xml"/>
<include name="**/*.fo"/>
<include name="**/*.afp"/>
+ <include name="**/*.xsl"/>
</fileset>
<fileset dir="${build.dir}/test-gensrc">
<include name="**/*.xml"/>
diff --git a/findbugs-exclude.xml b/findbugs-exclude.xml
index 5e179955f..e5aee4279 100644
--- a/findbugs-exclude.xml
+++ b/findbugs-exclude.xml
@@ -1,6 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<FindBugsFilter>
- <!-- The names of public methods will not be modified -->
+ <Match>
+ <Class name="org.apache.fop.render.intermediate.IFStructureTreeBuilder"/>
+ <Field name="delegate"/>
+ <Bug pattern="UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR"/>
+ </Match>
+ <Match>
+ <Class name="org.apache.fop.render.pdf.PDFLogicalStructureHandler"/>
+ <Field name="currentPage"/>
+ <Bug pattern="UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR"/>
+ </Match>
+ <Match>
+ <Class name="org.apache.fop.render.pdf.PDFLogicalStructureHandler"/>
+ <Field name="pageParentTreeArray"/>
+ <Bug pattern="UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR"/>
+ </Match>
+ <Match>
+ <Class name="org.apache.fop.render.pdf.PDFStructureTreeBuilder"/>
+ <Field name="logicalStructureHandler"/>
+ <Bug pattern="UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR"/>
+ </Match>
+ <Match>
+ <Class name="org.apache.fop.render.pdf.PDFStructureTreeBuilder"/>
+ <Field name="pdfFactory"/>
+ <Bug pattern="UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR"/>
+ </Match>
+ <Match>
+ <Class name="org.apache.fop.accessibility.fo.FO2StructureTreeConverter$1"/>
+ <Bug pattern="SIC_INNER_SHOULD_BE_STATIC_ANON"/>
+ </Match>
+ <Match>
+ <Class name="~org.apache.fop.accessibility.fo.FOEventRecorder.*"/>
+ <Bug pattern="SIC_INNER_SHOULD_BE_STATIC_ANON"/>
+ </Match>
<Match>
<Class name="org.apache.fop.afp.AFPDataObjectInfo"/>
<Method name="getUri"/>
@@ -4789,4 +4821,4 @@
<Bug pattern="REC_CATCH_EXCEPTION"/>
</Match>
<!-- /Automatically generated list of exclusions on 18 February 2011 -->
-</FindBugsFilter> \ No newline at end of file
+</FindBugsFilter>
diff --git a/src/documentation/intermediate-format-ng/fop-intermediate-format-ng.xsd b/src/documentation/intermediate-format-ng/fop-intermediate-format-ng.xsd
index b6fa00bd2..86dce1a3c 100644
--- a/src/documentation/intermediate-format-ng/fop-intermediate-format-ng.xsd
+++ b/src/documentation/intermediate-format-ng/fop-intermediate-format-ng.xsd
@@ -40,10 +40,17 @@
</xs:element>
<xs:element name="header">
<xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <!--xs:element ref="x:xmpmeta" xmlns:x="adobe:ns:meta/"/-->
- <xs:any namespace="##other" processContents="lax"/>
- </xs:choice>
+ <xs:sequence>
+ <xs:element name="locale" minOccurs="0" maxOccurs="1">
+ <xs:complexType>
+ <xs:attributeGroup ref="mf:foreignAtts"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <!--xs:element ref="x:xmpmeta" xmlns:x="adobe:ns:meta/"/-->
+ <xs:any namespace="##other" processContents="lax"/>
+ </xs:choice>
+ </xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="trailer">
diff --git a/src/java/org/apache/fop/accessibility/Accessibility.java b/src/java/org/apache/fop/accessibility/Accessibility.java
index d550b433a..c842cf43f 100644
--- a/src/java/org/apache/fop/accessibility/Accessibility.java
+++ b/src/java/org/apache/fop/accessibility/Accessibility.java
@@ -19,18 +19,6 @@
package org.apache.fop.accessibility;
-import javax.xml.transform.Source;
-import javax.xml.transform.Templates;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerConfigurationException;
-import javax.xml.transform.sax.SAXTransformerFactory;
-import javax.xml.transform.sax.TransformerHandler;
-import javax.xml.transform.stream.StreamSource;
-
-import org.xml.sax.helpers.DefaultHandler;
-
-import org.apache.fop.apps.FOPException;
-import org.apache.fop.apps.FOUserAgent;
/**
* Helper class for FOP's accessibility features.
@@ -40,48 +28,6 @@ public final class Accessibility {
/** Constant string for the rendering options key to enable accessibility features. */
public static final String ACCESSIBILITY = "accessibility";
- // TODO what if the default factory is not a SAXTransformerFactory?
- private static SAXTransformerFactory tfactory
- = (SAXTransformerFactory)SAXTransformerFactory.newInstance();
-
- private static Templates addPtrTemplates;
-
- private static Templates reduceFOTreeTemplates;
-
private Accessibility() { }
- /**
- * Decorates the given handler so the structure tree used for accessibility
- * features can be branched off the main content stream.
- * @param handler the handler to decorate
- * @param userAgent the user agent
- * @return the decorated handler
- * @throws FOPException if an error occurs setting up the decoration
- */
- public static DefaultHandler decorateDefaultHandler(DefaultHandler handler,
- FOUserAgent userAgent) throws FOPException {
- try {
- setupTemplates();
- TransformerHandler addPtr = tfactory.newTransformerHandler(addPtrTemplates);
- Transformer reduceFOTree = reduceFOTreeTemplates.newTransformer();
- return new AccessibilityPreprocessor(addPtr, reduceFOTree, userAgent, handler);
- } catch (TransformerConfigurationException e) {
- throw new FOPException(e);
- }
- }
-
- private static synchronized void setupTemplates() throws TransformerConfigurationException {
- if (addPtrTemplates == null) {
- addPtrTemplates = loadTemplates("addPtr.xsl");
- }
- if (reduceFOTreeTemplates == null) {
- reduceFOTreeTemplates = loadTemplates("reduceFOTree.xsl");
- }
- }
-
- private static Templates loadTemplates(String source) throws TransformerConfigurationException {
- Source src = new StreamSource(Accessibility.class.getResource(source).toExternalForm());
- return tfactory.newTemplates(src);
- }
-
}
diff --git a/src/java/org/apache/fop/accessibility/AccessibilityPreprocessor.java b/src/java/org/apache/fop/accessibility/AccessibilityPreprocessor.java
deleted file mode 100644
index 1958b74a8..000000000
--- a/src/java/org/apache/fop/accessibility/AccessibilityPreprocessor.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* $Id$ */
-
-package org.apache.fop.accessibility;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-import javax.xml.transform.Source;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.dom.DOMResult;
-import javax.xml.transform.sax.TransformerHandler;
-import javax.xml.transform.stream.StreamResult;
-import javax.xml.transform.stream.StreamSource;
-
-import org.w3c.dom.NodeList;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
-
-import org.apache.commons.io.output.ByteArrayOutputStream;
-
-import org.apache.fop.apps.FOUserAgent;
-import org.apache.fop.util.TransformerDefaultHandler;
-
-/**
- * This class prepares an XSL-FO document for accessibility. It adds a unique
- * identifier to every applicable FO, then creates the structure tree, before
- * handing the document over to the regular handler.
- */
-class AccessibilityPreprocessor extends TransformerDefaultHandler {
-
- private final ByteArrayOutputStream enrichedFOBuffer = new ByteArrayOutputStream();
-
- private final Transformer reduceFOTree;
-
- private final FOUserAgent userAgent;
-
- private final DefaultHandler fopHandler;
-
- public AccessibilityPreprocessor(TransformerHandler addPtr, Transformer reduceFOTree,
- FOUserAgent userAgent, DefaultHandler fopHandler) {
- super(addPtr);
- this.reduceFOTree = reduceFOTree;
- this.userAgent = userAgent;
- this.fopHandler = fopHandler;
- getTransformerHandler().setResult(new StreamResult(enrichedFOBuffer));
- }
-
- /** {@inheritDoc} */
- public void endDocument() throws SAXException {
- super.endDocument();
- // do the second transform to struct
- try {
- //TODO this must be optimized, no buffering (ex. SAX-based tee-proxy)
- byte[] enrichedFO = enrichedFOBuffer.toByteArray();
- Source src = new StreamSource(new ByteArrayInputStream(enrichedFO));
- DOMResult res = new DOMResult();
- reduceFOTree.transform(src, res);
- StructureTree structureTree = new StructureTree();
- NodeList pageSequences = res.getNode().getFirstChild().getChildNodes();
- for (int i = 0; i < pageSequences.getLength(); i++) {
- structureTree.addPageSequenceStructure(pageSequences.item(i).getChildNodes());
- }
- userAgent.setStructureTree(structureTree);
-
- SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
- saxParserFactory.setNamespaceAware(true);
- saxParserFactory.setValidating(false);
- SAXParser saxParser = saxParserFactory.newSAXParser();
- InputStream in = new ByteArrayInputStream(enrichedFO);
- saxParser.parse(in, fopHandler);
- } catch (Exception e) {
- throw new SAXException(e);
- }
- }
-
-}
diff --git a/src/java/org/apache/fop/accessibility/DummyStructureTreeEventHandler.java b/src/java/org/apache/fop/accessibility/DummyStructureTreeEventHandler.java
new file mode 100644
index 000000000..66eaece89
--- /dev/null
+++ b/src/java/org/apache/fop/accessibility/DummyStructureTreeEventHandler.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.accessibility;
+
+import java.util.Locale;
+
+import org.xml.sax.Attributes;
+
+/**
+ * This implementation ignores all structure tree events.
+ */
+public final class DummyStructureTreeEventHandler implements StructureTreeEventHandler {
+
+ /** The singleton instance of this class. */
+ public static final StructureTreeEventHandler INSTANCE = new DummyStructureTreeEventHandler();
+
+ private DummyStructureTreeEventHandler() { }
+
+ /** {@inheritDoc} */
+ public void startPageSequence(Locale locale) {
+ }
+
+ /** {@inheritDoc} */
+ public void endPageSequence() {
+ }
+
+ /** {@inheritDoc} */
+ public StructureTreeElement startNode(String name, Attributes attributes) {
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ public void endNode(String name) {
+ }
+
+ /** {@inheritDoc} */
+ public StructureTreeElement startImageNode(String name, Attributes attributes) {
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ public StructureTreeElement startReferencedNode(String name, Attributes attributes) {
+ return null;
+ }
+
+}
diff --git a/src/java/org/apache/fop/accessibility/StructureTree.java b/src/java/org/apache/fop/accessibility/StructureTree.java
deleted file mode 100644
index a0fdaac21..000000000
--- a/src/java/org/apache/fop/accessibility/StructureTree.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* $Id$ */
-
-package org.apache.fop.accessibility;
-
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-/**
- * A reduced version of the document's FO tree, containing only its logical
- * structure. Used by accessible output formats.
- */
-public final class StructureTree {
-
- private final List pageSequenceStructures = new ArrayList();
-
- /**
- * Package-private default constructor.
- */
- StructureTree() { }
-
- private static boolean flowOrStaticContentNodes(NodeList nodes) {
- for (int i = 0; i < nodes.getLength(); i++) {
- Node node = nodes.item(i);
- if (node.getNodeType() != Node.ELEMENT_NODE) {
- return false;
- }
- String name = node.getLocalName();
- if (!(name.equals("flow") || name.equals("static-content"))) {
- return false;
- }
- }
- return true;
- }
-
- void addPageSequenceStructure(NodeList structureTree) {
- assert flowOrStaticContentNodes(structureTree);
- pageSequenceStructures.add(structureTree);
- }
-
- /**
- * Returns the list of nodes that are the children of the given page sequence.
- *
- * @param index index of the page sequence, 0-based
- * @return its children nodes
- */
- public NodeList getPageSequence(int index) {
- return (NodeList) pageSequenceStructures.get(index);
- }
-
- /**
- * Returns an XML-like representation of the structure trees.
- * <p>
- * <strong>Note:</strong> use only for debugging purpose, as this method
- * performs non-trivial operations.
- * </p>
- * @return a string representation of this object
- */
- public String toString() {
- try {
- Transformer t = TransformerFactory.newInstance().newTransformer();
- Writer str = new StringWriter();
- for (Iterator iter = pageSequenceStructures.iterator(); iter.hasNext();) {
- NodeList nodes = (NodeList) iter.next();
- for (int i = 0, c = nodes.getLength(); i < c; i++) {
- t.transform(new DOMSource(nodes.item(i)), new StreamResult(str));
- }
- }
- return str.toString();
- } catch (Exception e) {
- return e.toString();
- }
- }
-
-}
diff --git a/src/java/org/apache/fop/accessibility/StructureTree2SAXEventAdapter.java b/src/java/org/apache/fop/accessibility/StructureTree2SAXEventAdapter.java
new file mode 100644
index 000000000..79c589f9b
--- /dev/null
+++ b/src/java/org/apache/fop/accessibility/StructureTree2SAXEventAdapter.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.accessibility;
+
+import java.util.Locale;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import org.apache.fop.fo.FOElementMapping;
+import org.apache.fop.fo.extensions.ExtensionElementMapping;
+import org.apache.fop.fo.extensions.InternalElementMapping;
+import org.apache.fop.render.intermediate.IFConstants;
+
+/**
+ * Converts structure tree events to SAX events.
+ */
+public final class StructureTree2SAXEventAdapter implements StructureTreeEventHandler {
+
+ private final ContentHandler contentHandler;
+
+ private StructureTree2SAXEventAdapter(ContentHandler currentContentHandler) {
+ this.contentHandler = currentContentHandler;
+ }
+
+ /**
+ * Factory method that creates a new instance.
+ * @param contentHandler The handler that receives SAX events
+ * @return -
+ */
+ public static StructureTreeEventHandler newInstance(ContentHandler contentHandler) {
+ return new StructureTree2SAXEventAdapter(contentHandler);
+ }
+
+ /** {@inheritDoc} */
+ public void startPageSequence(Locale locale) {
+ try {
+
+ contentHandler.startPrefixMapping(
+ InternalElementMapping.STANDARD_PREFIX, InternalElementMapping.URI);
+ contentHandler.startPrefixMapping(
+ ExtensionElementMapping.STANDARD_PREFIX, ExtensionElementMapping.URI);
+ contentHandler.startElement(IFConstants.NAMESPACE,
+ IFConstants.EL_STRUCTURE_TREE, IFConstants.EL_STRUCTURE_TREE,
+ new AttributesImpl());
+ } catch (SAXException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void endPageSequence() {
+ try {
+ contentHandler.endElement(IFConstants.NAMESPACE, IFConstants.EL_STRUCTURE_TREE,
+ IFConstants.EL_STRUCTURE_TREE);
+ contentHandler.endPrefixMapping(
+ ExtensionElementMapping.STANDARD_PREFIX);
+ contentHandler.endPrefixMapping(
+ InternalElementMapping.STANDARD_PREFIX);
+
+ } catch (SAXException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public StructureTreeElement startNode(String name, Attributes attributes) {
+ try {
+ if (name.equals("#PCDATA")) {
+ name = "marked-content";
+ contentHandler.startElement(IFConstants.NAMESPACE, name,
+ name, attributes);
+ } else {
+ contentHandler.startElement(FOElementMapping.URI, name,
+ FOElementMapping.STANDARD_PREFIX + ":" + name,
+ attributes);
+ }
+ return null;
+ } catch (SAXException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void endNode(String name) {
+ try {
+ contentHandler.endElement(FOElementMapping.URI, name,
+ FOElementMapping.STANDARD_PREFIX + ":" + name);
+ } catch (SAXException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public StructureTreeElement startImageNode(String name, Attributes attributes) {
+ return startNode(name, attributes);
+ }
+
+ /** {@inheritDoc} */
+ public StructureTreeElement startReferencedNode(String name, Attributes attributes) {
+ return startNode(name, attributes);
+ }
+
+}
diff --git a/src/java/org/apache/fop/accessibility/StructureTreeBuilder.java b/src/java/org/apache/fop/accessibility/StructureTreeBuilder.java
deleted file mode 100644
index 036502e99..000000000
--- a/src/java/org/apache/fop/accessibility/StructureTreeBuilder.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* $Id$ */
-
-package org.apache.fop.accessibility;
-
-import javax.xml.transform.TransformerConfigurationException;
-import javax.xml.transform.dom.DOMResult;
-import javax.xml.transform.sax.SAXTransformerFactory;
-import javax.xml.transform.sax.TransformerHandler;
-
-import org.xml.sax.ContentHandler;
-import org.xml.sax.SAXException;
-
-import org.apache.fop.util.DelegatingContentHandler;
-
-/**
- * Helper class that re-builds a structure tree from what is stored in an
- * intermediate XML file (IF XML or Area Tree XML).
- */
-public final class StructureTreeBuilder {
-
- private final SAXTransformerFactory factory;
-
- private final StructureTree structureTree = new StructureTree();
-
- /**
- * Creates a new instance.
- *
- * @param factory a factory internally used to build the structures of page
- * sequences
- */
- public StructureTreeBuilder(SAXTransformerFactory factory) {
- this.factory = factory;
- }
-
- /**
- * Returns the structure tree that will result from the parsing.
- *
- * @return the structure tree built by this object
- */
- public StructureTree getStructureTree() {
- return structureTree;
- }
-
- /**
- * Returns a ContenHandler for parsing the structure of a new page sequence.
- * It is assumed that page sequences are being parsed in the document order.
- *
- * @return a handler for parsing the &lt;structure-tree&gt; or
- * &lt;structureTree&gt; element and its descendants
- * @throws SAXException if there is an error when creating the handler
- */
- public ContentHandler getHandlerForNextPageSequence() throws SAXException {
- TransformerHandler structureTreeBuilder;
- try {
- structureTreeBuilder = factory.newTransformerHandler();
- } catch (TransformerConfigurationException e) {
- throw new SAXException(e);
- }
- final DOMResult domResult = new DOMResult();
- structureTreeBuilder.setResult(domResult);
- return new DelegatingContentHandler(structureTreeBuilder) {
-
- public void characters(char[] ch, int start, int length) throws SAXException {
- /*
- * There's no text node in the structure tree. This is just
- * whitespace => ignore
- */
- }
-
- public void endDocument() throws SAXException {
- super.endDocument();
- structureTree.addPageSequenceStructure(domResult.getNode().getFirstChild()
- .getChildNodes());
- }
- };
- }
-
-}
diff --git a/src/java/org/apache/fop/accessibility/StructureTreeElement.java b/src/java/org/apache/fop/accessibility/StructureTreeElement.java
new file mode 100644
index 000000000..ebed2c8ff
--- /dev/null
+++ b/src/java/org/apache/fop/accessibility/StructureTreeElement.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.accessibility;
+
+/**
+ * An object that represents the structure of the document in the output format.
+ * In PDF, an implementation of this interface will typically result into the
+ * creation of a structure element dictionary (a dictionary of type StructElem).
+ */
+public interface StructureTreeElement {
+}
diff --git a/src/java/org/apache/fop/accessibility/StructureTreeEventHandler.java b/src/java/org/apache/fop/accessibility/StructureTreeEventHandler.java
new file mode 100644
index 000000000..4b94d61f1
--- /dev/null
+++ b/src/java/org/apache/fop/accessibility/StructureTreeEventHandler.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.accessibility;
+
+import java.util.Locale;
+
+import org.xml.sax.Attributes;
+
+/**
+ * Receive notifications relating to the structure tree of an FO document.
+ * A structure tree is a reduced version of the document's FO tree, containing only the logical
+ * structure that is used by accessible output formats.
+ */
+public interface StructureTreeEventHandler {
+
+ /**
+ * Starts a page sequence structure tree node.
+ *
+ * @param locale The locale of the page sequence
+ */
+ void startPageSequence(Locale locale);
+
+ /**
+ * Starts a structure tree node.
+ *
+ * @param name the name of the structure tree node
+ * @param attributes the node properties
+ * @return the corresponding structure tree element
+ */
+ StructureTreeElement startNode(String name, Attributes attributes);
+
+ /**
+ * Ends a structure tree node.
+ *
+ * @param name the name of the structure tree node
+ */
+ void endNode(String name);
+
+ /**
+ * Starts an image node.
+ *
+ * @param name the name of the structure tree node
+ * @param attributes the node properties
+ * @return the corresponding structure tree element
+ */
+ StructureTreeElement startImageNode(String name, Attributes attributes);
+
+ /**
+ * Starts a node that can be referenced by other nodes. This is usually a
+ * node that can have Marked Content References as children.
+ *
+ * @param name the name of the structure tree node
+ * @param attributes the node properties
+ * @return the corresponding structure tree element
+ */
+ StructureTreeElement startReferencedNode(String name, Attributes attributes);
+
+ /**
+ * Ends a page sequence structure tree node.
+ */
+ void endPageSequence();
+}
diff --git a/src/java/org/apache/fop/accessibility/addPtr.xsl b/src/java/org/apache/fop/accessibility/addPtr.xsl
deleted file mode 100644
index b3984d426..000000000
--- a/src/java/org/apache/fop/accessibility/addPtr.xsl
+++ /dev/null
@@ -1,88 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- $Id$ -->
-<xsl:stylesheet version="1.0"
- xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
- xmlns:fo="http://www.w3.org/1999/XSL/Format"
- xmlns:foi="http://xmlgraphics.apache.org/fop/internal">
-
- <xsl:template name="addPtr">
- <xsl:copy>
- <xsl:apply-templates select="@*"/>
- <xsl:attribute name="foi:ptr">
- <xsl:value-of select="generate-id()"/>
- </xsl:attribute>
- <xsl:apply-templates/>
- </xsl:copy>
- </xsl:template>
-
- <!-- Block-level Formatting Objects -->
- <xsl:template match="fo:block|fo:block-container">
- <xsl:call-template name="addPtr"/>
- </xsl:template>
-
- <!-- Inline-level Formatting Objects -->
- <xsl:template match="fo:character|fo:inline|fo:inline-container">
- <xsl:call-template name="addPtr"/>
- </xsl:template>
-
- <xsl:template match="fo:external-graphic|fo:instream-foreign-object">
- <xsl:call-template name="addPtr"/>
- </xsl:template>
-
- <xsl:template match="fo:page-number|fo:page-number-citation|fo:page-number-citation-last">
- <xsl:call-template name="addPtr"/>
- </xsl:template>
-
- <!-- Formatting Objects for Tables -->
- <xsl:template match="fo:table-and-caption|fo:table-caption|fo:table">
- <xsl:call-template name="addPtr"/>
- </xsl:template>
-
- <xsl:template match="fo:table-header|fo:table-footer|fo:table-body|fo:table-row|fo:table-cell">
- <xsl:call-template name="addPtr"/>
- </xsl:template>
-
- <!-- Formatting Objects for Lists -->
- <xsl:template match="fo:list-block|fo:list-item|fo:list-item-label|fo:list-item-body">
- <xsl:call-template name="addPtr"/>
- </xsl:template>
-
- <!-- Dynamic Effects: Link and Multi Formatting Objects -->
- <xsl:template match="fo:basic-link">
- <xsl:call-template name="addPtr"/>
- </xsl:template>
-
- <!-- Out-of-Line Formatting Objects -->
- <xsl:template match="fo:float|fo:footnote|fo:footnote-body">
- <xsl:call-template name="addPtr"/>
- </xsl:template>
-
- <!-- Other Formatting Objects -->
- <xsl:template match="fo:wrapper|fo:marker">
- <xsl:call-template name="addPtr"/>
- </xsl:template>
-
-
- <xsl:template match="@*|node()">
- <xsl:copy>
- <xsl:apply-templates select="@*|node()"/>
- </xsl:copy>
- </xsl:template>
-
-</xsl:stylesheet>
diff --git a/src/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java b/src/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java
new file mode 100644
index 000000000..47c227e9a
--- /dev/null
+++ b/src/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java
@@ -0,0 +1,491 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.accessibility.fo;
+
+import java.util.Stack;
+
+import org.xml.sax.SAXException;
+
+import org.apache.fop.accessibility.StructureTreeEventHandler;
+import org.apache.fop.fo.DelegatingFOEventHandler;
+import org.apache.fop.fo.FOEventHandler;
+import org.apache.fop.fo.FOText;
+import org.apache.fop.fo.extensions.ExternalDocument;
+import org.apache.fop.fo.flow.BasicLink;
+import org.apache.fop.fo.flow.Block;
+import org.apache.fop.fo.flow.BlockContainer;
+import org.apache.fop.fo.flow.Character;
+import org.apache.fop.fo.flow.ExternalGraphic;
+import org.apache.fop.fo.flow.Footnote;
+import org.apache.fop.fo.flow.FootnoteBody;
+import org.apache.fop.fo.flow.Inline;
+import org.apache.fop.fo.flow.InstreamForeignObject;
+import org.apache.fop.fo.flow.Leader;
+import org.apache.fop.fo.flow.ListBlock;
+import org.apache.fop.fo.flow.ListItem;
+import org.apache.fop.fo.flow.ListItemBody;
+import org.apache.fop.fo.flow.ListItemLabel;
+import org.apache.fop.fo.flow.PageNumber;
+import org.apache.fop.fo.flow.PageNumberCitation;
+import org.apache.fop.fo.flow.PageNumberCitationLast;
+import org.apache.fop.fo.flow.Wrapper;
+import org.apache.fop.fo.flow.table.Table;
+import org.apache.fop.fo.flow.table.TableBody;
+import org.apache.fop.fo.flow.table.TableCell;
+import org.apache.fop.fo.flow.table.TableColumn;
+import org.apache.fop.fo.flow.table.TableFooter;
+import org.apache.fop.fo.flow.table.TableHeader;
+import org.apache.fop.fo.flow.table.TableRow;
+import org.apache.fop.fo.pagination.Flow;
+import org.apache.fop.fo.pagination.PageSequence;
+import org.apache.fop.fo.pagination.Root;
+import org.apache.fop.fo.pagination.StaticContent;
+
+/**
+ * Allows to create the structure tree of an FO document, by converting FO
+ * events into appropriate structure tree events.
+ */
+public class FO2StructureTreeConverter extends DelegatingFOEventHandler {
+
+ /** The top of the {@link converters} stack. */
+ private FOEventHandler converter;
+
+ private final Stack<FOEventHandler> converters = new Stack<FOEventHandler>();
+
+ private final Stack<FOEventRecorder> tableFooterRecorders = new Stack<FOEventRecorder>();
+
+ private final FOEventHandler structureTreeEventTrigger;
+
+ /** The descendants of some elements like fo:leader must be ignored. */
+ private final FOEventHandler eventSwallower = new FOEventHandler() {
+ };
+
+ /**
+ * Creates a new instance.
+ *
+ * @param structureTreeEventHandler the object that will hold the structure tree
+ * @param delegate the FO event handler that must be wrapped by this instance
+ */
+ public FO2StructureTreeConverter(StructureTreeEventHandler structureTreeEventHandler,
+ FOEventHandler delegate) {
+ super(delegate);
+ this.structureTreeEventTrigger = new StructureTreeEventTrigger(structureTreeEventHandler);
+ this.converter = structureTreeEventTrigger;
+ }
+
+ @Override
+ public void startDocument() throws SAXException {
+ converter.startDocument();
+ super.startDocument();
+ }
+
+ @Override
+ public void endDocument() throws SAXException {
+ converter.endDocument();
+ super.endDocument();
+ }
+
+ @Override
+ public void startRoot(Root root) {
+ converter.startRoot(root);
+ super.startRoot(root);
+ }
+
+ @Override
+ public void endRoot(Root root) {
+ converter.endRoot(root);
+ super.endRoot(root);
+ }
+
+ @Override
+ public void startPageSequence(PageSequence pageSeq) {
+ converter.startPageSequence(pageSeq);
+ super.startPageSequence(pageSeq);
+ }
+
+ @Override
+ public void endPageSequence(PageSequence pageSeq) {
+ converter.endPageSequence(pageSeq);
+ super.endPageSequence(pageSeq);
+ }
+
+ @Override
+ public void startPageNumber(PageNumber pagenum) {
+ converter.startPageNumber(pagenum);
+ super.startPageNumber(pagenum);
+ }
+
+ @Override
+ public void endPageNumber(PageNumber pagenum) {
+ converter.endPageNumber(pagenum);
+ super.endPageNumber(pagenum);
+ }
+
+ @Override
+ public void startPageNumberCitation(PageNumberCitation pageCite) {
+ converter.startPageNumberCitation(pageCite);
+ super.startPageNumberCitation(pageCite);
+ }
+
+ @Override
+ public void endPageNumberCitation(PageNumberCitation pageCite) {
+ converter.endPageNumberCitation(pageCite);
+ super.endPageNumberCitation(pageCite);
+ }
+
+ @Override
+ public void startPageNumberCitationLast(PageNumberCitationLast pageLast) {
+ converter.startPageNumberCitationLast(pageLast);
+ super.startPageNumberCitationLast(pageLast);
+ }
+
+ @Override
+ public void endPageNumberCitationLast(PageNumberCitationLast pageLast) {
+ converter.endPageNumberCitationLast(pageLast);
+ super.endPageNumberCitationLast(pageLast);
+ }
+
+ @Override
+ public void startFlow(Flow fl) {
+ converter.startFlow(fl);
+ super.startFlow(fl);
+ }
+
+ @Override
+ public void endFlow(Flow fl) {
+ converter.endFlow(fl);
+ super.endFlow(fl);
+ }
+
+ @Override
+ public void startBlock(Block bl) {
+ converter.startBlock(bl);
+ super.startBlock(bl);
+ }
+
+ @Override
+ public void endBlock(Block bl) {
+ converter.endBlock(bl);
+ super.endBlock(bl);
+ }
+
+ @Override
+ public void startBlockContainer(BlockContainer blc) {
+ converter.startBlockContainer(blc);
+ super.startBlockContainer(blc);
+ }
+
+ @Override
+ public void endBlockContainer(BlockContainer blc) {
+ converter.endBlockContainer(blc);
+ super.endBlockContainer(blc);
+ }
+
+ @Override
+ public void startInline(Inline inl) {
+ converter.startInline(inl);
+ super.startInline(inl);
+ }
+
+ @Override
+ public void endInline(Inline inl) {
+ converter.endInline(inl);
+ super.endInline(inl);
+ }
+
+ @Override
+ public void startTable(Table tbl) {
+ converter.startTable(tbl);
+ tableFooterRecorders.push(null);
+ super.startTable(tbl);
+ }
+
+ @Override
+ public void endTable(Table tbl) {
+ FOEventRecorder tableFooterRecorder = tableFooterRecorders.pop();
+ if (tableFooterRecorder != null) {
+ tableFooterRecorder.replay(converter);
+ }
+ converter.endTable(tbl);
+ super.endTable(tbl);
+ }
+
+ @Override
+ public void startColumn(TableColumn tc) {
+ converter.startColumn(tc);
+ super.startColumn(tc);
+ }
+
+ @Override
+ public void endColumn(TableColumn tc) {
+ converter.endColumn(tc);
+ super.endColumn(tc);
+ }
+
+ @Override
+ public void startHeader(TableHeader header) {
+ converter.startHeader(header);
+ super.startHeader(header);
+ }
+
+ @Override
+ public void endHeader(TableHeader header) {
+ converter.endHeader(header);
+ super.endHeader(header);
+ }
+
+ @Override
+ public void startFooter(TableFooter footer) {
+ converters.push(converter);
+ converter = new FOEventRecorder();
+ converter.startFooter(footer);
+ super.startFooter(footer);
+ }
+
+ @Override
+ public void endFooter(TableFooter footer) {
+ converter.endFooter(footer);
+ /* Replace the dummy table footer with the real one. */
+ tableFooterRecorders.pop();
+ tableFooterRecorders.push((FOEventRecorder) converter);
+ converter = converters.pop();
+ super.endFooter(footer);
+ }
+
+ @Override
+ public void startBody(TableBody body) {
+ converter.startBody(body);
+ super.startBody(body);
+ }
+
+ @Override
+ public void endBody(TableBody body) {
+ converter.endBody(body);
+ super.endBody(body);
+ }
+
+ @Override
+ public void startRow(TableRow tr) {
+ converter.startRow(tr);
+ super.startRow(tr);
+ }
+
+ @Override
+ public void endRow(TableRow tr) {
+ converter.endRow(tr);
+ super.endRow(tr);
+ }
+
+ @Override
+ public void startCell(TableCell tc) {
+ converter.startCell(tc);
+ super.startCell(tc);
+ }
+
+ @Override
+ public void endCell(TableCell tc) {
+ converter.endCell(tc);
+ super.endCell(tc);
+ }
+
+ @Override
+ public void startList(ListBlock lb) {
+ converter.startList(lb);
+ super.startList(lb);
+ }
+
+ @Override
+ public void endList(ListBlock lb) {
+ converter.endList(lb);
+ super.endList(lb);
+ }
+
+ @Override
+ public void startListItem(ListItem li) {
+ converter.startListItem(li);
+ super.startListItem(li);
+ }
+
+ @Override
+ public void endListItem(ListItem li) {
+ converter.endListItem(li);
+ super.endListItem(li);
+ }
+
+ @Override
+ public void startListLabel(ListItemLabel listItemLabel) {
+ converter.startListLabel(listItemLabel);
+ super.startListLabel(listItemLabel);
+ }
+
+ @Override
+ public void endListLabel(ListItemLabel listItemLabel) {
+ converter.endListLabel(listItemLabel);
+ super.endListLabel(listItemLabel);
+ }
+
+ @Override
+ public void startListBody(ListItemBody listItemBody) {
+ converter.startListBody(listItemBody);
+ super.startListBody(listItemBody);
+ }
+
+ @Override
+ public void endListBody(ListItemBody listItemBody) {
+ converter.endListBody(listItemBody);
+ super.endListBody(listItemBody);
+ }
+
+ @Override
+ public void startStatic(StaticContent staticContent) {
+ converter.startStatic(staticContent);
+ super.startStatic(staticContent);
+ }
+
+ @Override
+ public void endStatic(StaticContent statisContent) {
+ converter.endStatic(statisContent);
+ super.endStatic(statisContent);
+ }
+
+ @Override
+ public void startMarkup() {
+ converter.startMarkup();
+ super.startMarkup();
+ }
+
+ @Override
+ public void endMarkup() {
+ converter.endMarkup();
+ super.endMarkup();
+ }
+
+ @Override
+ public void startLink(BasicLink basicLink) {
+ converter.startLink(basicLink);
+ super.startLink(basicLink);
+ }
+
+ @Override
+ public void endLink(BasicLink basicLink) {
+ converter.endLink(basicLink);
+ super.endLink(basicLink);
+ }
+
+ @Override
+ public void image(ExternalGraphic eg) {
+ converter.image(eg);
+ super.image(eg);
+ }
+
+ @Override
+ public void pageRef() {
+ converter.pageRef();
+ super.pageRef();
+ }
+
+ @Override
+ public void startInstreamForeignObject(InstreamForeignObject ifo) {
+ converter.startInstreamForeignObject(ifo);
+ super.startInstreamForeignObject(ifo);
+ }
+
+ @Override
+ public void endInstreamForeignObject(InstreamForeignObject ifo) {
+ converter.endInstreamForeignObject(ifo);
+ super.endInstreamForeignObject(ifo);
+ }
+
+ @Override
+ public void startFootnote(Footnote footnote) {
+ converter.startFootnote(footnote);
+ super.startFootnote(footnote);
+ }
+
+ @Override
+ public void endFootnote(Footnote footnote) {
+ converter.endFootnote(footnote);
+ super.endFootnote(footnote);
+ }
+
+ @Override
+ public void startFootnoteBody(FootnoteBody body) {
+ converter.startFootnoteBody(body);
+ super.startFootnoteBody(body);
+ }
+
+ @Override
+ public void endFootnoteBody(FootnoteBody body) {
+ converter.endFootnoteBody(body);
+ super.endFootnoteBody(body);
+ }
+
+ @Override
+ public void startLeader(Leader l) {
+ converters.push(converter);
+ converter = eventSwallower;
+ converter.startLeader(l);
+ super.startLeader(l);
+ }
+
+ @Override
+ public void endLeader(Leader l) {
+ converter.endLeader(l);
+ converter = converters.pop();
+ super.endLeader(l);
+ }
+
+ @Override
+ public void startWrapper(Wrapper wrapper) {
+ converter.startWrapper(wrapper);
+ super.startWrapper(wrapper);
+ }
+
+ @Override
+ public void endWrapper(Wrapper wrapper) {
+ converter.endWrapper(wrapper);
+ super.endWrapper(wrapper);
+ }
+
+ @Override
+ public void character(Character c) {
+ converter.character(c);
+ super.character(c);
+ }
+
+ @Override
+ public void characters(FOText foText) {
+ converter.characters(foText);
+ super.characters(foText);
+ }
+
+ @Override
+ public void startExternalDocument(ExternalDocument document) {
+ converter.startExternalDocument(document);
+ super.startExternalDocument(document);
+ }
+
+ @Override
+ public void endExternalDocument(ExternalDocument document) {
+ converter.endExternalDocument(document);
+ super.endExternalDocument(document);
+ }
+
+}
diff --git a/src/java/org/apache/fop/accessibility/fo/FOEventRecorder.java b/src/java/org/apache/fop/accessibility/fo/FOEventRecorder.java
new file mode 100644
index 000000000..b2b18046d
--- /dev/null
+++ b/src/java/org/apache/fop/accessibility/fo/FOEventRecorder.java
@@ -0,0 +1,508 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.accessibility.fo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.fop.fo.FOEventHandler;
+import org.apache.fop.fo.FOText;
+import org.apache.fop.fo.flow.BasicLink;
+import org.apache.fop.fo.flow.Block;
+import org.apache.fop.fo.flow.BlockContainer;
+import org.apache.fop.fo.flow.Character;
+import org.apache.fop.fo.flow.ExternalGraphic;
+import org.apache.fop.fo.flow.Footnote;
+import org.apache.fop.fo.flow.FootnoteBody;
+import org.apache.fop.fo.flow.Inline;
+import org.apache.fop.fo.flow.InstreamForeignObject;
+import org.apache.fop.fo.flow.Leader;
+import org.apache.fop.fo.flow.ListBlock;
+import org.apache.fop.fo.flow.ListItem;
+import org.apache.fop.fo.flow.ListItemBody;
+import org.apache.fop.fo.flow.ListItemLabel;
+import org.apache.fop.fo.flow.PageNumber;
+import org.apache.fop.fo.flow.PageNumberCitation;
+import org.apache.fop.fo.flow.PageNumberCitationLast;
+import org.apache.fop.fo.flow.Wrapper;
+import org.apache.fop.fo.flow.table.Table;
+import org.apache.fop.fo.flow.table.TableBody;
+import org.apache.fop.fo.flow.table.TableCell;
+import org.apache.fop.fo.flow.table.TableColumn;
+import org.apache.fop.fo.flow.table.TableFooter;
+import org.apache.fop.fo.flow.table.TableHeader;
+import org.apache.fop.fo.flow.table.TableRow;
+
+final class FOEventRecorder extends FOEventHandler {
+
+ private interface Event {
+ void replay(FOEventHandler target);
+ }
+
+ private final List<Event> events = new ArrayList<Event>();
+
+ public void replay(FOEventHandler target) {
+ for (Event event : events) {
+ event.replay(target);
+ }
+ }
+
+ @Override
+ public void startPageNumber(final PageNumber pagenum) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.startPageNumber(pagenum);
+ }
+ });
+ }
+
+ @Override
+ public void endPageNumber(final PageNumber pagenum) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.endPageNumber(pagenum);
+ }
+ });
+ }
+
+ @Override
+ public void startPageNumberCitation(final PageNumberCitation pageCite) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.startPageNumberCitation(pageCite);
+ }
+ });
+ }
+
+ @Override
+ public void endPageNumberCitation(final PageNumberCitation pageCite) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.endPageNumberCitation(pageCite);
+ }
+ });
+ }
+
+ @Override
+ public void startPageNumberCitationLast(final PageNumberCitationLast pageLast) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.startPageNumberCitationLast(pageLast);
+ }
+ });
+ }
+
+ @Override
+ public void endPageNumberCitationLast(final PageNumberCitationLast pageLast) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.endPageNumberCitationLast(pageLast);
+ }
+ });
+ }
+
+ @Override
+ public void startBlock(final Block bl) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.startBlock(bl);
+ }
+ });
+ }
+
+ @Override
+ public void endBlock(final Block bl) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.endBlock(bl);
+ }
+ });
+ }
+
+ @Override
+ public void startBlockContainer(final BlockContainer blc) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.startBlockContainer(blc);
+ }
+ });
+ }
+
+ @Override
+ public void endBlockContainer(final BlockContainer blc) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.endBlockContainer(blc);
+ }
+ });
+ }
+
+ @Override
+ public void startInline(final Inline inl) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.startInline(inl);
+ }
+ });
+ }
+
+ @Override
+ public void endInline(final Inline inl) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.endInline(inl);
+ }
+ });
+ }
+
+ @Override
+ public void startTable(final Table tbl) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.startTable(tbl);
+ }
+ });
+ }
+
+ @Override
+ public void endTable(final Table tbl) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.endTable(tbl);
+ }
+ });
+ }
+
+ @Override
+ public void startColumn(final TableColumn tc) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.startColumn(tc);
+ }
+ });
+ }
+
+ @Override
+ public void endColumn(final TableColumn tc) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.endColumn(tc);
+ }
+ });
+ }
+
+ @Override
+ public void startHeader(final TableHeader header) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.startHeader(header);
+ }
+ });
+ }
+
+ @Override
+ public void endHeader(final TableHeader header) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.endHeader(header);
+ }
+ });
+ }
+
+ @Override
+ public void startFooter(final TableFooter footer) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.startFooter(footer);
+ }
+ });
+ }
+
+ @Override
+ public void endFooter(final TableFooter footer) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.endFooter(footer);
+ }
+ });
+ }
+
+ @Override
+ public void startBody(final TableBody body) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.startBody(body);
+ }
+ });
+ }
+
+ @Override
+ public void endBody(final TableBody body) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.endBody(body);
+ }
+ });
+ }
+
+ @Override
+ public void startRow(final TableRow tr) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.startRow(tr);
+ }
+ });
+ }
+
+ @Override
+ public void endRow(final TableRow tr) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.endRow(tr);
+ }
+ });
+ }
+
+ @Override
+ public void startCell(final TableCell tc) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.startCell(tc);
+ }
+ });
+ }
+
+ @Override
+ public void endCell(final TableCell tc) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.endCell(tc);
+ }
+ });
+ }
+
+ @Override
+ public void startList(final ListBlock lb) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.startList(lb);
+ }
+ });
+ }
+
+ @Override
+ public void endList(final ListBlock lb) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.endList(lb);
+ }
+ });
+ }
+
+ @Override
+ public void startListItem(final ListItem li) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.startListItem(li);
+ }
+ });
+ }
+
+ @Override
+ public void endListItem(final ListItem li) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.endListItem(li);
+ }
+ });
+ }
+
+ @Override
+ public void startListLabel(final ListItemLabel listItemLabel) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.startListLabel(listItemLabel);
+ }
+ });
+ }
+
+ @Override
+ public void endListLabel(final ListItemLabel listItemLabel) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.endListLabel(listItemLabel);
+ }
+ });
+ }
+
+ @Override
+ public void startListBody(final ListItemBody listItemBody) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.startListBody(listItemBody);
+ }
+ });
+ }
+
+ @Override
+ public void endListBody(final ListItemBody listItemBody) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.endListBody(listItemBody);
+ }
+ });
+ }
+
+ @Override
+ public void startLink(final BasicLink basicLink) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.startLink(basicLink);
+ }
+ });
+ }
+
+ @Override
+ public void endLink(final BasicLink basicLink) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.endLink(basicLink);
+ }
+ });
+ }
+
+ @Override
+ public void image(final ExternalGraphic eg) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.image(eg);
+ }
+ });
+ }
+
+ @Override
+ public void startInstreamForeignObject(final InstreamForeignObject ifo) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.startInstreamForeignObject(ifo);
+ }
+ });
+ }
+
+ @Override
+ public void endInstreamForeignObject(final InstreamForeignObject ifo) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.endInstreamForeignObject(ifo);
+ }
+ });
+ }
+
+ @Override
+ public void startFootnote(final Footnote footnote) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.startFootnote(footnote);
+ }
+ });
+ }
+
+ @Override
+ public void endFootnote(final Footnote footnote) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.endFootnote(footnote);
+ }
+ });
+ }
+
+ @Override
+ public void startFootnoteBody(final FootnoteBody body) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.startFootnoteBody(body);
+ }
+ });
+ }
+
+ @Override
+ public void endFootnoteBody(final FootnoteBody body) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.endFootnoteBody(body);
+ }
+ });
+ }
+
+ @Override
+ public void startLeader(final Leader l) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.startLeader(l);
+ }
+ });
+ }
+
+ @Override
+ public void endLeader(final Leader l) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.endLeader(l);
+ }
+ });
+ }
+
+ @Override
+ public void startWrapper(final Wrapper wrapper) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.startWrapper(wrapper);
+ }
+ });
+ }
+
+ @Override
+ public void endWrapper(final Wrapper wrapper) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.endWrapper(wrapper);
+ }
+ });
+ }
+
+ @Override
+ public void character(final Character c) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.character(c);
+ }
+ });
+ }
+
+ @Override
+ public void characters(final FOText foText) {
+ events.add(new Event() {
+ public void replay(FOEventHandler target) {
+ target.characters(foText);
+ }
+ });
+ }
+
+}
diff --git a/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java b/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java
new file mode 100644
index 000000000..957f40870
--- /dev/null
+++ b/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java
@@ -0,0 +1,410 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.accessibility.fo;
+
+import java.util.Locale;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import org.apache.fop.accessibility.StructureTreeElement;
+import org.apache.fop.accessibility.StructureTreeEventHandler;
+import org.apache.fop.fo.FOEventHandler;
+import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.FOText;
+import org.apache.fop.fo.extensions.ExtensionElementMapping;
+import org.apache.fop.fo.flow.AbstractGraphics;
+import org.apache.fop.fo.flow.BasicLink;
+import org.apache.fop.fo.flow.Block;
+import org.apache.fop.fo.flow.BlockContainer;
+import org.apache.fop.fo.flow.Character;
+import org.apache.fop.fo.flow.ExternalGraphic;
+import org.apache.fop.fo.flow.Footnote;
+import org.apache.fop.fo.flow.FootnoteBody;
+import org.apache.fop.fo.flow.Inline;
+import org.apache.fop.fo.flow.InstreamForeignObject;
+import org.apache.fop.fo.flow.ListBlock;
+import org.apache.fop.fo.flow.ListItem;
+import org.apache.fop.fo.flow.ListItemBody;
+import org.apache.fop.fo.flow.ListItemLabel;
+import org.apache.fop.fo.flow.PageNumber;
+import org.apache.fop.fo.flow.PageNumberCitation;
+import org.apache.fop.fo.flow.PageNumberCitationLast;
+import org.apache.fop.fo.flow.Wrapper;
+import org.apache.fop.fo.flow.table.Table;
+import org.apache.fop.fo.flow.table.TableBody;
+import org.apache.fop.fo.flow.table.TableCell;
+import org.apache.fop.fo.flow.table.TableFooter;
+import org.apache.fop.fo.flow.table.TableHeader;
+import org.apache.fop.fo.flow.table.TableRow;
+import org.apache.fop.fo.pagination.Flow;
+import org.apache.fop.fo.pagination.PageSequence;
+import org.apache.fop.fo.pagination.StaticContent;
+import org.apache.fop.fo.properties.CommonAccessibilityHolder;
+import org.apache.fop.util.XMLUtil;
+
+/**
+ * A bridge between {@link FOEventHandler} and {@link StructureTreeEventHandler}.
+ */
+class StructureTreeEventTrigger extends FOEventHandler {
+
+ private StructureTreeEventHandler structureTreeEventHandler;
+
+ public StructureTreeEventTrigger(StructureTreeEventHandler structureTreeEventHandler) {
+ this.structureTreeEventHandler = structureTreeEventHandler;
+ }
+
+ @Override
+ public void startDocument() throws SAXException {
+ }
+
+ @Override
+ public void endDocument() throws SAXException {
+ }
+
+ @Override
+ public void startPageSequence(PageSequence pageSeq) {
+ Locale locale = null;
+ if (pageSeq.getLanguage() != null) {
+ if (pageSeq.getCountry() != null) {
+ locale = new Locale(pageSeq.getLanguage(), pageSeq.getCountry());
+ } else {
+ locale = new Locale(pageSeq.getLanguage());
+ }
+ }
+ structureTreeEventHandler.startPageSequence(locale);
+ }
+
+ @Override
+ public void endPageSequence(PageSequence pageSeq) {
+ structureTreeEventHandler.endPageSequence();
+ }
+
+ @Override
+ public void startPageNumber(PageNumber pagenum) {
+ startElementWithID(pagenum);
+ }
+
+ @Override
+ public void endPageNumber(PageNumber pagenum) {
+ endElement(pagenum);
+ }
+
+ @Override
+ public void startPageNumberCitation(PageNumberCitation pageCite) {
+ startElementWithID(pageCite);
+ }
+
+ @Override
+ public void endPageNumberCitation(PageNumberCitation pageCite) {
+ endElement(pageCite);
+ }
+
+ @Override
+ public void startPageNumberCitationLast(PageNumberCitationLast pageLast) {
+ startElementWithID(pageLast);
+ }
+
+ @Override
+ public void endPageNumberCitationLast(PageNumberCitationLast pageLast) {
+ endElement(pageLast);
+ }
+
+ @Override
+ public void startFlow(Flow fl) {
+ startElement(fl);
+ }
+
+ @Override
+ public void endFlow(Flow fl) {
+ endElement(fl);
+ }
+
+ @Override
+ public void startBlock(Block bl) {
+ startElement(bl);
+ }
+
+ @Override
+ public void endBlock(Block bl) {
+ endElement(bl);
+ }
+
+ @Override
+ public void startBlockContainer(BlockContainer blc) {
+ startElement(blc);
+ }
+
+ @Override
+ public void endBlockContainer(BlockContainer blc) {
+ endElement(blc);
+ }
+
+ @Override
+ public void startInline(Inline inl) {
+ startElement(inl);
+ }
+
+ @Override
+ public void endInline(Inline inl) {
+ endElement(inl);
+ }
+
+ @Override
+ public void startTable(Table tbl) {
+ startElement(tbl);
+ }
+
+ @Override
+ public void endTable(Table tbl) {
+ endElement(tbl);
+ }
+
+ @Override
+ public void startHeader(TableHeader header) {
+ startElement(header);
+ }
+
+ @Override
+ public void endHeader(TableHeader header) {
+ endElement(header);
+ }
+
+ @Override
+ public void startFooter(TableFooter footer) {
+ startElement(footer);
+ }
+
+ @Override
+ public void endFooter(TableFooter footer) {
+ endElement(footer);
+ }
+
+ @Override
+ public void startBody(TableBody body) {
+ startElement(body);
+ }
+
+ @Override
+ public void endBody(TableBody body) {
+ endElement(body);
+ }
+
+ @Override
+ public void startRow(TableRow tr) {
+ startElement(tr);
+ }
+
+ @Override
+ public void endRow(TableRow tr) {
+ endElement(tr);
+ }
+
+ @Override
+ public void startCell(TableCell tc) {
+ AttributesImpl attributes = new AttributesImpl();
+ int colSpan = tc.getNumberColumnsSpanned();
+ if (colSpan > 1) {
+ addNoNamespaceAttribute(attributes, "number-columns-spanned",
+ Integer.toString(colSpan));
+ }
+ startElement(tc, attributes);
+ }
+
+ @Override
+ public void endCell(TableCell tc) {
+ endElement(tc);
+ }
+
+ @Override
+ public void startList(ListBlock lb) {
+ startElement(lb);
+ }
+
+ @Override
+ public void endList(ListBlock lb) {
+ endElement(lb);
+ }
+
+ @Override
+ public void startListItem(ListItem li) {
+ startElement(li);
+ }
+
+ @Override
+ public void endListItem(ListItem li) {
+ endElement(li);
+ }
+
+ @Override
+ public void startListLabel(ListItemLabel listItemLabel) {
+ startElement(listItemLabel);
+ }
+
+ @Override
+ public void endListLabel(ListItemLabel listItemLabel) {
+ endElement(listItemLabel);
+ }
+
+ @Override
+ public void startListBody(ListItemBody listItemBody) {
+ startElement(listItemBody);
+ }
+
+ @Override
+ public void endListBody(ListItemBody listItemBody) {
+ endElement(listItemBody);
+ }
+
+ @Override
+ public void startStatic(StaticContent staticContent) {
+ startElement(staticContent);
+ }
+
+ @Override
+ public void endStatic(StaticContent statisContent) {
+ endElement(statisContent);
+ }
+
+ @Override
+ public void startLink(BasicLink basicLink) {
+ startElementWithID(basicLink);
+ }
+
+ @Override
+ public void endLink(BasicLink basicLink) {
+ endElement(basicLink);
+ }
+
+ @Override
+ public void image(ExternalGraphic eg) {
+ startElementWithIDAndAltText(eg);
+ endElement(eg);
+ }
+
+ @Override
+ public void startInstreamForeignObject(InstreamForeignObject ifo) {
+ startElementWithIDAndAltText(ifo);
+ }
+
+ @Override
+ public void endInstreamForeignObject(InstreamForeignObject ifo) {
+ endElement(ifo);
+ }
+
+ @Override
+ public void startFootnote(Footnote footnote) {
+ startElement(footnote);
+ }
+
+ @Override
+ public void endFootnote(Footnote footnote) {
+ endElement(footnote);
+ }
+
+ @Override
+ public void startFootnoteBody(FootnoteBody body) {
+ startElement(body);
+ }
+
+ @Override
+ public void endFootnoteBody(FootnoteBody body) {
+ endElement(body);
+ }
+
+ @Override
+ public void startWrapper(Wrapper wrapper) {
+ startElement(wrapper);
+ }
+
+ @Override
+ public void endWrapper(Wrapper wrapper) {
+ endElement(wrapper);
+ }
+
+ @Override
+ public void character(Character c) {
+ startElementWithID(c);
+ endElement(c);
+ }
+
+ @Override
+ public void characters(FOText foText) {
+ startElementWithID(foText);
+ endElement(foText);
+ }
+
+
+ private void startElement(FONode node) {
+ startElement(node, new AttributesImpl());
+ }
+
+ private void startElementWithID(FONode node) {
+ AttributesImpl attributes = new AttributesImpl();
+ String localName = node.getLocalName();
+ if (node instanceof CommonAccessibilityHolder) {
+ addRole((CommonAccessibilityHolder) node, attributes);
+ }
+ node.setStructureTreeElement(
+ structureTreeEventHandler.startReferencedNode(localName, attributes));
+ }
+
+ private void startElementWithIDAndAltText(AbstractGraphics node) {
+ AttributesImpl attributes = new AttributesImpl();
+ String localName = node.getLocalName();
+ addRole(node, attributes);
+ addAttribute(attributes, ExtensionElementMapping.URI, "alt-text",
+ ExtensionElementMapping.STANDARD_PREFIX, node.getAltText());
+ node.setStructureTreeElement(
+ structureTreeEventHandler.startImageNode(localName, attributes));
+ }
+
+ private StructureTreeElement startElement(FONode node, AttributesImpl attributes) {
+ String localName = node.getLocalName();
+ if (node instanceof CommonAccessibilityHolder) {
+ addRole((CommonAccessibilityHolder) node, attributes);
+ }
+ return structureTreeEventHandler.startNode(localName, attributes);
+ }
+
+ private void addNoNamespaceAttribute(AttributesImpl attributes, String name, String value) {
+ attributes.addAttribute("", name, name, XMLUtil.CDATA, value);
+ }
+
+ private void addAttribute(AttributesImpl attributes,
+ String namespace, String localName, String prefix, String value) {
+ assert namespace.length() > 0 && prefix.length() > 0;
+ String qualifiedName = prefix + ":" + localName;
+ attributes.addAttribute(namespace, localName, qualifiedName, XMLUtil.CDATA, value);
+ }
+
+ private void addRole(CommonAccessibilityHolder node, AttributesImpl attributes) {
+ String role = node.getCommonAccessibility().getRole();
+ if (role != null) {
+ addNoNamespaceAttribute(attributes, "role", role);
+ }
+ }
+
+ private void endElement(FONode node) {
+ String localName = node.getLocalName();
+ structureTreeEventHandler.endNode(localName);
+ }
+
+}
diff --git a/src/java/org/apache/fop/apps/FOUserAgent.java b/src/java/org/apache/fop/apps/FOUserAgent.java
index 071066e04..7d1736586 100644
--- a/src/java/org/apache/fop/apps/FOUserAgent.java
+++ b/src/java/org/apache/fop/apps/FOUserAgent.java
@@ -39,7 +39,8 @@ import org.apache.xmlgraphics.util.UnitConv;
import org.apache.fop.Version;
import org.apache.fop.accessibility.Accessibility;
-import org.apache.fop.accessibility.StructureTree;
+import org.apache.fop.accessibility.DummyStructureTreeEventHandler;
+import org.apache.fop.accessibility.StructureTreeEventHandler;
import org.apache.fop.events.DefaultEventBroadcaster;
import org.apache.fop.events.Event;
import org.apache.fop.events.EventBroadcaster;
@@ -101,8 +102,8 @@ public class FOUserAgent {
private boolean locatorEnabled = true; // true by default (for error messages).
private boolean conserveMemoryPolicy = false;
private EventBroadcaster eventBroadcaster = new FOPEventBroadcaster();
-
- private StructureTree structureTree;
+ private StructureTreeEventHandler structureTreeEventHandler
+ = DummyStructureTreeEventHandler.INSTANCE;
/** Producer: Metadata element for the system/software that produces
* the document. (Some renderers can store this in the document.)
@@ -173,6 +174,9 @@ public class FOUserAgent {
* @param documentHandler the document handler instance to use
*/
public void setDocumentHandlerOverride(IFDocumentHandler documentHandler) {
+ if (isAccessibilityEnabled()) {
+ setStructureTreeEventHandler(documentHandler.getStructureTreeEventHandler());
+ }
this.documentHandlerOverride = documentHandler;
}
@@ -674,24 +678,23 @@ public class FOUserAgent {
}
/**
- * Sets the document's structure tree, for use by accessible output formats.
+ * Sets the document's structure tree event handler, for use by accessible
+ * output formats.
*
- * @param structureTree a simplified version of the FO tree, retaining only
- * its logical structure
+ * @param structureTreeEventHandler The structure tree event handler to set
*/
- public void setStructureTree(StructureTree structureTree) {
- this.structureTree = structureTree;
+ public void setStructureTreeEventHandler(StructureTreeEventHandler structureTreeEventHandler) {
+ this.structureTreeEventHandler = structureTreeEventHandler;
}
/**
- * Returns the document's structure tree, for use by accessible output
- * formats.
+ * Returns the document's structure tree event handler, for use by
+ * accessible output formats.
*
- * @return a simplified version of the FO tree, retaining only its logical
- * structure
+ * @return The structure tree event handler
*/
- public StructureTree getStructureTree() {
- return this.structureTree;
+ public StructureTreeEventHandler getStructureTreeEventHandler() {
+ return this.structureTreeEventHandler;
}
}
diff --git a/src/java/org/apache/fop/apps/Fop.java b/src/java/org/apache/fop/apps/Fop.java
index 07fd4c0a4..0527ea290 100644
--- a/src/java/org/apache/fop/apps/Fop.java
+++ b/src/java/org/apache/fop/apps/Fop.java
@@ -24,7 +24,6 @@ import java.io.OutputStream;
import org.xml.sax.helpers.DefaultHandler;
-import org.apache.fop.accessibility.Accessibility;
import org.apache.fop.fo.FOTreeBuilder;
/**
@@ -111,11 +110,7 @@ public class Fop {
if (foTreeBuilder == null) {
createDefaultHandler();
}
- if (this.foUserAgent.isAccessibilityEnabled()) {
- return Accessibility.decorateDefaultHandler(this.foTreeBuilder, foUserAgent);
- } else {
- return this.foTreeBuilder;
- }
+ return this.foTreeBuilder;
}
/**
diff --git a/src/java/org/apache/fop/area/AreaTreeHandler.java b/src/java/org/apache/fop/area/AreaTreeHandler.java
index f45245bfe..6448e7c5d 100644
--- a/src/java/org/apache/fop/area/AreaTreeHandler.java
+++ b/src/java/org/apache/fop/area/AreaTreeHandler.java
@@ -22,6 +22,7 @@ package org.apache.fop.area;
// Java
import java.io.OutputStream;
import java.util.List;
+import java.util.Locale;
import org.xml.sax.SAXException;
@@ -182,6 +183,14 @@ public class AreaTreeHandler extends FOEventHandler {
}
}
+ @Override
+ public void startRoot(Root root) {
+ Locale locale = root.getLocale();
+ if (locale != null) {
+ model.setDocumentLocale(locale);
+ }
+ }
+
/**
* finish the previous pageSequence
*/
diff --git a/src/java/org/apache/fop/area/AreaTreeModel.java b/src/java/org/apache/fop/area/AreaTreeModel.java
index 2a1f14ab5..941f6cea2 100644
--- a/src/java/org/apache/fop/area/AreaTreeModel.java
+++ b/src/java/org/apache/fop/area/AreaTreeModel.java
@@ -21,6 +21,7 @@ package org.apache.fop.area;
// Java
import java.util.List;
+import java.util.Locale;
import org.xml.sax.SAXException;
@@ -123,4 +124,11 @@ public class AreaTreeModel {
public PageViewport getPage(int seq, int count) {
return pageSequenceList.get(seq - 1).getPage(count);
}
+
+ /**
+ *
+ * @param locale The locale of the document
+ */
+ public void setDocumentLocale(Locale locale) {
+ }
}
diff --git a/src/java/org/apache/fop/area/AreaTreeParser.java b/src/java/org/apache/fop/area/AreaTreeParser.java
index d2f52f991..d8c22f2e8 100644
--- a/src/java/org/apache/fop/area/AreaTreeParser.java
+++ b/src/java/org/apache/fop/area/AreaTreeParser.java
@@ -58,8 +58,6 @@ import org.apache.xmlgraphics.image.loader.ImageSessionContext;
import org.apache.xmlgraphics.util.QName;
import org.apache.fop.ResourceEventProducer;
-import org.apache.fop.accessibility.AccessibilityEventProducer;
-import org.apache.fop.accessibility.StructureTreeBuilder;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.area.Trait.Background;
import org.apache.fop.area.Trait.InternalLink;
@@ -69,11 +67,11 @@ import org.apache.fop.area.inline.Image;
import org.apache.fop.area.inline.InlineArea;
import org.apache.fop.area.inline.InlineBlockParent;
import org.apache.fop.area.inline.InlineParent;
+import org.apache.fop.area.inline.InlineViewport;
import org.apache.fop.area.inline.Leader;
import org.apache.fop.area.inline.Space;
import org.apache.fop.area.inline.SpaceArea;
import org.apache.fop.area.inline.TextArea;
-import org.apache.fop.area.inline.InlineViewport;
import org.apache.fop.area.inline.WordArea;
import org.apache.fop.fo.ElementMappingRegistry;
import org.apache.fop.fo.expr.PropertyException;
@@ -86,7 +84,6 @@ import org.apache.fop.util.ContentHandlerFactory;
import org.apache.fop.util.ContentHandlerFactoryRegistry;
import org.apache.fop.util.ConversionUtils;
import org.apache.fop.util.DefaultErrorListener;
-import org.apache.fop.util.DelegatingContentHandler;
import org.apache.fop.util.XMLConstants;
import org.apache.fop.util.XMLUtil;
@@ -166,27 +163,6 @@ public class AreaTreeParser {
private DOMImplementation domImplementation;
private Locator locator;
-
- private StructureTreeBuilder structureTreeBuilder;
-
- private ContentHandler structureTreeBuilderWrapper;
-
- private Attributes pageSequenceAttributes;
-
- private final class StructureTreeBuilderWrapper extends DelegatingContentHandler {
-
- private StructureTreeBuilderWrapper()
- throws SAXException {
- super(structureTreeBuilder.getHandlerForNextPageSequence());
- }
-
- public void endDocument() throws SAXException {
- super.endDocument();
- startAreaTreeElement("pageSequence", pageSequenceAttributes);
- pageSequenceAttributes = null;
- }
- }
-
public Handler(AreaTreeModel treeModel, FOUserAgent userAgent,
ElementMappingRegistry elementMappingRegistry) {
this.treeModel = treeModel;
@@ -223,11 +199,6 @@ public class AreaTreeParser {
makers.put("bookmarkTree", new BookmarkTreeMaker());
makers.put("bookmark", new BookmarkMaker());
makers.put("destination", new DestinationMaker());
-
- if (userAgent.isAccessibilityEnabled()) {
- structureTreeBuilder = new StructureTreeBuilder(tFactory);
- userAgent.setStructureTree(structureTreeBuilder.getStructureTree());
- }
}
private Area findAreaType(Class clazz) {
@@ -308,32 +279,15 @@ public class AreaTreeParser {
} else {
boolean handled = true;
if ("".equals(uri)) {
- if (localName.equals("pageSequence") && userAgent.isAccessibilityEnabled()) {
- structureTreeBuilderWrapper = new StructureTreeBuilderWrapper();
- pageSequenceAttributes = new AttributesImpl(attributes);
- } else if (localName.equals("structureTree")) {
- if (userAgent.isAccessibilityEnabled()) {
- delegate = structureTreeBuilderWrapper;
- } else {
- /* Delegate to a handler that does nothing */
- delegate = new DefaultHandler();
- }
+ if (localName.equals("structureTree")) {
+
+ /* The area tree parser no longer supports the structure tree. */
+ delegate = new DefaultHandler();
+
delegateStack.push(qName);
delegate.startDocument();
delegate.startElement(uri, localName, qName, attributes);
} else {
- if (pageSequenceAttributes != null) {
- /*
- * This means that no structure-element tag was
- * found in the XML, otherwise a
- * StructureTreeBuilderWrapper object would have
- * been created, which would have reset the
- * pageSequenceAttributes field.
- */
- AccessibilityEventProducer.Provider
- .get(userAgent.getEventBroadcaster())
- .noStructureTreeInXML(this);
- }
handled = startAreaTreeElement(localName, attributes);
}
} else {
@@ -772,7 +726,6 @@ public class AreaTreeParser {
setTraits(attributes, ip, SUBSET_BOX);
setTraits(attributes, ip, SUBSET_COLOR);
setTraits(attributes, ip, SUBSET_LINK);
- setPtr(ip, attributes);
Area parent = (Area)areaStack.peek();
parent.addChildArea(ip);
areaStack.push(ip);
@@ -821,7 +774,6 @@ public class AreaTreeParser {
"tlsadjust", 0));
text.setTextWordSpaceAdjust(XMLUtil.getAttributeAsInt(attributes,
"twsadjust", 0));
- setPtr(text, attributes);
Area parent = (Area)areaStack.peek();
parent.addChildArea(text);
areaStack.push(text);
@@ -914,7 +866,6 @@ public class AreaTreeParser {
viewport.setContentPosition(XMLUtil.getAttributeAsRectangle2D(attributes, "pos"));
viewport.setClip(XMLUtil.getAttributeAsBoolean(attributes, "clip", false));
viewport.setOffset(XMLUtil.getAttributeAsInt(attributes, "offset", 0));
- setPtr(viewport, attributes);
Area parent = (Area)areaStack.peek();
parent.addChildArea(viewport);
areaStack.push(viewport);
@@ -933,7 +884,6 @@ public class AreaTreeParser {
transferForeignObjects(attributes, image);
setAreaAttributes(attributes, image);
setTraits(attributes, image, SUBSET_COMMON);
- setPtr(image, attributes);
getCurrentViewport().setContent(image);
}
}
@@ -1218,13 +1168,6 @@ public class AreaTreeParser {
}
}
- private void setPtr(Area area, Attributes attributes) {
- String ptr = attributes.getValue("ptr");
- if (ptr != null) {
- area.addTrait(Trait.PTR, ptr);
- }
- }
-
/** {@inheritDoc} */
public void characters(char[] ch, int start, int length) throws SAXException {
if (delegate != null) {
diff --git a/src/java/org/apache/fop/area/RenderPagesModel.java b/src/java/org/apache/fop/area/RenderPagesModel.java
index afec850f8..cef2552c8 100644
--- a/src/java/org/apache/fop/area/RenderPagesModel.java
+++ b/src/java/org/apache/fop/area/RenderPagesModel.java
@@ -24,6 +24,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.List;
+import java.util.Locale;
import org.xml.sax.SAXException;
@@ -83,6 +84,11 @@ public class RenderPagesModel extends AreaTreeModel {
}
}
+ @Override
+ public void setDocumentLocale(Locale locale) {
+ renderer.setDocumentLocale(locale);
+ }
+
/** {@inheritDoc} */
@Override
public void startPageSequence(PageSequence pageSequence) {
diff --git a/src/java/org/apache/fop/area/Trait.java b/src/java/org/apache/fop/area/Trait.java
index 042b65337..d9194559d 100644
--- a/src/java/org/apache/fop/area/Trait.java
+++ b/src/java/org/apache/fop/area/Trait.java
@@ -153,8 +153,8 @@ public final class Trait implements Serializable {
/** Trait for color of linethrough decorations when rendering inline parent. */
public static final Integer LINETHROUGH_COLOR = 36;
- /** The ptr trait. Used for accessibility */
- public static final Integer PTR = 37;
+ /** For navigation in the document structure. */
+ public static final Integer STRUCTURE_TREE_ELEMENT = 37;
/** Maximum value used by trait keys */
public static final int MAX_TRAIT_KEY = 37;
@@ -186,7 +186,7 @@ public final class Trait implements Serializable {
static {
// Create a hashmap mapping trait code to name for external representation
//put(ID_LINK, new TraitInfo("id-link", String.class));
- put(PTR, new TraitInfo("ptr", String.class));
+ put(STRUCTURE_TREE_ELEMENT, new TraitInfo("structure-tree-element", String.class));
put(INTERNAL_LINK, new TraitInfo("internal-link", InternalLink.class));
put(EXTERNAL_LINK, new TraitInfo("external-link", ExternalLink.class));
put(FONT, new TraitInfo("font", FontTriplet.class));
diff --git a/src/java/org/apache/fop/fo/Constants.java b/src/java/org/apache/fop/fo/Constants.java
index 726d4d89e..a2b982269 100644
--- a/src/java/org/apache/fop/fo/Constants.java
+++ b/src/java/org/apache/fop/fo/Constants.java
@@ -771,18 +771,16 @@ public interface Constants {
* multi-column layouts.
*/
int PR_X_DISABLE_COLUMN_BALANCING = 273;
- /** Property constant - FOP proprietary: FOP internal use for accessibility */
- int PR_X_PTR = 274;
/**
* Property constant - FOP proprietary: alternative text for e-g and i-f-o.
* Used for accessibility.
*/
- int PR_X_ALT_TEXT = 275;
+ int PR_X_ALT_TEXT = 274;
/** Property constant - FOP proprietary prototype (in XSL-FO 2.0 Requirements) */
- int PR_X_XML_BASE = 276;
+ int PR_X_XML_BASE = 275;
/** Number of property constants defined */
- int PROPERTY_COUNT = 276;
+ int PROPERTY_COUNT = 275;
// compound property constants
diff --git a/src/java/org/apache/fop/fo/DelegatingFOEventHandler.java b/src/java/org/apache/fop/fo/DelegatingFOEventHandler.java
new file mode 100644
index 000000000..e64106a80
--- /dev/null
+++ b/src/java/org/apache/fop/fo/DelegatingFOEventHandler.java
@@ -0,0 +1,404 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.fo;
+
+import org.xml.sax.SAXException;
+
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.fo.extensions.ExternalDocument;
+import org.apache.fop.fo.flow.BasicLink;
+import org.apache.fop.fo.flow.Block;
+import org.apache.fop.fo.flow.BlockContainer;
+import org.apache.fop.fo.flow.Character;
+import org.apache.fop.fo.flow.ExternalGraphic;
+import org.apache.fop.fo.flow.Footnote;
+import org.apache.fop.fo.flow.FootnoteBody;
+import org.apache.fop.fo.flow.Inline;
+import org.apache.fop.fo.flow.InstreamForeignObject;
+import org.apache.fop.fo.flow.Leader;
+import org.apache.fop.fo.flow.ListBlock;
+import org.apache.fop.fo.flow.ListItem;
+import org.apache.fop.fo.flow.ListItemBody;
+import org.apache.fop.fo.flow.ListItemLabel;
+import org.apache.fop.fo.flow.PageNumber;
+import org.apache.fop.fo.flow.PageNumberCitation;
+import org.apache.fop.fo.flow.PageNumberCitationLast;
+import org.apache.fop.fo.flow.Wrapper;
+import org.apache.fop.fo.flow.table.Table;
+import org.apache.fop.fo.flow.table.TableBody;
+import org.apache.fop.fo.flow.table.TableCell;
+import org.apache.fop.fo.flow.table.TableColumn;
+import org.apache.fop.fo.flow.table.TableFooter;
+import org.apache.fop.fo.flow.table.TableHeader;
+import org.apache.fop.fo.flow.table.TableRow;
+import org.apache.fop.fo.pagination.Flow;
+import org.apache.fop.fo.pagination.PageSequence;
+import org.apache.fop.fo.pagination.Root;
+import org.apache.fop.fo.pagination.StaticContent;
+import org.apache.fop.fonts.FontInfo;
+
+/**
+ * This class delegates all FO events to another FOEventHandler instance.
+ */
+public abstract class DelegatingFOEventHandler extends FOEventHandler {
+
+ private final FOEventHandler delegate;
+
+ /**
+ * Creates a new instance that delegates events to the given object.
+ *
+ * @param delegate the object to which all FO events will be forwarded
+ */
+ public DelegatingFOEventHandler(FOEventHandler delegate) {
+ super(delegate.getUserAgent());
+ this.delegate = delegate;
+ }
+
+ @Override
+ public FOUserAgent getUserAgent() {
+ return delegate.getUserAgent();
+ }
+
+ @Override
+ public FontInfo getFontInfo() {
+ return delegate.getFontInfo();
+ }
+
+ @Override
+ public void startDocument() throws SAXException {
+ delegate.startDocument();
+ }
+
+ @Override
+ public void endDocument() throws SAXException {
+ delegate.endDocument();
+ }
+
+ @Override
+ public void startRoot(Root root) {
+ delegate.startRoot(root);
+ }
+
+ @Override
+ public void endRoot(Root root) {
+ delegate.endRoot(root);
+ }
+
+ @Override
+ public void startPageSequence(PageSequence pageSeq) {
+ delegate.startPageSequence(pageSeq);
+ }
+
+ @Override
+ public void endPageSequence(PageSequence pageSeq) {
+ delegate.endPageSequence(pageSeq);
+ }
+
+ @Override
+ public void startPageNumber(PageNumber pagenum) {
+ delegate.startPageNumber(pagenum);
+ }
+
+ @Override
+ public void endPageNumber(PageNumber pagenum) {
+ delegate.endPageNumber(pagenum);
+ }
+
+ @Override
+ public void startPageNumberCitation(PageNumberCitation pageCite) {
+ delegate.startPageNumberCitation(pageCite);
+ }
+
+ @Override
+ public void endPageNumberCitation(PageNumberCitation pageCite) {
+ delegate.endPageNumberCitation(pageCite);
+ }
+
+ @Override
+ public void startPageNumberCitationLast(PageNumberCitationLast pageLast) {
+ delegate.startPageNumberCitationLast(pageLast);
+ }
+
+ @Override
+ public void endPageNumberCitationLast(PageNumberCitationLast pageLast) {
+ delegate.endPageNumberCitationLast(pageLast);
+ }
+
+ @Override
+ public void startFlow(Flow fl) {
+ delegate.startFlow(fl);
+ }
+
+ @Override
+ public void endFlow(Flow fl) {
+ delegate.endFlow(fl);
+ }
+
+ @Override
+ public void startBlock(Block bl) {
+ delegate.startBlock(bl);
+ }
+
+ @Override
+ public void endBlock(Block bl) {
+ delegate.endBlock(bl);
+ }
+
+ @Override
+ public void startBlockContainer(BlockContainer blc) {
+ delegate.startBlockContainer(blc);
+ }
+
+ @Override
+ public void endBlockContainer(BlockContainer blc) {
+ delegate.endBlockContainer(blc);
+ }
+
+ @Override
+ public void startInline(Inline inl) {
+ delegate.startInline(inl);
+ }
+
+ @Override
+ public void endInline(Inline inl) {
+ delegate.endInline(inl);
+ }
+
+ @Override
+ public void startTable(Table tbl) {
+ delegate.startTable(tbl);
+ }
+
+ @Override
+ public void endTable(Table tbl) {
+ delegate.endTable(tbl);
+ }
+
+ @Override
+ public void startColumn(TableColumn tc) {
+ delegate.startColumn(tc);
+ }
+
+ @Override
+ public void endColumn(TableColumn tc) {
+ delegate.endColumn(tc);
+ }
+
+ @Override
+ public void startHeader(TableHeader header) {
+ delegate.startHeader(header);
+ }
+
+ @Override
+ public void endHeader(TableHeader header) {
+ delegate.endHeader(header);
+ }
+
+ @Override
+ public void startFooter(TableFooter footer) {
+ delegate.startFooter(footer);
+ }
+
+ @Override
+ public void endFooter(TableFooter footer) {
+ delegate.endFooter(footer);
+ }
+
+ @Override
+ public void startBody(TableBody body) {
+ delegate.startBody(body);
+ }
+
+ @Override
+ public void endBody(TableBody body) {
+ delegate.endBody(body);
+ }
+
+ @Override
+ public void startRow(TableRow tr) {
+ delegate.startRow(tr);
+ }
+
+ @Override
+ public void endRow(TableRow tr) {
+ delegate.endRow(tr);
+ }
+
+ @Override
+ public void startCell(TableCell tc) {
+ delegate.startCell(tc);
+ }
+
+ @Override
+ public void endCell(TableCell tc) {
+ delegate.endCell(tc);
+ }
+
+ @Override
+ public void startList(ListBlock lb) {
+ delegate.startList(lb);
+ }
+
+ @Override
+ public void endList(ListBlock lb) {
+ delegate.endList(lb);
+ }
+
+ @Override
+ public void startListItem(ListItem li) {
+ delegate.startListItem(li);
+ }
+
+ @Override
+ public void endListItem(ListItem li) {
+ delegate.endListItem(li);
+ }
+
+ @Override
+ public void startListLabel(ListItemLabel listItemLabel) {
+ delegate.startListLabel(listItemLabel);
+ }
+
+ @Override
+ public void endListLabel(ListItemLabel listItemLabel) {
+ delegate.endListLabel(listItemLabel);
+ }
+
+ @Override
+ public void startListBody(ListItemBody listItemBody) {
+ delegate.startListBody(listItemBody);
+ }
+
+ @Override
+ public void endListBody(ListItemBody listItemBody) {
+ delegate.endListBody(listItemBody);
+ }
+
+ @Override
+ public void startStatic(StaticContent staticContent) {
+ delegate.startStatic(staticContent);
+ }
+
+ @Override
+ public void endStatic(StaticContent statisContent) {
+ delegate.endStatic(statisContent);
+ }
+
+ @Override
+ public void startMarkup() {
+ delegate.startMarkup();
+ }
+
+ @Override
+ public void endMarkup() {
+ delegate.endMarkup();
+ }
+
+ @Override
+ public void startLink(BasicLink basicLink) {
+ delegate.startLink(basicLink);
+ }
+
+ @Override
+ public void endLink(BasicLink basicLink) {
+ delegate.endLink(basicLink);
+ }
+
+ @Override
+ public void image(ExternalGraphic eg) {
+ delegate.image(eg);
+ }
+
+ @Override
+ public void pageRef() {
+ delegate.pageRef();
+ }
+
+ @Override
+ public void startInstreamForeignObject(InstreamForeignObject ifo) {
+ delegate.startInstreamForeignObject(ifo);
+ }
+
+ @Override
+ public void endInstreamForeignObject(InstreamForeignObject ifo) {
+ delegate.endInstreamForeignObject(ifo);
+ }
+
+ @Override
+ public void startFootnote(Footnote footnote) {
+ delegate.startFootnote(footnote);
+ }
+
+ @Override
+ public void endFootnote(Footnote footnote) {
+ delegate.endFootnote(footnote);
+ }
+
+ @Override
+ public void startFootnoteBody(FootnoteBody body) {
+ delegate.startFootnoteBody(body);
+ }
+
+ @Override
+ public void endFootnoteBody(FootnoteBody body) {
+ delegate.endFootnoteBody(body);
+ }
+
+ @Override
+ public void startLeader(Leader l) {
+ delegate.startLeader(l);
+ }
+
+ @Override
+ public void endLeader(Leader l) {
+ delegate.endLeader(l);
+ }
+
+ @Override
+ public void startWrapper(Wrapper wrapper) {
+ delegate.startWrapper(wrapper);
+ }
+
+ @Override
+ public void endWrapper(Wrapper wrapper) {
+ delegate.endWrapper(wrapper);
+ }
+
+ @Override
+ public void character(Character c) {
+ delegate.character(c);
+ }
+
+ @Override
+ public void characters(FOText foText) {
+ delegate.characters(foText);
+ }
+
+ @Override
+ public void startExternalDocument(ExternalDocument document) {
+ delegate.startExternalDocument(document);
+ }
+
+ @Override
+ public void endExternalDocument(ExternalDocument document) {
+ delegate.endExternalDocument(document);
+ }
+
+}
diff --git a/src/java/org/apache/fop/fo/FOElementMapping.java b/src/java/org/apache/fop/fo/FOElementMapping.java
index 495cd274b..b087e1d9c 100644
--- a/src/java/org/apache/fop/fo/FOElementMapping.java
+++ b/src/java/org/apache/fop/fo/FOElementMapping.java
@@ -34,6 +34,9 @@ public class FOElementMapping extends ElementMapping {
/** The XSL-FO namespace URI */
public static final String URI = "http://www.w3.org/1999/XSL/Format";
+ /** Standard prefix */
+ public static final String STANDARD_PREFIX = "fo";
+
/**
* Basic constructor; inititializes the namespace URI for the fo: namespace
*/
@@ -143,7 +146,7 @@ public class FOElementMapping extends ElementMapping {
/** {@inheritDoc} */
public String getStandardPrefix() {
- return "fo";
+ return STANDARD_PREFIX;
}
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/fo/FOEventHandler.java b/src/java/org/apache/fop/fo/FOEventHandler.java
index e280af2d7..b7bcd4215 100644
--- a/src/java/org/apache/fop/fo/FOEventHandler.java
+++ b/src/java/org/apache/fop/fo/FOEventHandler.java
@@ -35,9 +35,12 @@ import org.apache.fop.fo.flow.InstreamForeignObject;
import org.apache.fop.fo.flow.Leader;
import org.apache.fop.fo.flow.ListBlock;
import org.apache.fop.fo.flow.ListItem;
+import org.apache.fop.fo.flow.ListItemBody;
+import org.apache.fop.fo.flow.ListItemLabel;
import org.apache.fop.fo.flow.PageNumber;
import org.apache.fop.fo.flow.PageNumberCitation;
import org.apache.fop.fo.flow.PageNumberCitationLast;
+import org.apache.fop.fo.flow.Wrapper;
import org.apache.fop.fo.flow.table.Table;
import org.apache.fop.fo.flow.table.TableBody;
import org.apache.fop.fo.flow.table.TableCell;
@@ -47,6 +50,8 @@ import org.apache.fop.fo.flow.table.TableHeader;
import org.apache.fop.fo.flow.table.TableRow;
import org.apache.fop.fo.pagination.Flow;
import org.apache.fop.fo.pagination.PageSequence;
+import org.apache.fop.fo.pagination.Root;
+import org.apache.fop.fo.pagination.StaticContent;
import org.apache.fop.fonts.FontEventAdapter;
import org.apache.fop.fonts.FontInfo;
@@ -83,6 +88,10 @@ public abstract class FOEventHandler {
this.fontInfo.setEventListener(new FontEventAdapter(foUserAgent.getEventBroadcaster()));
}
+ /** Constructor for sub-classes that do not need an {@link FOUserAgent} instance. */
+ protected FOEventHandler() {
+ }
+
/**
* Returns the User Agent object associated with this FOEventHandler.
* @return the User Agent object
@@ -113,6 +122,14 @@ public abstract class FOEventHandler {
public void endDocument() throws SAXException {
}
+ /** {@inheritDoc} */
+ public void startRoot(Root root) {
+ }
+
+ /** {@inheritDoc} */
+ public void endRoot(Root root) {
+ }
+
/**
*
* @param pageSeq PageSequence that is starting.
@@ -359,39 +376,45 @@ public abstract class FOEventHandler {
/**
* Process start of a ListLabel.
+ * @param listItemLabel ListItemLabel that is starting
*/
- public void startListLabel() {
+ public void startListLabel(ListItemLabel listItemLabel) {
}
/**
* Process end of a ListLabel.
+ * @param listItemLabel ListItemLabel that is ending
*/
- public void endListLabel() {
+ public void endListLabel(ListItemLabel listItemLabel) {
}
/**
* Process start of a ListBody.
+ * @param listItemBody ListItemBody that is starting
*/
- public void startListBody() {
+ public void startListBody(ListItemBody listItemBody) {
}
/**
* Process end of a ListBody.
+ * @param listItemBody ListItemBody that is ending
*/
- public void endListBody() {
+ public void endListBody(ListItemBody listItemBody) {
}
// Static Regions
/**
* Process start of a Static.
+ * @param staticContent StaticContent that is starting
*/
- public void startStatic() {
+ public void startStatic(StaticContent staticContent) {
}
/**
* Process end of a Static.
+ * @param statisContent StaticContent that is ending
*/
- public void endStatic() {
+ public void endStatic(StaticContent statisContent) {
}
@@ -409,15 +432,16 @@ public abstract class FOEventHandler {
/**
* Process start of a Link.
- * @param basicLink BasicLink that is ending
+ * @param basicLink BasicLink that is starting
*/
public void startLink(BasicLink basicLink) {
}
/**
* Process end of a Link.
+ * @param basicLink BasicLink that is ending
*/
- public void endLink() {
+ public void endLink(BasicLink basicLink) {
}
/**
@@ -434,10 +458,17 @@ public abstract class FOEventHandler {
}
/**
- * Process an InstreamForeignObject.
- * @param ifo InstreamForeignObject to process.
+ * Process the start of an InstreamForeignObject.
+ * @param ifo InstreamForeignObject that is starting
+ */
+ public void startInstreamForeignObject(InstreamForeignObject ifo) {
+ }
+
+ /**
+ * Process the end of an InstreamForeignObject.
+ * @param ifo InstreamForeignObject that is ending
*/
- public void foreignObject(InstreamForeignObject ifo) {
+ public void endInstreamForeignObject(InstreamForeignObject ifo) {
}
/**
@@ -469,10 +500,33 @@ public abstract class FOEventHandler {
}
/**
- * Process a Leader.
- * @param l Leader to process.
+ * Process the start of a Leader.
+ * @param l Leader that is starting
+ */
+ public void startLeader(Leader l) {
+ }
+
+ /**
+ * Process the end of a Leader.
+ * @param l Leader that is ending
+ */
+ public void endLeader(Leader l) {
+ }
+
+ /**
+ * Process the start of a wrapper.
+ *
+ * @param wrapper wrapper that is starting
+ */
+ public void startWrapper(Wrapper wrapper) {
+ }
+
+ /**
+ * Process the ending of a wrapper.
+ *
+ * @param wrapper wrapper that is ending
*/
- public void leader(Leader l) {
+ public void endWrapper(Wrapper wrapper) {
}
/**
@@ -484,11 +538,9 @@ public abstract class FOEventHandler {
/**
* Process character data.
- * @param data Array of characters to process.
- * @param start Offset for characters to process.
- * @param length Portion of array to process.
+ * @param foText text to process
*/
- public void characters(char[] data, int start, int length) {
+ public void characters(FOText foText) {
}
/**
diff --git a/src/java/org/apache/fop/fo/FONode.java b/src/java/org/apache/fop/fo/FONode.java
index c9c04aa4e..b63c49ae2 100644
--- a/src/java/org/apache/fop/fo/FONode.java
+++ b/src/java/org/apache/fop/fo/FONode.java
@@ -32,6 +32,7 @@ import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.util.QName;
+import org.apache.fop.accessibility.StructureTreeElement;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.fo.extensions.ExtensionAttachment;
@@ -912,4 +913,13 @@ public abstract class FONode implements Cloneable {
}
+ /**
+ * Sets the structure tree element.
+ *
+ * @param structureTreeElement set.
+ */
+ public void setStructureTreeElement(StructureTreeElement structureTreeElement) {
+ throw new UnsupportedOperationException();
+ }
+
}
diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java
index cf4eef3a5..172aa5329 100644
--- a/src/java/org/apache/fop/fo/FOPropertyMapping.java
+++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java
@@ -2533,12 +2533,6 @@ public final class FOPropertyMapping implements Constants {
m.setDefault("");
addPropertyMaker("id", m);
- // foi:ptr, used for accessibility
- m = new StringProperty.Maker(PR_X_PTR);
- m.setInherited(false);
- m.setDefault("");
- addPropertyMaker("foi:ptr", m);
-
// fox:alt-text, used for accessibility
m = new StringProperty.Maker(PR_X_ALT_TEXT);
m.setInherited(false);
diff --git a/src/java/org/apache/fop/fo/FOText.java b/src/java/org/apache/fop/fo/FOText.java
index 5db11f731..43b58685f 100644
--- a/src/java/org/apache/fop/fo/FOText.java
+++ b/src/java/org/apache/fop/fo/FOText.java
@@ -25,6 +25,7 @@ import java.util.NoSuchElementException;
import org.xml.sax.Locator;
+import org.apache.fop.accessibility.StructureTreeElement;
import org.apache.fop.apps.FOPException;
import org.apache.fop.datatypes.Length;
import org.apache.fop.fo.flow.Block;
@@ -79,6 +80,8 @@ public class FOText extends FONode implements CharSequence {
/** Holds the text decoration values. May be null */
private CommonTextDecoration textDecoration;
+ private StructureTreeElement structureTreeElement;
+
private static final int IS_WORD_CHAR_FALSE = 0;
private static final int IS_WORD_CHAR_TRUE = 1;
private static final int IS_WORD_CHAR_MAYBE = 2;
@@ -115,25 +118,14 @@ public class FOText extends FONode implements CharSequence {
/**
* Return the array of characters for this instance.
*
- * @return a char array containing the text
+ * @return a char sequence containing the text
*/
- public char[] getCharArray() {
-
+ public CharSequence getCharSequence() {
if (this.charBuffer == null) {
return null;
}
-
- if (this.charBuffer.hasArray()) {
- return this.charBuffer.array();
- }
-
- // only if the buffer implementation has
- // no accessible backing array, return a new one
- char[] ca = new char[this.charBuffer.limit()];
this.charBuffer.rewind();
- this.charBuffer.get(ca);
- return ca;
-
+ return this.charBuffer.asReadOnlyBuffer().subSequence(0, this.charBuffer.limit());
}
/** {@inheritDoc} */
@@ -176,8 +168,7 @@ public class FOText extends FONode implements CharSequence {
/** {@inheritDoc} */
protected void endOfNode() throws FOPException {
super.endOfNode();
- getFOEventHandler().characters(
- this.getCharArray(), 0, this.charBuffer.limit());
+ getFOEventHandler().characters(this);
}
/** {@inheritDoc} */
@@ -670,4 +661,15 @@ public class FOText extends FONode implements CharSequence {
this.charBuffer.rewind();
}
}
+
+ @Override
+ public void setStructureTreeElement(StructureTreeElement structureTreeElement) {
+ this.structureTreeElement = structureTreeElement;
+ }
+
+ /** @return the structure tree element. */
+ public StructureTreeElement getStructureTreeElement() {
+ return structureTreeElement;
+ }
+
}
diff --git a/src/java/org/apache/fop/fo/FOTreeBuilder.java b/src/java/org/apache/fop/fo/FOTreeBuilder.java
index 629e87e6b..38f74d8fd 100644
--- a/src/java/org/apache/fop/fo/FOTreeBuilder.java
+++ b/src/java/org/apache/fop/fo/FOTreeBuilder.java
@@ -33,6 +33,7 @@ import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.util.QName;
+import org.apache.fop.accessibility.fo.FO2StructureTreeConverter;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.FormattingResults;
@@ -104,6 +105,10 @@ public class FOTreeBuilder extends DefaultHandler {
//one of the RTF-, MIF- etc. Handlers.
foEventHandler = foUserAgent.getRendererFactory().createFOEventHandler(
foUserAgent, outputFormat, stream);
+ if (userAgent.isAccessibilityEnabled()) {
+ foEventHandler = new FO2StructureTreeConverter(
+ foUserAgent.getStructureTreeEventHandler(), foEventHandler);
+ }
builderContext = new FOTreeBuilderContext();
builderContext.setPropertyListMaker(new PropertyListMaker() {
public PropertyList make(FObj fobj, PropertyList parentPropertyList) {
diff --git a/src/java/org/apache/fop/fo/PropertyList.java b/src/java/org/apache/fop/fo/PropertyList.java
index a1634e868..65ebd40a2 100644
--- a/src/java/org/apache/fop/fo/PropertyList.java
+++ b/src/java/org/apache/fop/fo/PropertyList.java
@@ -30,7 +30,6 @@ import org.apache.xmlgraphics.util.QName;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.fo.expr.PropertyException;
import org.apache.fop.fo.properties.CommonAbsolutePosition;
-import org.apache.fop.fo.properties.CommonAccessibility;
import org.apache.fop.fo.properties.CommonAural;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.CommonFont;
@@ -601,15 +600,6 @@ public abstract class PropertyList {
}
/**
- * Constructs a CommonAccessibility object.
- * @return the CommonAccessibility object
- * @throws PropertyException if there's a problem while processing the properties
- */
- public CommonAccessibility getAccessibilityProps() throws PropertyException {
- return new CommonAccessibility(this);
- }
-
- /**
* Constructs a CommonAural object.
* @return the CommonAural object
* @throws PropertyException if there's a problem while processing the properties
diff --git a/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java b/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java
index 80a569c90..f0e03399f 100644
--- a/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java
+++ b/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java
@@ -37,6 +37,9 @@ public class ExtensionElementMapping extends ElementMapping {
/** The FOP extension namespace URI */
public static final String URI = "http://xmlgraphics.apache.org/fop/extensions";
+ /** The standard XML prefix for elements and attributes in this namespace. */
+ public static final String STANDARD_PREFIX = "fox";
+
private static final Set<String> PROPERTY_ATTRIBUTES
= new java.util.HashSet<String>();
@@ -85,7 +88,7 @@ public class ExtensionElementMapping extends ElementMapping {
/** {@inheritDoc} */
public String getStandardPrefix() {
- return "fox";
+ return STANDARD_PREFIX;
}
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/fo/extensions/InternalElementMapping.java b/src/java/org/apache/fop/fo/extensions/InternalElementMapping.java
index 4798f5500..687952d25 100644
--- a/src/java/org/apache/fop/fo/extensions/InternalElementMapping.java
+++ b/src/java/org/apache/fop/fo/extensions/InternalElementMapping.java
@@ -34,11 +34,21 @@ public class InternalElementMapping extends ElementMapping {
/** The FOP extension namespace URI */
public static final String URI = "http://xmlgraphics.apache.org/fop/internal";
+ /** The standard XML prefix for elements and attributes in this namespace. */
+ public static final String STANDARD_PREFIX = "foi";
+
+ /** The "struct-id" attribute, to identify a structure tree element. */
+ public static final String STRUCT_ID = "struct-id";
+
+ /** The "struct-ref" attribute, to refer to a structure tree element. */
+ public static final String STRUCT_REF = "struct-ref";
+
private static final Set<String> PROPERTY_ATTRIBUTES = new java.util.HashSet<String>();
static {
//These are FOP's extension properties for accessibility
- PROPERTY_ATTRIBUTES.add("ptr");
+ PROPERTY_ATTRIBUTES.add(STRUCT_ID);
+ PROPERTY_ATTRIBUTES.add(STRUCT_REF);
}
/**
@@ -59,7 +69,7 @@ public class InternalElementMapping extends ElementMapping {
/** {@inheritDoc} */
public String getStandardPrefix() {
- return "foi";
+ return STANDARD_PREFIX;
}
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/fo/flow/AbstractGraphics.java b/src/java/org/apache/fop/fo/flow/AbstractGraphics.java
index eeb06c1df..d5fe2b500 100644
--- a/src/java/org/apache/fop/fo/flow/AbstractGraphics.java
+++ b/src/java/org/apache/fop/fo/flow/AbstractGraphics.java
@@ -19,17 +19,20 @@
package org.apache.fop.fo.flow;
+import org.apache.fop.accessibility.StructureTreeElement;
import org.apache.fop.apps.FOPException;
import org.apache.fop.datatypes.Length;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.GraphicsProperties;
import org.apache.fop.fo.PropertyList;
+import org.apache.fop.fo.properties.CommonAccessibility;
+import org.apache.fop.fo.properties.CommonAccessibilityHolder;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.KeepProperty;
import org.apache.fop.fo.properties.LengthRangeProperty;
import org.apache.fop.fo.properties.SpaceProperty;
-import org.apache.fop.fo.properties.StructurePointerPropertySet;
+import org.apache.fop.fo.properties.StructureTreeElementHolder;
/**
* Common base class for the <a href="http://www.w3.org/TR/xsl/#fo_instream-foreign-object">
@@ -38,10 +41,11 @@ import org.apache.fop.fo.properties.StructurePointerPropertySet;
* <code>fo:external-graphic</code></a> flow formatting objects.
*/
public abstract class AbstractGraphics extends FObj
- implements GraphicsProperties, StructurePointerPropertySet {
+ implements GraphicsProperties, StructureTreeElementHolder, CommonAccessibilityHolder {
// The value of properties relevant for fo:instream-foreign-object
// and external-graphics.
+ private CommonAccessibility commonAccessibility;
private CommonBorderPaddingBackground commonBorderPaddingBackground;
private Length alignmentAdjust;
private int alignmentBaseline;
@@ -62,7 +66,8 @@ public abstract class AbstractGraphics extends FObj
private int scaling;
private int textAlign;
private Length width;
- private String ptr; // used for accessibility
+ private String altText;
+ private StructureTreeElement structureTreeElement;
// Unused but valid items, commented out for performance:
// private CommonAccessibility commonAccessibility;
// private CommonAural commonAural;
@@ -85,6 +90,7 @@ public abstract class AbstractGraphics extends FObj
/** {@inheritDoc} */
public void bind(PropertyList pList) throws FOPException {
+ commonAccessibility = CommonAccessibility.getInstance(pList);
commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
alignmentAdjust = pList.get(PR_ALIGNMENT_ADJUST).getLength();
alignmentBaseline = pList.get(PR_ALIGNMENT_BASELINE).getEnum();
@@ -97,7 +103,6 @@ public abstract class AbstractGraphics extends FObj
dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum();
height = pList.get(PR_HEIGHT).getLength();
id = pList.get(PR_ID).getString();
- ptr = pList.get(PR_X_PTR).getString(); // used for accessibility
inlineProgressionDimension = pList.get(PR_INLINE_PROGRESSION_DIMENSION).getLengthRange();
keepWithNext = pList.get(PR_KEEP_WITH_NEXT).getKeep();
keepWithPrevious = pList.get(PR_KEEP_WITH_PREVIOUS).getKeep();
@@ -107,13 +112,18 @@ public abstract class AbstractGraphics extends FObj
textAlign = pList.get(PR_TEXT_ALIGN).getEnum();
width = pList.get(PR_WIDTH).getLength();
if (getUserAgent().isAccessibilityEnabled()) {
- String altText = pList.get(PR_X_ALT_TEXT).getString();
+ altText = pList.get(PR_X_ALT_TEXT).getString();
if (altText.equals("")) {
getFOValidationEventProducer().altTextMissing(this, getLocalName(), getLocator());
}
}
}
+ /** {@inheritDoc} */
+ public CommonAccessibility getCommonAccessibility() {
+ return commonAccessibility;
+ }
+
/**
* @return the "id" property.
*/
@@ -217,9 +227,19 @@ public abstract class AbstractGraphics extends FObj
return keepWithPrevious;
}
+ @Override
+ public void setStructureTreeElement(StructureTreeElement structureTreeElement) {
+ this.structureTreeElement = structureTreeElement;
+ }
+
/** {@inheritDoc} */
- public String getPtr() {
- return ptr;
+ public StructureTreeElement getStructureTreeElement() {
+ return structureTreeElement;
+ }
+
+ /** @return the alternative text property. */
+ public String getAltText() {
+ return altText;
}
/** @return the graphic's intrinsic width in millipoints */
diff --git a/src/java/org/apache/fop/fo/flow/AbstractListItemPart.java b/src/java/org/apache/fop/fo/flow/AbstractListItemPart.java
index b0e93e9c6..0e99bfe96 100644
--- a/src/java/org/apache/fop/fo/flow/AbstractListItemPart.java
+++ b/src/java/org/apache/fop/fo/flow/AbstractListItemPart.java
@@ -26,6 +26,8 @@ import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
+import org.apache.fop.fo.properties.CommonAccessibility;
+import org.apache.fop.fo.properties.CommonAccessibilityHolder;
import org.apache.fop.fo.properties.KeepProperty;
/**
@@ -33,8 +35,10 @@ import org.apache.fop.fo.properties.KeepProperty;
* <code>fo:list-item-label</code></a> and <a href="http://www.w3.org/TR/xsl/#fo_list-item-body">
* <code>fo:list-item-body</code></a>.
*/
-public abstract class AbstractListItemPart extends FObj {
- // The value of properties relevant for fo:list-item-label and fo:list-item-body.
+public abstract class AbstractListItemPart extends FObj implements CommonAccessibilityHolder {
+
+ private CommonAccessibility commonAccessibility;
+
private KeepProperty keepTogether;
// Valid properties, commented out for performance:
// private CommonAccessibility commonAccessibility;
@@ -55,6 +59,7 @@ public abstract class AbstractListItemPart extends FObj {
/** {@inheritDoc} */
public void bind(PropertyList pList) throws FOPException {
super.bind(pList);
+ commonAccessibility = CommonAccessibility.getInstance(pList);
keepTogether = pList.get(PR_KEEP_TOGETHER).getKeep();
}
@@ -86,6 +91,11 @@ public abstract class AbstractListItemPart extends FObj {
}
}
+ /** {@inheritDoc} */
+ public CommonAccessibility getCommonAccessibility() {
+ return commonAccessibility;
+ }
+
/** @return the "keep-together" property. */
public KeepProperty getKeepTogether() {
return keepTogether;
diff --git a/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java b/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java
index 7bc0ff00c..5a6893b55 100644
--- a/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java
+++ b/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java
@@ -24,6 +24,7 @@ import java.awt.Color;
import org.xml.sax.Attributes;
import org.xml.sax.Locator;
+import org.apache.fop.accessibility.StructureTreeElement;
import org.apache.fop.apps.FOPException;
import org.apache.fop.datatypes.Length;
import org.apache.fop.fo.Constants;
@@ -31,11 +32,13 @@ import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
+import org.apache.fop.fo.properties.CommonAccessibility;
+import org.apache.fop.fo.properties.CommonAccessibilityHolder;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.CommonFont;
import org.apache.fop.fo.properties.CommonTextDecoration;
import org.apache.fop.fo.properties.SpaceProperty;
-import org.apache.fop.fo.properties.StructurePointerPropertySet;
+import org.apache.fop.fo.properties.StructureTreeElementHolder;
/**
* Common base class for the <a href="http://www.w3.org/TR/xsl/#fo_page-number-citation">
@@ -44,16 +47,17 @@ import org.apache.fop.fo.properties.StructurePointerPropertySet;
* <code>fo:page-number-citation-last</code></a> objects.
*/
public abstract class AbstractPageNumberCitation extends FObj
- implements StructurePointerPropertySet {
+ implements StructureTreeElementHolder, CommonAccessibilityHolder {
// The value of properties relevant for fo:page-number-citation(-last).
+ private CommonAccessibility commonAccessibility;
private CommonBorderPaddingBackground commonBorderPaddingBackground;
private CommonFont commonFont;
private Length alignmentAdjust;
private int alignmentBaseline;
private Length baselineShift;
private int dominantBaseline;
- private String ptr; // used for accessibility
+ private StructureTreeElement structureTreeElement;
// private ToBeImplementedProperty letterSpacing;
private SpaceProperty lineHeight;
private String refId;
@@ -61,7 +65,6 @@ public abstract class AbstractPageNumberCitation extends FObj
private CommonTextDecoration textDecoration;
// private ToBeImplementedProperty textShadow;
// Unused but valid items, commented out for performance:
- // private CommonAccessibility commonAccessibility;
// private CommonAural commonAural;
// private CommonMarginInline commonMarginInline;
// private CommonRelativePosition commonRelativePosition;
@@ -91,6 +94,7 @@ public abstract class AbstractPageNumberCitation extends FObj
/** {@inheritDoc} */
public void bind(PropertyList pList) throws FOPException {
super.bind(pList);
+ commonAccessibility = CommonAccessibility.getInstance(pList);
commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
commonFont = pList.getFontProps();
alignmentAdjust = pList.get(PR_ALIGNMENT_ADJUST).getLength();
@@ -99,7 +103,6 @@ public abstract class AbstractPageNumberCitation extends FObj
dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum();
// letterSpacing = pList.get(PR_LETTER_SPACING);
lineHeight = pList.get(PR_LINE_HEIGHT).getSpace();
- ptr = pList.get(PR_X_PTR).getString(); // used for accessibility
refId = pList.get(PR_REF_ID).getString();
textDecoration = pList.getTextDecorationProps();
// textShadow = pList.get(PR_TEXT_SHADOW);
@@ -129,6 +132,11 @@ public abstract class AbstractPageNumberCitation extends FObj
}
}
+ /** {@inheritDoc} */
+ public CommonAccessibility getCommonAccessibility() {
+ return commonAccessibility;
+ }
+
/** @return the {@link CommonFont} */
public CommonFont getCommonFont() {
return commonFont;
@@ -144,9 +152,14 @@ public abstract class AbstractPageNumberCitation extends FObj
return textDecoration;
}
+ @Override
+ public void setStructureTreeElement(StructureTreeElement structureTreeElement) {
+ this.structureTreeElement = structureTreeElement;
+ }
+
/** {@inheritDoc} */
- public String getPtr() {
- return ptr;
+ public StructureTreeElement getStructureTreeElement() {
+ return structureTreeElement;
}
/** @return the "alignment-adjust" property */
diff --git a/src/java/org/apache/fop/fo/flow/BasicLink.java b/src/java/org/apache/fop/fo/flow/BasicLink.java
index c3a735db6..0d6d5d9b4 100644
--- a/src/java/org/apache/fop/fo/flow/BasicLink.java
+++ b/src/java/org/apache/fop/fo/flow/BasicLink.java
@@ -21,12 +21,13 @@ package org.apache.fop.fo.flow;
import org.xml.sax.Locator;
+import org.apache.fop.accessibility.StructureTreeElement;
import org.apache.fop.apps.FOPException;
import org.apache.fop.datatypes.Length;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
-import org.apache.fop.fo.properties.StructurePointerPropertySet;
+import org.apache.fop.fo.properties.StructureTreeElementHolder;
/**
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_basic-link">
@@ -36,14 +37,14 @@ import org.apache.fop.fo.properties.StructurePointerPropertySet;
* and whether that link is external (uses a URI) or internal (an id
* reference).
*/
-public class BasicLink extends InlineLevel implements StructurePointerPropertySet {
+public class BasicLink extends InlineLevel implements StructureTreeElementHolder {
// The value of properties relevant for fo:basic-link.
private Length alignmentAdjust;
private int alignmentBaseline;
private Length baselineShift;
private int dominantBaseline;
- private String ptr;
+ private StructureTreeElement structureTreeElement;
// private ToBeImplementedProperty destinationPlacementOffset;
private String externalDestination;
// private ToBeImplementedProperty indicateDestination;
@@ -76,7 +77,6 @@ public class BasicLink extends InlineLevel implements StructurePointerPropertySe
alignmentBaseline = pList.get(PR_ALIGNMENT_BASELINE).getEnum();
baselineShift = pList.get(PR_BASELINE_SHIFT).getLength();
dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum();
- ptr = pList.get(PR_X_PTR).getString(); // used for accessibility
// destinationPlacementOffset = pList.get(PR_DESTINATION_PLACEMENT_OFFSET);
externalDestination = pList.get(PR_EXTERNAL_DESTINATION).getString();
// indicateDestination = pList.get(PR_INDICATE_DESTINATION);
@@ -104,7 +104,7 @@ public class BasicLink extends InlineLevel implements StructurePointerPropertySe
/** {@inheritDoc} */
protected void endOfNode() throws FOPException {
super.endOfNode();
- getFOEventHandler().endLink();
+ getFOEventHandler().endLink(this);
}
/** {@inheritDoc} */
@@ -143,9 +143,14 @@ public class BasicLink extends InlineLevel implements StructurePointerPropertySe
return dominantBaseline;
}
+ @Override
+ public void setStructureTreeElement(StructureTreeElement structureTreeElement) {
+ this.structureTreeElement = structureTreeElement;
+ }
+
/** {@inheritDoc} */
- public String getPtr() {
- return ptr;
+ public StructureTreeElement getStructureTreeElement() {
+ return structureTreeElement;
}
/**
diff --git a/src/java/org/apache/fop/fo/flow/Block.java b/src/java/org/apache/fop/fo/flow/Block.java
index 66e06db83..84f1abc1b 100644
--- a/src/java/org/apache/fop/fo/flow/Block.java
+++ b/src/java/org/apache/fop/fo/flow/Block.java
@@ -33,6 +33,8 @@ import org.apache.fop.fo.NullCharIterator;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
import org.apache.fop.fo.properties.BreakPropertySet;
+import org.apache.fop.fo.properties.CommonAccessibility;
+import org.apache.fop.fo.properties.CommonAccessibilityHolder;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.CommonFont;
import org.apache.fop.fo.properties.CommonHyphenation;
@@ -40,19 +42,20 @@ import org.apache.fop.fo.properties.CommonMarginBlock;
import org.apache.fop.fo.properties.CommonRelativePosition;
import org.apache.fop.fo.properties.KeepProperty;
import org.apache.fop.fo.properties.SpaceProperty;
-import org.apache.fop.fo.properties.StructurePointerPropertySet;
/**
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_block">
* <code>fo:block object</code></a>.
*/
-public class Block extends FObjMixed implements BreakPropertySet, StructurePointerPropertySet {
+public class Block extends FObjMixed implements BreakPropertySet,
+ CommonAccessibilityHolder {
// used for FO validation
private boolean blockOrInlineItemFound = false;
private boolean initialPropertySetFound = false;
// The value of properties relevant for fo:block.
+ private CommonAccessibility commonAccessibility;
private CommonBorderPaddingBackground commonBorderPaddingBackground;
private CommonFont commonFont;
private CommonHyphenation commonHyphenation;
@@ -73,7 +76,6 @@ public class Block extends FObjMixed implements BreakPropertySet, StructurePoint
private int lineHeightShiftAdjustment;
private int lineStackingStrategy;
private Numeric orphans;
- private String ptr; //used for accessibility
private int whiteSpaceTreatment;
private int span;
private int textAlign;
@@ -104,6 +106,7 @@ public class Block extends FObjMixed implements BreakPropertySet, StructurePoint
/** {@inheritDoc} */
public void bind(PropertyList pList) throws FOPException {
super.bind(pList);
+ commonAccessibility = CommonAccessibility.getInstance(pList);
commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
commonFont = pList.getFontProps();
commonHyphenation = pList.getHyphenationProps();
@@ -125,7 +128,6 @@ public class Block extends FObjMixed implements BreakPropertySet, StructurePoint
lineHeightShiftAdjustment = pList.get(PR_LINE_HEIGHT_SHIFT_ADJUSTMENT).getEnum();
lineStackingStrategy = pList.get(PR_LINE_STACKING_STRATEGY).getEnum();
orphans = pList.get(PR_ORPHANS).getNumeric();
- ptr = pList.get(PR_X_PTR).getString(); //used for accessibility
whiteSpaceTreatment = pList.get(PR_WHITE_SPACE_TREATMENT).getEnum();
span = pList.get(PR_SPAN).getEnum();
textAlign = pList.get(PR_TEXT_ALIGN).getEnum();
@@ -149,6 +151,11 @@ public class Block extends FObjMixed implements BreakPropertySet, StructurePoint
getFOEventHandler().endBlock(this);
}
+ /** {@inheritDoc} */
+ public CommonAccessibility getCommonAccessibility() {
+ return commonAccessibility;
+ }
+
/** @return the {@link CommonMarginBlock} */
public CommonMarginBlock getCommonMarginBlock() {
return commonMarginBlock;
@@ -175,11 +182,6 @@ public class Block extends FObjMixed implements BreakPropertySet, StructurePoint
return breakAfter;
}
- /** {@inheritDoc} */
- public String getPtr() {
- return ptr;
- }
-
/** @return the "break-before" property. */
public int getBreakBefore() {
return breakBefore;
diff --git a/src/java/org/apache/fop/fo/flow/Character.java b/src/java/org/apache/fop/fo/flow/Character.java
index 7328b5644..c4de9fb72 100644
--- a/src/java/org/apache/fop/fo/flow/Character.java
+++ b/src/java/org/apache/fop/fo/flow/Character.java
@@ -24,6 +24,7 @@ import java.util.NoSuchElementException;
import org.xml.sax.Locator;
+import org.apache.fop.accessibility.StructureTreeElement;
import org.apache.fop.apps.FOPException;
import org.apache.fop.datatypes.Length;
import org.apache.fop.fo.CharIterator;
@@ -38,13 +39,13 @@ import org.apache.fop.fo.properties.CommonTextDecoration;
import org.apache.fop.fo.properties.KeepProperty;
import org.apache.fop.fo.properties.Property;
import org.apache.fop.fo.properties.SpaceProperty;
-import org.apache.fop.fo.properties.StructurePointerPropertySet;
+import org.apache.fop.fo.properties.StructureTreeElementHolder;
/**
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_character">
* <code>fo:character</code></a> object.
*/
-public class Character extends FObj implements StructurePointerPropertySet {
+public class Character extends FObj implements StructureTreeElementHolder {
// The value of properties relevant for fo:character.
private CommonBorderPaddingBackground commonBorderPaddingBackground;
private CommonFont commonFont;
@@ -63,7 +64,7 @@ public class Character extends FObj implements StructurePointerPropertySet {
private CommonTextDecoration textDecoration;
// private ToBeImplementedProperty textShadow;
private Property wordSpacing;
- private String ptr; // used for accessibility
+ private StructureTreeElement structureTreeElement;
// Unused but valid items, commented out for performance:
// private CommonAural commonAural;
// private CommonMarginInline commonMarginInline;
@@ -110,7 +111,6 @@ public class Character extends FObj implements StructurePointerPropertySet {
lineHeight = pList.get(PR_LINE_HEIGHT).getSpace();
textDecoration = pList.getTextDecorationProps();
wordSpacing = pList.get(PR_WORD_SPACING);
- ptr = pList.get(PR_X_PTR).getString(); // used for accessibility
}
/** {@inheritDoc} */
@@ -210,9 +210,14 @@ public class Character extends FObj implements StructurePointerPropertySet {
return keepWithPrevious;
}
+ @Override
+ public void setStructureTreeElement(StructureTreeElement structureTreeElement) {
+ this.structureTreeElement = structureTreeElement;
+ }
+
/** {@inheritDoc} */
- public String getPtr() {
- return ptr;
+ public StructureTreeElement getStructureTreeElement() {
+ return structureTreeElement;
}
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/fo/flow/Footnote.java b/src/java/org/apache/fop/fo/flow/Footnote.java
index 51d2581cd..5953363ed 100644
--- a/src/java/org/apache/fop/fo/flow/Footnote.java
+++ b/src/java/org/apache/fop/fo/flow/Footnote.java
@@ -26,15 +26,16 @@ import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
+import org.apache.fop.fo.properties.CommonAccessibility;
+import org.apache.fop.fo.properties.CommonAccessibilityHolder;
/**
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_footnote">
* <code>fo:footnote</code></a> object.
*/
-public class Footnote extends FObj {
- // The value of properties relevant for fo:footnote (commented out for performance).
- // private CommonAccessibility commonAccessibility;
- // End of property values
+public class Footnote extends FObj implements CommonAccessibilityHolder {
+
+ private CommonAccessibility commonAccessibility;
private Inline footnoteCitation = null;
private FootnoteBody footnoteBody;
@@ -51,7 +52,7 @@ public class Footnote extends FObj {
/** {@inheritDoc} */
public void bind(PropertyList pList) throws FOPException {
- // No active properties -> do nothing.
+ commonAccessibility = CommonAccessibility.getInstance(pList);
}
/** {@inheritDoc} */
@@ -110,6 +111,11 @@ public class Footnote extends FObj {
}
}
+ /** {@inheritDoc} */
+ public CommonAccessibility getCommonAccessibility() {
+ return commonAccessibility;
+ }
+
/**
* Public accessor for inline FO
*
diff --git a/src/java/org/apache/fop/fo/flow/FootnoteBody.java b/src/java/org/apache/fop/fo/flow/FootnoteBody.java
index eb26a2009..1c103b6b5 100644
--- a/src/java/org/apache/fop/fo/flow/FootnoteBody.java
+++ b/src/java/org/apache/fop/fo/flow/FootnoteBody.java
@@ -27,15 +27,17 @@ import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
+import org.apache.fop.fo.properties.CommonAccessibility;
+import org.apache.fop.fo.properties.CommonAccessibilityHolder;
/**
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_footnote-body">
* <code>fo:footnote-body</code></a> object.
*/
-public class FootnoteBody extends FObj {
- // The value of properties relevant for fo:footnote-body (commented out for perforance).
- // private CommonAccessibility commonAccessibility;
- // End of property values
+public class FootnoteBody extends FObj implements CommonAccessibilityHolder {
+
+ /** {@inheritDoc} */
+ private CommonAccessibility commonAccessibility;
/**
* Base constructor
@@ -48,6 +50,7 @@ public class FootnoteBody extends FObj {
/** {@inheritDoc} */
public void bind(PropertyList pList) throws FOPException {
+ commonAccessibility = CommonAccessibility.getInstance(pList);
}
/** {@inheritDoc} */
@@ -93,4 +96,10 @@ public class FootnoteBody extends FObj {
public int getNameId() {
return FO_FOOTNOTE_BODY;
}
+
+ /** {@inheritDoc} */
+ public CommonAccessibility getCommonAccessibility() {
+ return commonAccessibility;
+ }
+
}
diff --git a/src/java/org/apache/fop/fo/flow/InitialPropertySet.java b/src/java/org/apache/fop/fo/flow/InitialPropertySet.java
index 0df7379f2..b41021b75 100644
--- a/src/java/org/apache/fop/fo/flow/InitialPropertySet.java
+++ b/src/java/org/apache/fop/fo/flow/InitialPropertySet.java
@@ -27,19 +27,22 @@ import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
+import org.apache.fop.fo.properties.CommonAccessibility;
+import org.apache.fop.fo.properties.CommonAccessibilityHolder;
import org.apache.fop.fo.properties.SpaceProperty;
/**
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_initial-property-set">
* <code>fo:initial-property-set</code></a> object.
*/
-public class InitialPropertySet extends FObj {
- // The value of properties relevant for fo:initial-property-set.
+public class InitialPropertySet extends FObj implements CommonAccessibilityHolder {
+
+ private CommonAccessibility commonAccessibility;
+
// private ToBeImplementedProperty letterSpacing;
private SpaceProperty lineHeight;
// private ToBeImplementedProperty textShadow;
// Unused but valid items, commented out for performance:
- // private CommonAccessibility commonAccessibility;
// private CommonAural commonAural;
// private CommonBorderPaddingBackground commonBorderPaddingBackground;
// private CommonFont commonFont;
@@ -63,6 +66,7 @@ public class InitialPropertySet extends FObj {
/** {@inheritDoc} */
public void bind(PropertyList pList) throws FOPException {
super.bind(pList);
+ commonAccessibility = CommonAccessibility.getInstance(pList);
// letterSpacing = pList.get(PR_LETTER_SPACING);
lineHeight = pList.get(PR_LINE_HEIGHT).getSpace();
// textShadow = pList.get(PR_TEXT_SHADOW);
@@ -96,4 +100,10 @@ public class InitialPropertySet extends FObj {
public int getNameId() {
return FO_INITIAL_PROPERTY_SET;
}
+
+ /** {@inheritDoc} */
+ public CommonAccessibility getCommonAccessibility() {
+ return commonAccessibility;
+ }
+
}
diff --git a/src/java/org/apache/fop/fo/flow/Inline.java b/src/java/org/apache/fop/fo/flow/Inline.java
index d9ae63ec8..debf6bbf6 100644
--- a/src/java/org/apache/fop/fo/flow/Inline.java
+++ b/src/java/org/apache/fop/fo/flow/Inline.java
@@ -26,19 +26,17 @@ import org.apache.fop.datatypes.Length;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
-import org.apache.fop.fo.properties.StructurePointerPropertySet;
/**
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_inline">
* <code>fo:inline</code></a> formatting object.
*/
-public class Inline extends InlineLevel implements StructurePointerPropertySet {
+public class Inline extends InlineLevel {
// The value of properties relevant for fo:inline.
// See also superclass InlineLevel
private Length alignmentAdjust;
private int alignmentBaseline;
private Length baselineShift;
- private String ptr; // used for accessibility
private int dominantBaseline;
// Unused but valid items, commented out for performance:
// private CommonRelativePosition commonRelativePosition;
@@ -68,7 +66,6 @@ public class Inline extends InlineLevel implements StructurePointerPropertySet {
alignmentBaseline = pList.get(PR_ALIGNMENT_BASELINE).getEnum();
baselineShift = pList.get(PR_BASELINE_SHIFT).getLength();
dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum();
- ptr = pList.get(PR_X_PTR).getString(); // used for accessibility
}
/** {@inheritDoc} */
@@ -149,11 +146,6 @@ public class Inline extends InlineLevel implements StructurePointerPropertySet {
}
/** {@inheritDoc} */
- public String getPtr() {
- return ptr;
- }
-
- /** {@inheritDoc} */
public String getLocalName() {
return "inline";
}
diff --git a/src/java/org/apache/fop/fo/flow/InlineLevel.java b/src/java/org/apache/fop/fo/flow/InlineLevel.java
index 5410e1ca7..0da769080 100644
--- a/src/java/org/apache/fop/fo/flow/InlineLevel.java
+++ b/src/java/org/apache/fop/fo/flow/InlineLevel.java
@@ -25,6 +25,8 @@ import org.apache.fop.apps.FOPException;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FObjMixed;
import org.apache.fop.fo.PropertyList;
+import org.apache.fop.fo.properties.CommonAccessibility;
+import org.apache.fop.fo.properties.CommonAccessibilityHolder;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.CommonFont;
import org.apache.fop.fo.properties.CommonMarginInline;
@@ -35,9 +37,10 @@ import org.apache.fop.fo.properties.SpaceProperty;
* Class modelling the commonalities of several inline-level
* formatting objects.
*/
-public abstract class InlineLevel extends FObjMixed {
+public abstract class InlineLevel extends FObjMixed implements CommonAccessibilityHolder {
// The value of properties relevant for inline-level FOs.
+ private CommonAccessibility commonAccessibility;
private CommonBorderPaddingBackground commonBorderPaddingBackground;
private CommonMarginInline commonMarginInline;
private CommonFont commonFont;
@@ -59,6 +62,7 @@ public abstract class InlineLevel extends FObjMixed {
/** {@inheritDoc} */
public void bind(PropertyList pList) throws FOPException {
super.bind(pList);
+ commonAccessibility = CommonAccessibility.getInstance(pList);
commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
commonMarginInline = pList.getMarginInlineProps();
commonFont = pList.getFontProps();
@@ -68,6 +72,11 @@ public abstract class InlineLevel extends FObjMixed {
lineHeight = pList.get(PR_LINE_HEIGHT).getSpace();
}
+ /** {@inheritDoc} */
+ public CommonAccessibility getCommonAccessibility() {
+ return commonAccessibility;
+ }
+
/** @return the {@link CommonMarginInline} */
public CommonMarginInline getCommonMarginInline() {
return commonMarginInline;
diff --git a/src/java/org/apache/fop/fo/flow/InstreamForeignObject.java b/src/java/org/apache/fop/fo/flow/InstreamForeignObject.java
index 02d25f8dd..33164188f 100644
--- a/src/java/org/apache/fop/fo/flow/InstreamForeignObject.java
+++ b/src/java/org/apache/fop/fo/flow/InstreamForeignObject.java
@@ -59,6 +59,12 @@ public class InstreamForeignObject extends AbstractGraphics {
super(parent);
}
+ @Override
+ protected void startOfNode() throws FOPException {
+ super.startOfNode();
+ getFOEventHandler().startInstreamForeignObject(this);
+ }
+
/**
* Make sure content model satisfied, if so then tell the
* {@link org.apache.fop.fo.FOEventHandler} that we are at
@@ -69,7 +75,7 @@ public class InstreamForeignObject extends AbstractGraphics {
if (firstChild == null) {
missingChildElementError("one (1) non-XSL namespace child");
}
- getFOEventHandler().foreignObject(this);
+ getFOEventHandler().endInstreamForeignObject(this);
}
/**
diff --git a/src/java/org/apache/fop/fo/flow/Leader.java b/src/java/org/apache/fop/fo/flow/Leader.java
index 54027514c..f12930dde 100644
--- a/src/java/org/apache/fop/fo/flow/Leader.java
+++ b/src/java/org/apache/fop/fo/flow/Leader.java
@@ -158,4 +158,16 @@ public class Leader extends InlineLevel {
public int getNameId() {
return FO_LEADER;
}
+
+ @Override
+ protected void startOfNode() throws FOPException {
+ super.startOfNode();
+ getFOEventHandler().startLeader(this);
+ }
+
+ @Override
+ protected void endOfNode() throws FOPException {
+ super.endOfNode();
+ getFOEventHandler().endLeader(this);
+ }
}
diff --git a/src/java/org/apache/fop/fo/flow/ListBlock.java b/src/java/org/apache/fop/fo/flow/ListBlock.java
index 8f72ded67..35288ec80 100644
--- a/src/java/org/apache/fop/fo/flow/ListBlock.java
+++ b/src/java/org/apache/fop/fo/flow/ListBlock.java
@@ -28,6 +28,8 @@ import org.apache.fop.fo.FObj;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
import org.apache.fop.fo.properties.BreakPropertySet;
+import org.apache.fop.fo.properties.CommonAccessibility;
+import org.apache.fop.fo.properties.CommonAccessibilityHolder;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.CommonMarginBlock;
import org.apache.fop.fo.properties.KeepProperty;
@@ -36,8 +38,9 @@ import org.apache.fop.fo.properties.KeepProperty;
* Class modelling the <a href=http://www.w3.org/TR/xsl/#fo_list-block">
* <code>fo:list-block</code></a> object.
*/
-public class ListBlock extends FObj implements BreakPropertySet {
+public class ListBlock extends FObj implements BreakPropertySet, CommonAccessibilityHolder {
// The value of properties relevant for fo:list-block.
+ private CommonAccessibility commonAccessibility;
private CommonBorderPaddingBackground commonBorderPaddingBackground;
private CommonMarginBlock commonMarginBlock;
private int breakAfter;
@@ -46,7 +49,6 @@ public class ListBlock extends FObj implements BreakPropertySet {
private KeepProperty keepWithNext;
private KeepProperty keepWithPrevious;
// Unused but valid items, commented out for performance:
- // private CommonAccessibility commonAccessibility;
// private CommonAural commonAural;
// private CommonRelativePosition commonRelativePosition;
// private int intrusionDisplace;
@@ -73,6 +75,7 @@ public class ListBlock extends FObj implements BreakPropertySet {
/** {@inheritDoc} */
public void bind(PropertyList pList) throws FOPException {
super.bind(pList);
+ commonAccessibility = CommonAccessibility.getInstance(pList);
commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
commonMarginBlock = pList.getMarginBlockProps();
breakAfter = pList.get(PR_BREAK_AFTER).getEnum();
@@ -123,6 +126,11 @@ public class ListBlock extends FObj implements BreakPropertySet {
}
}
+ /** {@inheritDoc} */
+ public CommonAccessibility getCommonAccessibility() {
+ return commonAccessibility;
+ }
+
/** @return the {@link CommonMarginBlock} */
public CommonMarginBlock getCommonMarginBlock() {
return commonMarginBlock;
diff --git a/src/java/org/apache/fop/fo/flow/ListItem.java b/src/java/org/apache/fop/fo/flow/ListItem.java
index c4a2aa64b..aa177777c 100644
--- a/src/java/org/apache/fop/fo/flow/ListItem.java
+++ b/src/java/org/apache/fop/fo/flow/ListItem.java
@@ -27,6 +27,8 @@ import org.apache.fop.fo.FObj;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
import org.apache.fop.fo.properties.BreakPropertySet;
+import org.apache.fop.fo.properties.CommonAccessibility;
+import org.apache.fop.fo.properties.CommonAccessibilityHolder;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.CommonMarginBlock;
import org.apache.fop.fo.properties.KeepProperty;
@@ -35,8 +37,9 @@ import org.apache.fop.fo.properties.KeepProperty;
* Class modelling the <a href=http://www.w3.org/TR/xsl/#fo_list-item">
* <code>fo:list-item</code></a> object.
*/
-public class ListItem extends FObj implements BreakPropertySet {
+public class ListItem extends FObj implements BreakPropertySet, CommonAccessibilityHolder {
// The value of properties relevant for fo:list-item.
+ private CommonAccessibility commonAccessibility;
private CommonBorderPaddingBackground commonBorderPaddingBackground;
private CommonMarginBlock commonMarginBlock;
private int breakAfter;
@@ -45,7 +48,6 @@ public class ListItem extends FObj implements BreakPropertySet {
private KeepProperty keepWithNext;
private KeepProperty keepWithPrevious;
// Unused but valid items, commented out for performance:
- // private CommonAccessibility commonAccessibility;
// private CommonAural commonAural;
// private CommonRelativePosition commonRelativePosition;
// private int intrusionDisplace;
@@ -67,6 +69,7 @@ public class ListItem extends FObj implements BreakPropertySet {
/** {@inheritDoc} */
public void bind(PropertyList pList) throws FOPException {
super.bind(pList);
+ commonAccessibility = CommonAccessibility.getInstance(pList);
commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
commonMarginBlock = pList.getMarginBlockProps();
breakAfter = pList.get(PR_BREAK_AFTER).getEnum();
@@ -134,6 +137,11 @@ public class ListItem extends FObj implements BreakPropertySet {
}
}
+ /** {@inheritDoc} */
+ public CommonAccessibility getCommonAccessibility() {
+ return commonAccessibility;
+ }
+
/** @return the {@link CommonMarginBlock} */
public CommonMarginBlock getCommonMarginBlock() {
return commonMarginBlock;
diff --git a/src/java/org/apache/fop/fo/flow/ListItemBody.java b/src/java/org/apache/fop/fo/flow/ListItemBody.java
index 853beb20b..3007f9ba3 100644
--- a/src/java/org/apache/fop/fo/flow/ListItemBody.java
+++ b/src/java/org/apache/fop/fo/flow/ListItemBody.java
@@ -38,13 +38,13 @@ public class ListItemBody extends AbstractListItemPart {
/** {@inheritDoc} */
protected void startOfNode() throws FOPException {
super.startOfNode();
- getFOEventHandler().startListBody();
+ getFOEventHandler().startListBody(this);
}
/** {@inheritDoc} */
protected void endOfNode() throws FOPException {
super.endOfNode();
- getFOEventHandler().endListBody();
+ getFOEventHandler().endListBody(this);
}
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/fo/flow/ListItemLabel.java b/src/java/org/apache/fop/fo/flow/ListItemLabel.java
index 1c757686c..10436afa6 100644
--- a/src/java/org/apache/fop/fo/flow/ListItemLabel.java
+++ b/src/java/org/apache/fop/fo/flow/ListItemLabel.java
@@ -40,13 +40,13 @@ public class ListItemLabel extends AbstractListItemPart {
/** {@inheritDoc} */
protected void startOfNode() throws FOPException {
super.startOfNode();
- getFOEventHandler().startListLabel();
+ getFOEventHandler().startListLabel(this);
}
/** {@inheritDoc} */
protected void endOfNode() throws FOPException {
super.endOfNode();
- getFOEventHandler().endListLabel();
+ getFOEventHandler().endListLabel(this);
}
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/fo/flow/PageNumber.java b/src/java/org/apache/fop/fo/flow/PageNumber.java
index 34d267a64..59169c2d3 100644
--- a/src/java/org/apache/fop/fo/flow/PageNumber.java
+++ b/src/java/org/apache/fop/fo/flow/PageNumber.java
@@ -23,6 +23,7 @@ import java.awt.Color;
import org.xml.sax.Locator;
+import org.apache.fop.accessibility.StructureTreeElement;
import org.apache.fop.apps.FOPException;
import org.apache.fop.datatypes.Length;
import org.apache.fop.fo.Constants;
@@ -30,32 +31,35 @@ import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
+import org.apache.fop.fo.properties.CommonAccessibility;
+import org.apache.fop.fo.properties.CommonAccessibilityHolder;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.CommonFont;
import org.apache.fop.fo.properties.CommonTextDecoration;
import org.apache.fop.fo.properties.SpaceProperty;
-import org.apache.fop.fo.properties.StructurePointerPropertySet;
+import org.apache.fop.fo.properties.StructureTreeElementHolder;
/**
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_page-number">
* <code>fo:page-number</code></a> object.
*/
-public class PageNumber extends FObj implements StructurePointerPropertySet {
+public class PageNumber extends FObj
+ implements StructureTreeElementHolder, CommonAccessibilityHolder {
// The value of properties relevant for fo:page-number.
+ private CommonAccessibility commonAccessibility;
private CommonBorderPaddingBackground commonBorderPaddingBackground;
private CommonFont commonFont;
private Length alignmentAdjust;
private int alignmentBaseline;
private Length baselineShift;
private int dominantBaseline;
- private String ptr; // used for accessibility
+ private StructureTreeElement structureTreeElement;
// private ToBeImplementedProperty letterSpacing;
private SpaceProperty lineHeight;
/** Holds the text decoration values. May be null */
private CommonTextDecoration textDecoration;
// private ToBeImplementedProperty textShadow;
// Unused but valid items, commented out for performance:
- // private CommonAccessibility commonAccessibility;
// private CommonAural commonAural;
// private CommonMarginInline commonMarginInline;
// private CommonRelativePosition commonRelativePosition;
@@ -85,6 +89,7 @@ public class PageNumber extends FObj implements StructurePointerPropertySet {
/** {@inheritDoc} */
public void bind(PropertyList pList) throws FOPException {
super.bind(pList);
+ commonAccessibility = CommonAccessibility.getInstance(pList);
commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
commonFont = pList.getFontProps();
alignmentAdjust = pList.get(PR_ALIGNMENT_ADJUST).getLength();
@@ -94,7 +99,6 @@ public class PageNumber extends FObj implements StructurePointerPropertySet {
// letterSpacing = pList.get(PR_LETTER_SPACING);
lineHeight = pList.get(PR_LINE_HEIGHT).getSpace();
textDecoration = pList.getTextDecorationProps();
- ptr = pList.get(PR_X_PTR).getString(); // used for accessibility
// textShadow = pList.get(PR_TEXT_SHADOW);
// implicit properties
@@ -123,6 +127,11 @@ public class PageNumber extends FObj implements StructurePointerPropertySet {
}
}
+ /** {@inheritDoc} */
+ public CommonAccessibility getCommonAccessibility() {
+ return commonAccessibility;
+ }
+
/** @return the Common Font Properties. */
public CommonFont getCommonFont() {
return commonFont;
@@ -168,9 +177,14 @@ public class PageNumber extends FObj implements StructurePointerPropertySet {
return lineHeight;
}
+ @Override
+ public void setStructureTreeElement(StructureTreeElement structureTreeElement) {
+ this.structureTreeElement = structureTreeElement;
+ }
+
/** {@inheritDoc} */
- public String getPtr() {
- return ptr;
+ public StructureTreeElement getStructureTreeElement() {
+ return structureTreeElement;
}
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/fo/flow/Wrapper.java b/src/java/org/apache/fop/fo/flow/Wrapper.java
index 7fb412521..6c5619252 100644
--- a/src/java/org/apache/fop/fo/flow/Wrapper.java
+++ b/src/java/org/apache/fop/fo/flow/Wrapper.java
@@ -51,6 +51,18 @@ public class Wrapper extends FObjMixed {
super(parent);
}
+ @Override
+ protected void startOfNode() throws FOPException {
+ super.startOfNode();
+ getFOEventHandler().startWrapper(this);
+ }
+
+ @Override
+ protected void endOfNode() throws FOPException {
+ super.endOfNode();
+ getFOEventHandler().endWrapper(this);
+ }
+
/**
* {@inheritDoc}
* <br>XSL Content Model: marker* (#PCDATA|%inline;|%block;)*
diff --git a/src/java/org/apache/fop/fo/flow/table/Table.java b/src/java/org/apache/fop/fo/flow/table/Table.java
index 86196cb29..c78f9f959 100644
--- a/src/java/org/apache/fop/fo/flow/table/Table.java
+++ b/src/java/org/apache/fop/fo/flow/table/Table.java
@@ -32,6 +32,8 @@ import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.StaticPropertyList;
import org.apache.fop.fo.ValidationException;
import org.apache.fop.fo.properties.BreakPropertySet;
+import org.apache.fop.fo.properties.CommonAccessibility;
+import org.apache.fop.fo.properties.CommonAccessibilityHolder;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.CommonMarginBlock;
import org.apache.fop.fo.properties.KeepProperty;
@@ -43,9 +45,11 @@ import org.apache.fop.fo.properties.TableColLength;
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_table">
* <code>fo:table</code></a> object.
*/
-public class Table extends TableFObj implements ColumnNumberManagerHolder, BreakPropertySet {
+public class Table extends TableFObj implements ColumnNumberManagerHolder, BreakPropertySet,
+ CommonAccessibilityHolder {
/** properties */
+ private CommonAccessibility commonAccessibility;
private CommonBorderPaddingBackground commonBorderPaddingBackground;
private CommonMarginBlock commonMarginBlock;
private LengthRangeProperty blockProgressionDimension;
@@ -61,7 +65,6 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder, Break
private int tableOmitFooterAtBreak;
private int tableOmitHeaderAtBreak;
// Unused but valid items, commented out for performance:
- // private CommonAccessibility commonAccessibility;
// private CommonAural commonAural;
// private CommonRelativePosition commonRelativePosition;
// private int intrusionDisplace;
@@ -112,6 +115,7 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder, Break
*/
public void bind(PropertyList pList) throws FOPException {
super.bind(pList);
+ commonAccessibility = CommonAccessibility.getInstance(pList);
commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
commonMarginBlock = pList.getMarginBlockProps();
blockProgressionDimension = pList.get(PR_BLOCK_PROGRESSION_DIMENSION).getLengthRange();
@@ -302,6 +306,11 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder, Break
}
/** {@inheritDoc} */
+ public CommonAccessibility getCommonAccessibility() {
+ return commonAccessibility;
+ }
+
+ /** {@inheritDoc} */
public Table getTable() {
return this;
}
diff --git a/src/java/org/apache/fop/fo/flow/table/TableAndCaption.java b/src/java/org/apache/fop/fo/flow/table/TableAndCaption.java
index 634460ec4..51db27e4e 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableAndCaption.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableAndCaption.java
@@ -25,17 +25,22 @@ import org.xml.sax.Locator;
import org.apache.fop.apps.FOPException;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FObj;
+import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
+import org.apache.fop.fo.properties.CommonAccessibility;
+import org.apache.fop.fo.properties.CommonAccessibilityHolder;
/**
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_table-and-caption">
* <code>fo:table-and-caption</code></a> property.
* TODO needs implementation
*/
-public class TableAndCaption extends FObj /*implements BreakPropertySet*/ {
+public class TableAndCaption extends FObj implements CommonAccessibilityHolder {
+
+ private CommonAccessibility commonAccessibility;
+
// The value of properties relevant for fo:table-and-caption.
// Unused but valid items, commented out for performance:
- // private CommonAccessibility commonAccessibility;
// private CommonAural commonAural;
// private CommonBorderPaddingBackground commonBorderPaddingBackground;
// private CommonMarginBlock commonMarginBlock;
@@ -50,7 +55,7 @@ public class TableAndCaption extends FObj /*implements BreakPropertySet*/ {
// private int textAlign;
// End of property values
- private static boolean notImplementedWarningGiven = false;
+ static boolean notImplementedWarningGiven = false; // CSOK: VisibilityModifier
/** used for FO validation */
private boolean tableCaptionFound = false;
@@ -71,6 +76,12 @@ public class TableAndCaption extends FObj /*implements BreakPropertySet*/ {
}
}
+ @Override
+ public void bind(PropertyList pList) throws FOPException {
+ super.bind(pList);
+ commonAccessibility = CommonAccessibility.getInstance(pList);
+ }
+
/**
* Make sure content model satisfied, if so then tell the
* FOEventHandler that we are at the end of the flow.
@@ -128,5 +139,11 @@ public class TableAndCaption extends FObj /*implements BreakPropertySet*/ {
public int getNameId() {
return FO_TABLE_AND_CAPTION;
}
+
+ /** {@inheritDoc} */
+ public CommonAccessibility getCommonAccessibility() {
+ return commonAccessibility;
+ }
+
}
diff --git a/src/java/org/apache/fop/fo/flow/table/TableCaption.java b/src/java/org/apache/fop/fo/flow/table/TableCaption.java
index fc5d3d5b7..380b27f34 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableCaption.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableCaption.java
@@ -27,13 +27,18 @@ import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
+import org.apache.fop.fo.properties.CommonAccessibility;
+import org.apache.fop.fo.properties.CommonAccessibilityHolder;
/**
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_table-caption">
* <code>fo:table-caption</code></a> object.
*/
-public class TableCaption extends FObj {
+public class TableCaption extends FObj implements CommonAccessibilityHolder {
+
+ private CommonAccessibility commonAccessibility;
+
// The value of properties relevant for fo:table-caption.
// Unused but valid items, commented out for performance:
// private CommonAural commonAural;
@@ -49,7 +54,7 @@ public class TableCaption extends FObj {
/** used for FO validation */
private boolean blockItemFound = false;
- private static boolean notImplementedWarningGiven = false;
+ static boolean notImplementedWarningGiven = false; // CSOK: VisibilityModifier
/**
* Create a TableCaption instance with the given {@link FONode}
@@ -69,6 +74,7 @@ public class TableCaption extends FObj {
/** {@inheritDoc} */
public void bind(PropertyList pList) throws FOPException {
super.bind(pList);
+ commonAccessibility = CommonAccessibility.getInstance(pList);
}
/** {@inheritDoc} */
@@ -109,5 +115,11 @@ public class TableCaption extends FObj {
public int getNameId() {
return FO_TABLE_CAPTION;
}
+
+ /** {@inheritDoc} */
+ public CommonAccessibility getCommonAccessibility() {
+ return commonAccessibility;
+ }
+
}
diff --git a/src/java/org/apache/fop/fo/flow/table/TableCell.java b/src/java/org/apache/fop/fo/flow/table/TableCell.java
index 637ee2a9a..c4f9c2aa6 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableCell.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableCell.java
@@ -26,6 +26,8 @@ import org.apache.fop.datatypes.Length;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
+import org.apache.fop.fo.properties.CommonAccessibility;
+import org.apache.fop.fo.properties.CommonAccessibilityHolder;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.LengthRangeProperty;
@@ -33,8 +35,9 @@ import org.apache.fop.fo.properties.LengthRangeProperty;
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_table-cell">
* <code>fo:table-cell</code></a> object.
*/
-public class TableCell extends TableFObj {
+public class TableCell extends TableFObj implements CommonAccessibilityHolder {
// The value of properties relevant for fo:table-cell.
+ private CommonAccessibility commonAccessibility;
private CommonBorderPaddingBackground commonBorderPaddingBackground;
private LengthRangeProperty blockProgressionDimension;
private int columnNumber;
@@ -46,7 +49,6 @@ public class TableCell extends TableFObj {
private int startsRow;
private Length width;
// Unused but valid items, commented out for performance:
- // private CommonAccessibility commonAccessibility;
// private CommonAural commonAural;
// private CommonRelativePosition commonRelativePosition;
// private int relativeAlign;
@@ -74,6 +76,7 @@ public class TableCell extends TableFObj {
*/
public void bind(PropertyList pList) throws FOPException {
super.bind(pList);
+ commonAccessibility = CommonAccessibility.getInstance(pList);
commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
blockProgressionDimension = pList.get(PR_BLOCK_PROGRESSION_DIMENSION).getLengthRange();
displayAlign = pList.get(PR_DISPLAY_ALIGN).getEnum();
@@ -145,6 +148,11 @@ public class TableCell extends TableFObj {
return true;
}
+ /** {@inheritDoc} */
+ public CommonAccessibility getCommonAccessibility() {
+ return commonAccessibility;
+ }
+
/**
* Get the {@link CommonBorderPaddingBackground} instance
* attached to this TableCell.
diff --git a/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java b/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java
index 41eab578f..89ecd159a 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java
@@ -24,11 +24,17 @@ import java.util.List;
import org.apache.fop.apps.FOPException;
import org.apache.fop.datatypes.Length;
import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.PropertyList;
+import org.apache.fop.fo.properties.CommonAccessibility;
+import org.apache.fop.fo.properties.CommonAccessibilityHolder;
/**
* A common class for fo:table-body and fo:table-row which both can contain fo:table-cell.
*/
-public abstract class TableCellContainer extends TableFObj implements ColumnNumberManagerHolder {
+public abstract class TableCellContainer extends TableFObj
+ implements ColumnNumberManagerHolder, CommonAccessibilityHolder {
+
+ private CommonAccessibility commonAccessibility;
/** list of pending spans */
protected List pendingSpans;
@@ -44,6 +50,12 @@ public abstract class TableCellContainer extends TableFObj implements ColumnNumb
super(parent);
}
+ @Override
+ public void bind(PropertyList pList) throws FOPException {
+ super.bind(pList);
+ commonAccessibility = CommonAccessibility.getInstance(pList);
+ }
+
/**
* Add cell to current row.
* @param cell a table cell to add
@@ -116,4 +128,9 @@ public abstract class TableCellContainer extends TableFObj implements ColumnNumb
return columnNumberManager;
}
+ /** {@inheritDoc} */
+ public CommonAccessibility getCommonAccessibility() {
+ return commonAccessibility;
+ }
+
}
diff --git a/src/java/org/apache/fop/fo/flow/table/TableFObj.java b/src/java/org/apache/fop/fo/flow/table/TableFObj.java
index fce82dcff..2506c26b4 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableFObj.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableFObj.java
@@ -36,19 +36,17 @@ import org.apache.fop.fo.properties.EnumProperty;
import org.apache.fop.fo.properties.NumberProperty;
import org.apache.fop.fo.properties.Property;
import org.apache.fop.fo.properties.PropertyMaker;
-import org.apache.fop.fo.properties.StructurePointerPropertySet;
import org.apache.fop.layoutmgr.table.CollapsingBorderModel;
/**
* Common base class for table-related FOs
*/
-public abstract class TableFObj extends FObj implements StructurePointerPropertySet {
+public abstract class TableFObj extends FObj {
private Numeric borderAfterPrecedence;
private Numeric borderBeforePrecedence;
private Numeric borderEndPrecedence;
private Numeric borderStartPrecedence;
- private String ptr;
ConditionalBorder borderBefore; // CSOK: VisibilityModifier
ConditionalBorder borderAfter; // CSOK: VisibilityModifier
@@ -74,7 +72,6 @@ public abstract class TableFObj extends FObj implements StructurePointerProperty
borderBeforePrecedence = pList.get(PR_BORDER_BEFORE_PRECEDENCE).getNumeric();
borderEndPrecedence = pList.get(PR_BORDER_END_PRECEDENCE).getNumeric();
borderStartPrecedence = pList.get(PR_BORDER_START_PRECEDENCE).getNumeric();
- ptr = pList.get(PR_X_PTR).getString();
if (getNameId() != FO_TABLE //Separate check for fo:table in Table.java
&& getNameId() != FO_TABLE_CELL
&& getCommonBorderPaddingBackground().hasPadding(
@@ -241,11 +238,6 @@ public abstract class TableFObj extends FObj implements StructurePointerProperty
}
}
- /** {@inheritDoc} */
- public String getPtr() {
- return ptr;
- }
-
/**
* Prepares the borders of this element if the collapsing-border model is in use.
* Conflict resolution with parent elements is done where applicable.
diff --git a/src/java/org/apache/fop/fo/pagination/Root.java b/src/java/org/apache/fop/fo/pagination/Root.java
index fb69dc2f1..1a2ce718b 100644
--- a/src/java/org/apache/fop/fo/pagination/Root.java
+++ b/src/java/org/apache/fop/fo/pagination/Root.java
@@ -21,6 +21,7 @@ package org.apache.fop.fo.pagination;
// java
import java.util.List;
+import java.util.Locale;
import org.xml.sax.Locator;
@@ -33,22 +34,26 @@ import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
import org.apache.fop.fo.extensions.destination.Destination;
import org.apache.fop.fo.pagination.bookmarks.BookmarkTree;
+import org.apache.fop.fo.properties.CommonAccessibility;
+import org.apache.fop.fo.properties.CommonAccessibilityHolder;
/**
* Class modeling the <a href="http://www.w3.org/TR/xsl/#fo_root">
* <code>fo:root</code></a> formatting object.
* Contains page masters, page-sequences.
*/
-public class Root extends FObj {
- // The value of properties relevant for fo:root.
+public class Root extends FObj implements CommonAccessibilityHolder {
+
+ private CommonAccessibility commonAccessibility;
+
private int mediaUsage;
- // End of property values
private LayoutMasterSet layoutMasterSet;
private Declarations declarations;
private BookmarkTree bookmarkTree = null;
private List<Destination> destinationList;
private List<PageSequence> pageSequences;
+ private Locale locale;
// temporary until above list populated
private boolean pageSequenceFound = false;
@@ -83,7 +88,26 @@ public class Root extends FObj {
/** {@inheritDoc} */
public void bind(PropertyList pList) throws FOPException {
super.bind(pList);
+ commonAccessibility = CommonAccessibility.getInstance(pList);
mediaUsage = pList.get(PR_MEDIA_USAGE).getEnum();
+ String language = pList.get(PR_LANGUAGE).getString();
+ String country = pList.get(PR_COUNTRY).getString();
+ if (isLocalePropertySet(language)) {
+ if (isLocalePropertySet(country)) {
+ locale = new Locale(language, country);
+ } else {
+ locale = new Locale(language);
+ }
+ }
+ }
+
+ private boolean isLocalePropertySet(String property) {
+ return property != null && !property.equals("none");
+ }
+
+ /** {@inheritDoc} */
+ protected void startOfNode() throws FOPException {
+ foEventHandler.startRoot(this);
}
/** {@inheritDoc} */
@@ -92,6 +116,7 @@ public class Root extends FObj {
missingChildElementError("(layout-master-set, declarations?, "
+ "bookmark-tree?, (page-sequence|fox:external-document)+)");
}
+ foEventHandler.endRoot(this);
}
/**
@@ -156,6 +181,11 @@ public class Root extends FObj {
}
}
+ /** {@inheritDoc} */
+ public CommonAccessibility getCommonAccessibility() {
+ return commonAccessibility;
+ }
+
/**
* Sets the FOEventHandler object that this Root is attached to
* @param foEventHandler the FOEventHandler object
@@ -335,4 +365,10 @@ public class Root extends FObj {
return FO_ROOT;
}
+
+ /** @return locale proprty. */
+ public Locale getLocale() {
+ return locale;
+ }
+
}
diff --git a/src/java/org/apache/fop/fo/pagination/StaticContent.java b/src/java/org/apache/fop/fo/pagination/StaticContent.java
index 4084a250a..e70c80c5d 100644
--- a/src/java/org/apache/fop/fo/pagination/StaticContent.java
+++ b/src/java/org/apache/fop/fo/pagination/StaticContent.java
@@ -44,7 +44,7 @@ public class StaticContent extends Flow {
if (getFlowName() == null || getFlowName().equals("")) {
missingPropertyError("flow-name");
}
- getFOEventHandler().startFlow(this);
+ getFOEventHandler().startStatic(this);
}
/**
@@ -56,7 +56,7 @@ public class StaticContent extends Flow {
if (firstChild == null && getUserAgent().validateStrictly()) {
missingChildElementError("(%block;)+");
}
- getFOEventHandler().endFlow(this);
+ getFOEventHandler().endStatic(this);
}
/**
diff --git a/src/java/org/apache/fop/fo/pagination/bookmarks/Bookmark.java b/src/java/org/apache/fop/fo/pagination/bookmarks/Bookmark.java
index 5969729d4..9e7d80cea 100644
--- a/src/java/org/apache/fop/fo/pagination/bookmarks/Bookmark.java
+++ b/src/java/org/apache/fop/fo/pagination/bookmarks/Bookmark.java
@@ -22,11 +22,14 @@ package org.apache.fop.fo.pagination.bookmarks;
import java.util.ArrayList;
import org.xml.sax.Locator;
+
import org.apache.fop.apps.FOPException;
-import org.apache.fop.fo.FObj;
import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.FObj;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
+import org.apache.fop.fo.properties.CommonAccessibility;
+import org.apache.fop.fo.properties.CommonAccessibilityHolder;
/**
@@ -34,11 +37,12 @@ import org.apache.fop.fo.ValidationException;
* <code>fo:bookmark</code></a> object, first introduced in the
* XSL 1.1 WD.
*/
-public class Bookmark extends FObj {
+public class Bookmark extends FObj implements CommonAccessibilityHolder {
private BookmarkTitle bookmarkTitle;
private ArrayList childBookmarks = new ArrayList();
// The value of properties relevant for this FO
+ private CommonAccessibility commonAccessibility;
private String internalDestination;
private String externalDestination;
private boolean bShow = true; // from starting-state property
@@ -59,6 +63,7 @@ public class Bookmark extends FObj {
/** {@inheritDoc} */
public void bind(PropertyList pList) throws FOPException {
+ commonAccessibility = CommonAccessibility.getInstance(pList);
externalDestination = pList.get(PR_EXTERNAL_DESTINATION).getString();
internalDestination = pList.get(PR_INTERNAL_DESTINATION).getString();
bShow = (pList.get(PR_STARTING_STATE).getEnum() == EN_SHOW);
@@ -112,6 +117,11 @@ public class Bookmark extends FObj {
}
}
+ /** {@inheritDoc} */
+ public CommonAccessibility getCommonAccessibility() {
+ return commonAccessibility;
+ }
+
/**
* Get the bookmark title for this bookmark
*
diff --git a/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTitle.java b/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTitle.java
index 028cdc7df..1db7d84ca 100644
--- a/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTitle.java
+++ b/src/java/org/apache/fop/fo/pagination/bookmarks/BookmarkTitle.java
@@ -21,17 +21,23 @@ package org.apache.fop.fo.pagination.bookmarks;
import org.xml.sax.Locator;
+import org.apache.fop.apps.FOPException;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
+import org.apache.fop.fo.properties.CommonAccessibility;
+import org.apache.fop.fo.properties.CommonAccessibilityHolder;
/**
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_bookmark-title">
* <code>fo:bookmark-title</code></a> object, first introduced in the
* XSL 1.1 WD.
*/
-public class BookmarkTitle extends FObj {
+public class BookmarkTitle extends FObj implements CommonAccessibilityHolder {
+
+ private CommonAccessibility commonAccessibility;
+
private String title = "";
/**
@@ -44,6 +50,12 @@ public class BookmarkTitle extends FObj {
super(parent);
}
+ @Override
+ public void bind(PropertyList pList) throws FOPException {
+ super.bind(pList);
+ commonAccessibility = CommonAccessibility.getInstance(pList);
+ }
+
/**
* Add the characters to this BookmarkTitle.
* The text data inside the BookmarkTitle xml element
@@ -72,6 +84,11 @@ public class BookmarkTitle extends FObj {
}
}
+ /** {@inheritDoc} */
+ public CommonAccessibility getCommonAccessibility() {
+ return commonAccessibility;
+ }
+
/**
* Get the title for this BookmarkTitle.
*
diff --git a/src/java/org/apache/fop/fo/properties/CommonAccessibility.java b/src/java/org/apache/fop/fo/properties/CommonAccessibility.java
index dc17228d2..85183b01f 100644
--- a/src/java/org/apache/fop/fo/properties/CommonAccessibility.java
+++ b/src/java/org/apache/fop/fo/properties/CommonAccessibility.java
@@ -24,37 +24,62 @@ import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.expr.PropertyException;
/**
- * Store all common accessibility properties.
- * See Sec 7.4 of the XSL-FO Standard.
- * Public "structure" allows direct member access.
+ * The "role" and "source-document" properties, see Section 7.5 of the XSL-FO 1.1
+ * Recommendation.
*/
-public class CommonAccessibility {
- /**
- * The "source-doc" property.
- */
- public String sourceDoc = null; // CSOK: VisibilityModifier
+public final class CommonAccessibility {
- /**
- * The "role" property.
- */
- public String role = null; // CSOK: VisibilityModifier
+ private static final CommonAccessibility DEFAULT_INSTANCE = new CommonAccessibility(null, null);
+
+ private final String sourceDocument;
+
+ private final String role;
+
+ private CommonAccessibility(String sourceDocument, String role) {
+ this.sourceDocument = sourceDocument;
+ this.role = role;
+ }
/**
- * Create a <code>CommonAccessibility</code> object.
- * @param pList The PropertyList with propery values.
- * @throws PropertyException if a property exception is raised
+ * Returns an instance that matches the values (if any) in the given property list.
+ *
+ * @param propertyList a list from which to retrieve the accessibility properties
+ * @return the corresponding instance
+ * @throws PropertyException if a problem occurs while retrieving the properties
*/
- public CommonAccessibility(PropertyList pList) throws PropertyException {
- sourceDoc = pList.get(Constants.PR_SOURCE_DOCUMENT).getString();
- if ("none".equals(sourceDoc)) {
- sourceDoc = null;
+ public static CommonAccessibility getInstance(PropertyList propertyList)
+ throws PropertyException {
+ String sourceDocument = propertyList.get(Constants.PR_SOURCE_DOCUMENT).getString();
+ if ("none".equals(sourceDocument)) {
+ sourceDocument = null;
}
- role = pList.get(Constants.PR_ROLE).getString();
+ String role = propertyList.get(Constants.PR_ROLE).getString();
if ("none".equals(role)) {
role = null;
}
+ if (sourceDocument == null && role == null) {
+ return DEFAULT_INSTANCE;
+ } else {
+ return new CommonAccessibility(sourceDocument, role);
+ }
+ }
+ /**
+ * Returns the value of the source-document property.
+ *
+ * @return the source document, or null if the property was set to "none"
+ */
+ public String getSourceDocument() {
+ return sourceDocument;
}
+ /**
+ * Returns the value of the role property.
+ *
+ * @return the role, or null if the property was set to "none"
+ */
+ public String getRole() {
+ return role;
+ }
}
diff --git a/src/java/org/apache/fop/fo/properties/StructurePointerPropertySet.java b/src/java/org/apache/fop/fo/properties/CommonAccessibilityHolder.java
index 5cce2822e..745c0cf0e 100644
--- a/src/java/org/apache/fop/fo/properties/StructurePointerPropertySet.java
+++ b/src/java/org/apache/fop/fo/properties/CommonAccessibilityHolder.java
@@ -20,15 +20,16 @@
package org.apache.fop.fo.properties;
/**
- * Defines property access methods for internal structure pointer extension properties.
+ * Classes that implement this interface support the common accessibility properties.
+ *
+ * @see CommonAccessibility
*/
-public interface StructurePointerPropertySet {
+public interface CommonAccessibilityHolder {
/**
- * Returns the value of the "foi:ptr" property, the internal structure pointer used
- * for tagged PDF and other formats that support a structure tree in addition to paged content.
- * @return the "foi:ptr" property
+ * Returns the accessibility properties.
+ *
+ * @return the accessibility properties
*/
- String getPtr();
-
+ CommonAccessibility getCommonAccessibility();
}
diff --git a/src/java/org/apache/fop/fo/properties/StructureTreeElementHolder.java b/src/java/org/apache/fop/fo/properties/StructureTreeElementHolder.java
new file mode 100644
index 000000000..6fbb608de
--- /dev/null
+++ b/src/java/org/apache/fop/fo/properties/StructureTreeElementHolder.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.fo.properties;
+
+import org.apache.fop.accessibility.StructureTreeElement;
+
+/**
+ * Implementations of this interface can return the element in the document's
+ * structure tree that they resulted into. Used for tagged PDF and other formats
+ * that support a structure tree in addition to paged content.
+ */
+public interface StructureTreeElementHolder {
+
+ /**
+ * Returns the element in the document's structure tree that corresponds to this instance.
+ *
+ * @return a structure tree element
+ */
+ StructureTreeElement getStructureTreeElement();
+
+}
diff --git a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java
index b748c2152..ed2ea4ee9 100644
--- a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java
@@ -329,7 +329,6 @@ public class BlockLayoutManager extends BlockStackingLayoutManager
addMarkersToPage(false, isFirst(firstPos), isLast(lastPos));
- TraitSetter.addPtr(curBlockArea, getBlockFO().getPtr()); // used for accessibility
TraitSetter.addSpaceBeforeAfter(curBlockArea, layoutContext.getSpaceAdjust(),
effSpaceBefore, effSpaceAfter);
flush();
diff --git a/src/java/org/apache/fop/layoutmgr/TraitSetter.java b/src/java/org/apache/fop/layoutmgr/TraitSetter.java
index c0e451577..0ae499478 100644
--- a/src/java/org/apache/fop/layoutmgr/TraitSetter.java
+++ b/src/java/org/apache/fop/layoutmgr/TraitSetter.java
@@ -22,6 +22,7 @@ package org.apache.fop.layoutmgr;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.fop.accessibility.StructureTreeElement;
import org.apache.fop.area.Area;
import org.apache.fop.area.Trait;
import org.apache.fop.datatypes.LengthBase;
@@ -29,9 +30,9 @@ import org.apache.fop.datatypes.PercentBaseContext;
import org.apache.fop.datatypes.SimplePercentBaseContext;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
+import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
import org.apache.fop.fo.properties.CommonMarginBlock;
import org.apache.fop.fo.properties.CommonTextDecoration;
-import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
import org.apache.fop.fonts.Font;
import org.apache.fop.traits.BorderProps;
import org.apache.fop.traits.MinOptMax;
@@ -591,13 +592,15 @@ public final class TraitSetter {
}
/**
- * Adds the ptr trait to the area.
+ * Sets the structure tree element associated to the given area.
+ *
* @param area the area to set the traits on
- * @param ptr string
+ * @param structureTreeElement the element the area is associated to in the document structure
*/
- public static void addPtr(Area area, String ptr) {
- if (ptr != null && ptr.length() > 0) {
- area.addTrait(Trait.PTR, ptr);
+ public static void addStructureTreeElement(Area area,
+ StructureTreeElement structureTreeElement) {
+ if (structureTreeElement != null) {
+ area.addTrait(Trait.STRUCTURE_TREE_ELEMENT, structureTreeElement);
}
}
diff --git a/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java
index 218497a53..8c797a48c 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java
@@ -85,7 +85,7 @@ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManage
transferForeignAttributes(viewportArea);
InlineViewport vp = new InlineViewport(viewportArea);
- TraitSetter.addPtr(vp, fobj.getPtr()); // used for accessibility
+ TraitSetter.addStructureTreeElement(vp, fobj.getStructureTreeElement());
TraitSetter.setProducerID(vp, fobj.getId());
vp.setIPD(imageLayout.getViewportSize().width);
vp.setBPD(imageLayout.getViewportSize().height);
diff --git a/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java
index e090fbae6..8c769924a 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java
@@ -136,7 +136,7 @@ public abstract class AbstractPageNumberCitationLayoutManager extends LeafNodeLa
text.setBaselineOffset(font.getAscender());
TraitSetter.addFontTraits(text, font);
text.addTrait(Trait.COLOR, fobj.getColor());
- TraitSetter.addPtr(text, fobj.getPtr()); // used for accessibility
+ TraitSetter.addStructureTreeElement(text, fobj.getStructureTreeElement());
TraitSetter.addTextDecoration(text, fobj.getTextDecoration());
}
diff --git a/src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java
index 40c9a324e..1390c04d8 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/BasicLinkLayoutManager.java
@@ -59,7 +59,7 @@ public class BasicLinkLayoutManager extends InlineLayoutManager {
private void setupBasicLinkArea(InlineArea area) {
BasicLink fobj = (BasicLink) this.fobj;
// internal destinations take precedence:
- TraitSetter.addPtr(area, fobj.getPtr()); // used for accessibility
+ TraitSetter.addStructureTreeElement(area, fobj.getStructureTreeElement());
if (fobj.hasInternalDestination()) {
String idref = fobj.getInternalDestination();
PageSequenceLayoutManager pslm = getPSLM();
diff --git a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java
index 2178b2e77..4877ff9bd 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java
@@ -87,7 +87,7 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager {
}
TraitSetter.setProducerID(text, node.getId());
TraitSetter.addTextDecoration(text, node.getTextDecoration());
- TraitSetter.addPtr(text, node.getPtr()); // used for accessibility
+ TraitSetter.addStructureTreeElement(text, node.getStructureTreeElement());
return text;
}
diff --git a/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java
index d8cfe6cda..4b7289b37 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java
@@ -19,13 +19,13 @@
package org.apache.fop.layoutmgr.inline;
+import org.apache.fop.area.Trait;
+import org.apache.fop.area.inline.InlineArea;
+import org.apache.fop.area.inline.TextArea;
import org.apache.fop.fo.flow.PageNumber;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontTriplet;
-import org.apache.fop.area.inline.InlineArea;
-import org.apache.fop.area.inline.TextArea;
-import org.apache.fop.area.Trait;
import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.TraitSetter;
import org.apache.fop.traits.MinOptMax;
@@ -85,7 +85,7 @@ public class PageNumberLayoutManager extends LeafNodeLayoutManager {
text.setBaselineOffset(font.getAscender());
TraitSetter.addFontTraits(text, font);
text.addTrait(Trait.COLOR, fobj.getColor());
- TraitSetter.addPtr(text, fobj.getPtr()); // used for accessibility
+ TraitSetter.addStructureTreeElement(text, fobj.getStructureTreeElement());
TraitSetter.addTextDecoration(text, fobj.getTextDecoration());
return text;
diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
index 81240dec0..8767fe296 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
@@ -31,8 +31,6 @@ import org.apache.fop.area.Trait;
import org.apache.fop.area.inline.TextArea;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FOText;
-import org.apache.fop.fo.FObj;
-import org.apache.fop.fo.properties.StructurePointerPropertySet;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontSelector;
import org.apache.fop.layoutmgr.InlineKnuthSequence;
@@ -438,7 +436,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
setText();
TraitSetter.addFontTraits(textArea, font);
textArea.addTrait(Trait.COLOR, foText.getColor());
- TraitSetter.addPtr(textArea, getPtr()); // used for accessibility
+ TraitSetter.addStructureTreeElement(textArea, foText.getStructureTreeElement());
TraitSetter.addTextDecoration(textArea, foText.getTextDecoration());
TraitSetter.addFontTraits(textArea, font);
return textArea;
@@ -577,20 +575,6 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
}
}
- /**
- * used for accessibility
- * @return ptr of fobj
- */
- private String getPtr() {
- FObj fobj = parentLayoutManager.getFObj();
- if (fobj instanceof StructurePointerPropertySet) {
- return (((StructurePointerPropertySet) fobj).getPtr());
- } else {
- //No structure pointer applicable
- return null;
- }
- }
-
private AreaInfo getAreaInfo(int index) {
return (AreaInfo) areaInfos.get(index);
}
diff --git a/src/java/org/apache/fop/pdf/PDFDocument.java b/src/java/org/apache/fop/pdf/PDFDocument.java
index 543d1a45f..256efd658 100644
--- a/src/java/org/apache/fop/pdf/PDFDocument.java
+++ b/src/java/org/apache/fop/pdf/PDFDocument.java
@@ -350,25 +350,6 @@ public class PDFDocument {
}
/**
- * Makes sure a Lang entry has been set on the document catalog, setting it
- * to a default value if necessary. When accessibility is enabled the
- * language must be specified for any text element in the document.
- */
- public void enforceLanguageOnRoot() {
- if (root.getLanguage() == null) {
- String fallbackLanguage;
- if (getProfile().getPDFAMode().isPDFA1LevelA()) {
- //According to Annex B of ISO-19005-1:2005(E), section B.2
- fallbackLanguage = "x-unknown";
- } else {
- //No language has been set on the first page-sequence, so fall back to "en".
- fallbackLanguage = "en";
- }
- root.setLanguage(fallbackLanguage);
- }
- }
-
- /**
* Get the {@link PDFInfo} object for this document.
*
* @return the {@link PDFInfo} object
diff --git a/src/java/org/apache/fop/pdf/PDFProfile.java b/src/java/org/apache/fop/pdf/PDFProfile.java
index fb4575105..b4b43c422 100644
--- a/src/java/org/apache/fop/pdf/PDFProfile.java
+++ b/src/java/org/apache/fop/pdf/PDFProfile.java
@@ -133,8 +133,12 @@ public class PDFProfile {
//---------=== Info and validation methods ===---------
+ private String format(String pattern, Object[] args) {
+ return MessageFormat.format(pattern, args);
+ }
+
private String format(String pattern, Object arg) {
- return MessageFormat.format(pattern, new Object[] {arg});
+ return format(pattern, new Object[] {arg});
}
/** Checks if encryption is allowed. */
diff --git a/src/java/org/apache/fop/pdf/PDFRoot.java b/src/java/org/apache/fop/pdf/PDFRoot.java
index f71841005..76f2587de 100644
--- a/src/java/org/apache/fop/pdf/PDFRoot.java
+++ b/src/java/org/apache/fop/pdf/PDFRoot.java
@@ -21,6 +21,9 @@ package org.apache.fop.pdf;
import java.io.IOException;
import java.io.OutputStream;
+import java.util.Locale;
+
+import org.apache.fop.util.LanguageTags;
/**
* Class representing a Root (/Catalog) object.
@@ -69,6 +72,7 @@ public class PDFRoot extends PDFDictionary {
setObjectNumber(objnum);
put("Type", new PDFName("Catalog"));
setRootPages(pages);
+ setLanguage("x-unknown");
}
/** {@inheritDoc} */
@@ -251,13 +255,17 @@ public class PDFRoot extends PDFDictionary {
}
/**
- * Sets the language identifier of the document.
- * @param lang the language identifier of the document.
+ * Sets the locale of the document.
+ * @param locale the locale of the document.
*/
- public void setLanguage(String lang) {
- if (lang == null) {
- throw new NullPointerException("lang must not be null");
+ public void setLanguage(Locale locale) {
+ if (locale == null) {
+ throw new NullPointerException("locale must not be null");
}
+ setLanguage(LanguageTags.toLanguageTag(locale));
+ }
+
+ private void setLanguage(String lang) {
put("Lang", lang);
}
diff --git a/src/java/org/apache/fop/pdf/PDFStructElem.java b/src/java/org/apache/fop/pdf/PDFStructElem.java
index 4fb8cbcd5..160d55384 100644
--- a/src/java/org/apache/fop/pdf/PDFStructElem.java
+++ b/src/java/org/apache/fop/pdf/PDFStructElem.java
@@ -19,18 +19,29 @@
package org.apache.fop.pdf;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Locale;
-import org.apache.fop.util.XMLUtil;
+import org.apache.fop.accessibility.StructureTreeElement;
+import org.apache.fop.util.LanguageTags;
/**
* Class representing a PDF Structure Element.
*/
-public class PDFStructElem extends PDFDictionary {
+public class PDFStructElem extends PDFDictionary implements StructureTreeElement {
private PDFStructElem parentElement;
/**
+ * Elements to be added to the kids array.
+ */
+ protected List<PDFObject> kids;
+
+ /**
* Creates a new structure element.
*
* @param parent parent of this element
@@ -57,21 +68,12 @@ public class PDFStructElem extends PDFDictionary {
/** {@inheritDoc} */
public void setParent(PDFObject parent) {
- if (parent != null) {
+ if (parent != null && parent.hasObjectNumber()) {
put("P", new PDFReference(parent));
}
}
/**
- * Returns the kids of this structure element.
- *
- * @return the value of the K entry
- */
- private PDFArray getKids() {
- return (PDFArray) get("K");
- }
-
- /**
* Add a kid to this structure element. This element will then add itself to
* its parent structure element if it has not already, and so will the
* parent, and so on.
@@ -79,24 +81,10 @@ public class PDFStructElem extends PDFDictionary {
* @param kid element to be added
*/
public void addKid(PDFObject kid) {
- PDFArray kids = getKids();
if (kids == null) {
- kids = new PDFArray();
- put("K", kids);
+ kids = new ArrayList<PDFObject>();
}
kids.add(kid);
- joinHierarchy();
- }
-
- private boolean containsKid(PDFObject kid) {
- PDFArray kids = getKids();
- return kids != null && kids.contains(kid);
- }
-
- private void joinHierarchy() {
- if (parentElement != null && !parentElement.containsKid(this)) {
- parentElement.addKid(this);
- }
}
/**
@@ -109,7 +97,6 @@ public class PDFStructElem extends PDFDictionary {
*/
public void setMCIDKid(int mcid) {
put("K", mcid);
- joinHierarchy();
}
/**
@@ -127,7 +114,7 @@ public class PDFStructElem extends PDFDictionary {
* @return the value of the S entry
*/
public PDFName getStructureType() {
- return (PDFName)get("S");
+ return (PDFName) get("S");
}
/**
@@ -145,7 +132,7 @@ public class PDFStructElem extends PDFDictionary {
* @param language a value for the Lang entry
*/
public void setLanguage(Locale language) {
- setLanguage(XMLUtil.toRFC3066(language));
+ setLanguage(LanguageTags.toLanguageTag(language));
}
/**
@@ -154,6 +141,71 @@ public class PDFStructElem extends PDFDictionary {
* @return the value of the Lang entry (<code>null</code> if no language was specified)
*/
public String getLanguage() {
- return (String)get("Lang");
+ return (String) get("Lang");
+ }
+
+ @Override
+ protected void writeDictionary(OutputStream out, StringBuilder textBuffer) throws IOException {
+ attachKids();
+ super.writeDictionary(out, textBuffer);
}
+
+ /**
+ * Attaches all valid kids to the kids array.
+ *
+ * @return true iff 1+ kids were added to the kids array
+ */
+ protected boolean attachKids() {
+ List<PDFObject> validKids = new ArrayList<PDFObject>();
+ if (kids != null) {
+ for (PDFObject kid : kids) {
+ if (kid instanceof Placeholder) {
+ if (((Placeholder) kid).attachKids()) {
+ validKids.add(kid);
+ }
+ } else {
+ validKids.add(kid);
+ }
+ }
+ }
+ boolean kidsAttached = !validKids.isEmpty();
+ if (kidsAttached) {
+ PDFArray array = new PDFArray();
+ for (PDFObject ob : validKids) {
+ array.add(ob);
+ }
+ put("K", array);
+ }
+ return kidsAttached;
+ }
+
+ /**
+ * Class representing a placeholder for a PDF Structure Element.
+ */
+ public static class Placeholder extends PDFStructElem {
+
+ @Override
+ public void outputInline(OutputStream out, StringBuilder textBuffer) throws IOException {
+ if (kids != null) {
+ assert kids.size() > 0;
+ for (int i = 0; i < kids.size(); i++) {
+ if (i > 0) {
+ textBuffer.append(' ');
+ }
+ Object obj = kids.get(i);
+ formatObject(obj, out, textBuffer);
+ }
+ }
+ }
+
+ /**
+ * Constructor
+ * @param parent -
+ * @param name -
+ */
+ public Placeholder(PDFObject parent, String name) {
+ super(parent, new PDFName(name));
+ }
+ }
+
}
diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java
index 659748df9..3c07c0006 100644
--- a/src/java/org/apache/fop/render/AbstractRenderer.java
+++ b/src/java/org/apache/fop/render/AbstractRenderer.java
@@ -27,6 +27,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.List;
+import java.util.Locale;
import java.util.Set;
import org.w3c.dom.Document;
@@ -152,6 +153,10 @@ public abstract class AbstractRenderer
return false;
}
+ /** {@inheritDoc} */
+ public void setDocumentLocale(Locale locale) {
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/src/java/org/apache/fop/render/Renderer.java b/src/java/org/apache/fop/render/Renderer.java
index 5f5596dfb..3ff6ffb2a 100644
--- a/src/java/org/apache/fop/render/Renderer.java
+++ b/src/java/org/apache/fop/render/Renderer.java
@@ -22,6 +22,7 @@ package org.apache.fop.render;
// Java
import java.io.IOException;
import java.io.OutputStream;
+import java.util.Locale;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
@@ -109,6 +110,12 @@ public interface Renderer {
boolean supportsOutOfOrder();
/**
+ *
+ * @param locale Locale of the language
+ */
+ void setDocumentLocale(Locale locale);
+
+ /**
* Tells the renderer to process an item not explicitly placed on the
* document (e.g., PDF bookmarks). Note - not all renderers will process
* all off-document items.
diff --git a/src/java/org/apache/fop/render/intermediate/AbstractIFDocumentHandler.java b/src/java/org/apache/fop/render/intermediate/AbstractIFDocumentHandler.java
index b156b6c3a..ad4e6ad0e 100644
--- a/src/java/org/apache/fop/render/intermediate/AbstractIFDocumentHandler.java
+++ b/src/java/org/apache/fop/render/intermediate/AbstractIFDocumentHandler.java
@@ -19,6 +19,13 @@
package org.apache.fop.render.intermediate;
+import java.util.Locale;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.fop.accessibility.DummyStructureTreeEventHandler;
+import org.apache.fop.accessibility.StructureTreeEventHandler;
import org.apache.fop.apps.FOUserAgent;
/**
@@ -53,6 +60,11 @@ public abstract class AbstractIFDocumentHandler implements IFDocumentHandler {
}
/** {@inheritDoc} */
+ public StructureTreeEventHandler getStructureTreeEventHandler() {
+ return DummyStructureTreeEventHandler.INSTANCE;
+ }
+
+ /** {@inheritDoc} */
public IFDocumentNavigationHandler getDocumentNavigationHandler() {
return null; //By default, this is not supported
}
@@ -66,6 +78,10 @@ public abstract class AbstractIFDocumentHandler implements IFDocumentHandler {
}
/** {@inheritDoc} */
+ public void setDocumentLocale(Locale locale) {
+ }
+
+ /** {@inheritDoc} */
public void startDocumentHeader() throws IFException {
//nop
}
@@ -104,5 +120,4 @@ public abstract class AbstractIFDocumentHandler implements IFDocumentHandler {
public void endPageTrailer() throws IFException {
//nop
}
-
}
diff --git a/src/java/org/apache/fop/render/intermediate/IFConstants.java b/src/java/org/apache/fop/render/intermediate/IFConstants.java
index 2b16b343d..c7bf13e31 100644
--- a/src/java/org/apache/fop/render/intermediate/IFConstants.java
+++ b/src/java/org/apache/fop/render/intermediate/IFConstants.java
@@ -39,6 +39,8 @@ public interface IFConstants extends XMLConstants {
String EL_HEADER = "header";
/** element name trailer */
String EL_TRAILER = "trailer";
+ /** element name locale */
+ String EL_LOCALE = "locale";
/** element name page-sequence */
String EL_PAGE_SEQUENCE = "page-sequence";
/** element name page */
diff --git a/src/java/org/apache/fop/render/intermediate/IFContext.java b/src/java/org/apache/fop/render/intermediate/IFContext.java
index b8be97253..c59a02ba8 100644
--- a/src/java/org/apache/fop/render/intermediate/IFContext.java
+++ b/src/java/org/apache/fop/render/intermediate/IFContext.java
@@ -25,6 +25,7 @@ import java.util.Map;
import org.apache.xmlgraphics.util.QName;
+import org.apache.fop.accessibility.StructureTreeElement;
import org.apache.fop.apps.FOUserAgent;
/**
@@ -46,7 +47,7 @@ public class IFContext {
private Locale language;
- private String structurePointer;
+ private StructureTreeElement structureTreeElement;
private String id = "";
@@ -132,29 +133,31 @@ public class IFContext {
}
/**
- * Sets the structure pointer for the following painted marks. This method is used when
- * accessibility features are enabled.
- * @param ptr the structure pointer
+ * Sets the structure tree element to which the subsequently painted marks
+ * will correspond. This method is used when accessibility features are
+ * enabled.
+ *
+ * @param structureTreeElement the structure tree element
*/
- public void setStructurePointer(String ptr) {
- this.structurePointer = ptr;
+ public void setStructureTreeElement(StructureTreeElement structureTreeElement) {
+ this.structureTreeElement = structureTreeElement;
}
/**
- * Resets the current structure pointer.
- * @see #setStructurePointer(String)
+ * Resets the current structure tree element.
+ * @see #setStructureTreeElement(String)
*/
- public void resetStructurePointer() {
- setStructurePointer(null);
+ public void resetStructureTreeElement() {
+ setStructureTreeElement(null);
}
/**
- * Returns the current structure pointer.
- * @return the structure pointer (or null if no pointer is active)
- * @see #setStructurePointer(String)
+ * Returns the current structure tree element.
+ * @return the structure tree element (or null if no element is active)
+ * @see #setStructureTreeElement(String)
*/
- public String getStructurePointer() {
- return this.structurePointer;
+ public StructureTreeElement getStructureTreeElement() {
+ return this.structureTreeElement;
}
/**
diff --git a/src/java/org/apache/fop/render/intermediate/IFDocumentHandler.java b/src/java/org/apache/fop/render/intermediate/IFDocumentHandler.java
index af1451fe3..6cb8f2795 100644
--- a/src/java/org/apache/fop/render/intermediate/IFDocumentHandler.java
+++ b/src/java/org/apache/fop/render/intermediate/IFDocumentHandler.java
@@ -20,9 +20,11 @@
package org.apache.fop.render.intermediate;
import java.awt.Dimension;
+import java.util.Locale;
import javax.xml.transform.Result;
+import org.apache.fop.accessibility.StructureTreeEventHandler;
import org.apache.fop.fonts.FontInfo;
/**
@@ -32,6 +34,7 @@ import org.apache.fop.fonts.FontInfo;
* <p>
* <pre>
* startDocument()
+ * [setDocumentLocale()]
* startDocumentHeader()
* [handleExtension()]*
* endDocumentHeader()
@@ -118,6 +121,11 @@ public interface IFDocumentHandler {
IFDocumentHandlerConfigurator getConfigurator();
/**
+ * @return the structure tree builder
+ */
+ StructureTreeEventHandler getStructureTreeEventHandler();
+
+ /**
* Returns a document navigation handler if this feature is supported.
* @return the document navigation handler or null if not supported
*/
@@ -152,6 +160,11 @@ public interface IFDocumentHandler {
void endDocument() throws IFException;
/**
+ * @param locale Locale of the document.
+ */
+ void setDocumentLocale(Locale locale);
+
+ /**
* Indicates the start of the document header. This method is called right after the
* {@link #startDocument()} method. Extensions sent to this painter between
* {@link #startDocumentHeader()} and {@link #endDocumentHeader()} apply to the document as
@@ -261,7 +274,4 @@ public interface IFDocumentHandler {
* @throws IFException if an error occurs while handling this event
*/
void handleExtensionObject(Object extension) throws IFException;
-
- //TODO Prototype the following:
- //ContentHandler handleExtension() throws Exception
}
diff --git a/src/java/org/apache/fop/render/intermediate/IFParser.java b/src/java/org/apache/fop/render/intermediate/IFParser.java
index 313cee685..36f1fd841 100644
--- a/src/java/org/apache/fop/render/intermediate/IFParser.java
+++ b/src/java/org/apache/fop/render/intermediate/IFParser.java
@@ -25,6 +25,7 @@ import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.util.HashMap;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
@@ -48,11 +49,13 @@ import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.util.QName;
import org.apache.fop.accessibility.AccessibilityEventProducer;
-import org.apache.fop.accessibility.StructureTreeBuilder;
+import org.apache.fop.accessibility.StructureTreeElement;
+import org.apache.fop.accessibility.StructureTreeEventHandler;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.fo.ElementMapping;
import org.apache.fop.fo.ElementMappingRegistry;
import org.apache.fop.fo.expr.PropertyException;
+import org.apache.fop.fo.extensions.InternalElementMapping;
import org.apache.fop.render.intermediate.extensions.DocumentNavigationExtensionConstants;
import org.apache.fop.render.intermediate.extensions.DocumentNavigationHandler;
import org.apache.fop.traits.BorderProps;
@@ -62,7 +65,7 @@ import org.apache.fop.util.ContentHandlerFactory;
import org.apache.fop.util.ContentHandlerFactoryRegistry;
import org.apache.fop.util.DOMBuilderContentHandlerFactory;
import org.apache.fop.util.DefaultErrorListener;
-import org.apache.fop.util.DelegatingContentHandler;
+import org.apache.fop.util.LanguageTags;
import org.apache.fop.util.XMLUtil;
/**
@@ -153,24 +156,59 @@ public class IFParser implements IFConstants {
private ContentHandler navParser;
- private StructureTreeBuilder structureTreeBuilder;
-
- private ContentHandler structureTreeBuilderWrapper;
+ private ContentHandler structureTreeHandler;
private Attributes pageSequenceAttributes;
- private final class StructureTreeBuilderWrapper extends DelegatingContentHandler {
+ private Map<String, StructureTreeElement> structureTreeElements
+ = new HashMap<String, StructureTreeElement>();
- private StructureTreeBuilderWrapper()
- throws SAXException {
- super(structureTreeBuilder.getHandlerForNextPageSequence());
+ private final class StructureTreeHandler extends DefaultHandler {
+
+ private final StructureTreeEventHandler structureTreeEventHandler;
+
+ private StructureTreeHandler(StructureTreeEventHandler structureTreeEventHandler,
+ Locale pageSequenceLanguage) throws SAXException {
+ this.structureTreeEventHandler = structureTreeEventHandler;
+ structureTreeEventHandler.startPageSequence(pageSequenceLanguage);
}
public void endDocument() throws SAXException {
- super.endDocument();
startIFElement(EL_PAGE_SEQUENCE, pageSequenceAttributes);
pageSequenceAttributes = null;
}
+
+ @Override
+ public void startElement(String uri, String localName, String qName,
+ Attributes attributes) throws SAXException {
+ if (!"structure-tree".equals(localName)) {
+ if (localName.equals("marked-content")) {
+ localName = "#PCDATA";
+ }
+ String structID = attributes.getValue(InternalElementMapping.URI,
+ InternalElementMapping.STRUCT_ID);
+ if (structID == null) {
+ structureTreeEventHandler.startNode(localName, attributes);
+ } else if (localName.equals("external-graphic")
+ || localName.equals("instream-foreign-object")) {
+ StructureTreeElement structureTreeElement
+ = structureTreeEventHandler.startImageNode(localName, attributes);
+ structureTreeElements.put(structID, structureTreeElement);
+ } else {
+ StructureTreeElement structureTreeElement = structureTreeEventHandler
+ .startReferencedNode(localName, attributes);
+ structureTreeElements.put(structID, structureTreeElement);
+ }
+ }
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String arqNameg2)
+ throws SAXException {
+ if (!"structure-tree".equals(localName)) {
+ structureTreeEventHandler.endNode(localName);
+ }
+ }
}
public Handler(IFDocumentHandler documentHandler, FOUserAgent userAgent,
@@ -180,6 +218,7 @@ public class IFParser implements IFConstants {
this.elementMappingRegistry = elementMappingRegistry;
elementHandlers.put(EL_DOCUMENT, new DocumentHandler());
elementHandlers.put(EL_HEADER, new DocumentHeaderHandler());
+ elementHandlers.put(EL_LOCALE, new LocaleHandler());
elementHandlers.put(EL_TRAILER, new DocumentTrailerHandler());
elementHandlers.put(EL_PAGE_SEQUENCE, new PageSequenceHandler());
elementHandlers.put(EL_PAGE, new PageHandler());
@@ -197,11 +236,6 @@ public class IFParser implements IFConstants {
elementHandlers.put(EL_LINE, new LineHandler());
elementHandlers.put(EL_BORDER_RECT, new BorderRectHandler());
elementHandlers.put(EL_IMAGE, new ImageHandler());
-
- if (userAgent.isAccessibilityEnabled()) {
- structureTreeBuilder = new StructureTreeBuilder(tFactory);
- userAgent.setStructureTree(structureTreeBuilder.getStructureTree());
- }
}
private void establishForeignAttributes(Map<QName, String> foreignAttributes) {
@@ -212,14 +246,6 @@ public class IFParser implements IFConstants {
documentHandler.getContext().resetForeignAttributes();
}
- private void establishStructurePointer(String ptr) {
- documentHandler.getContext().setStructurePointer(ptr);
- }
-
- private void resetStructurePointer() {
- documentHandler.getContext().resetStructurePointer();
- }
-
/** {@inheritDoc} */
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
@@ -231,10 +257,13 @@ public class IFParser implements IFConstants {
if (NAMESPACE.equals(uri)) {
if (localName.equals(EL_PAGE_SEQUENCE) && userAgent.isAccessibilityEnabled()) {
pageSequenceAttributes = new AttributesImpl(attributes);
- structureTreeBuilderWrapper = new StructureTreeBuilderWrapper();
+ Locale language = getLanguage(attributes);
+ structureTreeHandler = new StructureTreeHandler(
+ userAgent.getStructureTreeEventHandler(), language);
+
} else if (localName.equals(EL_STRUCTURE_TREE)) {
if (userAgent.isAccessibilityEnabled()) {
- delegate = structureTreeBuilderWrapper;
+ delegate = structureTreeHandler;
} else {
/* Delegate to a handler that does nothing */
delegate = new DefaultHandler();
@@ -260,7 +289,8 @@ public class IFParser implements IFConstants {
} else if (DocumentNavigationExtensionConstants.NAMESPACE.equals(uri)) {
if (this.navParser == null) {
this.navParser = new DocumentNavigationHandler(
- this.documentHandler.getDocumentNavigationHandler());
+ this.documentHandler.getDocumentNavigationHandler(),
+ structureTreeElements);
}
delegate = this.navParser;
delegateDepth++;
@@ -299,6 +329,11 @@ public class IFParser implements IFConstants {
}
}
+ private static Locale getLanguage(Attributes attributes) {
+ String xmllang = attributes.getValue(XML_NAMESPACE, "lang");
+ return (xmllang == null) ? null : LanguageTags.toLocale(xmllang);
+ }
+
private boolean startIFElement(String localName, Attributes attributes)
throws SAXException {
lastAttributes = new AttributesImpl(attributes);
@@ -413,6 +448,12 @@ public class IFParser implements IFConstants {
}
+ private class LocaleHandler extends AbstractElementHandler {
+ public void startElement(Attributes attributes) throws IFException {
+ documentHandler.setDocumentLocale(getLanguage(attributes));
+ }
+ }
+
private class DocumentTrailerHandler extends AbstractElementHandler {
public void startElement(Attributes attributes) throws IFException {
@@ -429,10 +470,9 @@ public class IFParser implements IFConstants {
public void startElement(Attributes attributes) throws IFException {
String id = attributes.getValue("id");
- String xmllang = attributes.getValue(XML_NAMESPACE, "lang");
- if (xmllang != null) {
- documentHandler.getContext().setLanguage(
- XMLUtil.convertRFC3066ToLocale(xmllang));
+ Locale language = getLanguage(attributes);
+ if (language != null) {
+ documentHandler.getContext().setLanguage(language);
}
Map<QName, String> foreignAttributes = getForeignAttributes(lastAttributes);
establishForeignAttributes(foreignAttributes);
@@ -578,9 +618,9 @@ public class IFParser implements IFConstants {
s = lastAttributes.getValue("word-spacing");
int wordSpacing = (s != null ? Integer.parseInt(s) : 0);
int[] dx = XMLUtil.getAttributeAsIntArray(lastAttributes, "dx");
- setStructurePointer(lastAttributes);
+ establishStructureTreeElement(lastAttributes);
painter.drawText(x, y, letterSpacing, wordSpacing, dx, content.toString());
- resetStructurePointer();
+ resetStructureTreeElement();
}
public boolean ignoreCharacters() {
@@ -675,7 +715,7 @@ public class IFParser implements IFConstants {
int height = Integer.parseInt(lastAttributes.getValue("height"));
Map<QName, String> foreignAttributes = getForeignAttributes(lastAttributes);
establishForeignAttributes(foreignAttributes);
- setStructurePointer(lastAttributes);
+ establishStructureTreeElement(lastAttributes);
if (foreignObject != null) {
painter.drawImage(foreignObject,
new Rectangle(x, y, width, height));
@@ -689,7 +729,7 @@ public class IFParser implements IFConstants {
painter.drawImage(uri, new Rectangle(x, y, width, height));
}
resetForeignAttributes();
- resetStructurePointer();
+ resetStructureTreeElement();
inForeignObject = false;
}
@@ -743,13 +783,20 @@ public class IFParser implements IFConstants {
return foreignAttributes;
}
- private void setStructurePointer(Attributes attributes) {
- String ptr = attributes.getValue("ptr");
- if (ptr != null && ptr.length() > 0) {
- establishStructurePointer(ptr);
+ private void establishStructureTreeElement(Attributes attributes) {
+ String structRef = attributes.getValue(InternalElementMapping.URI,
+ InternalElementMapping.STRUCT_REF);
+ if (structRef != null && structRef.length() > 0) {
+ assert structureTreeElements.containsKey(structRef);
+ StructureTreeElement structureTreeElement = structureTreeElements.get(structRef);
+ documentHandler.getContext().setStructureTreeElement(structureTreeElement);
}
}
+ private void resetStructureTreeElement() {
+ documentHandler.getContext().resetStructureTreeElement();
+ }
+
/** {@inheritDoc} */
public void characters(char[] ch, int start, int length) throws SAXException {
if (delegate != null) {
diff --git a/src/java/org/apache/fop/render/intermediate/IFRenderer.java b/src/java/org/apache/fop/render/intermediate/IFRenderer.java
index 9d8fb6e4b..4fec6c623 100644
--- a/src/java/org/apache/fop/render/intermediate/IFRenderer.java
+++ b/src/java/org/apache/fop/render/intermediate/IFRenderer.java
@@ -50,6 +50,7 @@ import org.apache.xmlgraphics.xmp.schemas.XMPBasicAdapter;
import org.apache.xmlgraphics.xmp.schemas.XMPBasicSchema;
import org.apache.fop.Version;
+import org.apache.fop.accessibility.StructureTreeElement;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.MimeConstants;
@@ -231,7 +232,11 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
*/
protected IFDocumentHandler createDefaultDocumentHandler() {
IFSerializer serializer = new IFSerializer();
- serializer.setContext(new IFContext(getUserAgent()));
+ FOUserAgent userAgent = getUserAgent();
+ serializer.setContext(new IFContext(userAgent));
+ if (userAgent.isAccessibilityEnabled()) {
+ userAgent.setStructureTreeEventHandler(serializer.getStructureTreeEventHandler());
+ }
return serializer;
}
@@ -298,6 +303,11 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
log.debug("Rendering finished.");
}
+ @Override
+ public void setDocumentLocale(Locale locale) {
+ documentHandler.setDocumentLocale(locale);
+ }
+
/** {@inheritDoc} */
public void processOffDocumentItem(OffDocumentItem odi) {
if (odi instanceof DestinationData) {
@@ -623,12 +633,12 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
documentHandler.getContext().resetForeignAttributes();
}
- private void establishStructurePointer(String ptr) {
- documentHandler.getContext().setStructurePointer(ptr);
+ private void establishStructureTreeElement(StructureTreeElement structureTreeElement) {
+ documentHandler.getContext().setStructureTreeElement(structureTreeElement);
}
private void resetStructurePointer() {
- documentHandler.getContext().resetStructurePointer();
+ documentHandler.getContext().resetStructureTreeElement();
}
/** {@inheritDoc} */
@@ -845,8 +855,9 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
/** {@inheritDoc} */
public void renderInlineViewport(InlineViewport viewport) {
- String ptr = (String) viewport.getTrait(Trait.PTR);
- establishStructurePointer(ptr);
+ StructureTreeElement structElem
+ = (StructureTreeElement) viewport.getTrait(Trait.STRUCTURE_TREE_ELEMENT);
+ establishStructureTreeElement(structElem);
pushdID(viewport);
Dimension dim = new Dimension(viewport.getIPD(), viewport.getBPD());
viewportDimensionStack.push(dim);
@@ -906,7 +917,6 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
// stuff we only need if a link must be created:
Rectangle ipRect = null;
AbstractAction action = null;
- String ptr = (String) ip.getTrait(Trait.PTR); // used for accessibility
// make sure the rect is determined *before* calling super!
int ipp = currentIPPosition;
int bpp = currentBPPosition + ip.getOffset();
@@ -950,7 +960,9 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
// warn if link trait found but not allowed, else create link
if (linkTraitFound) {
- action.setStructurePointer(ptr); // used for accessibility
+ StructureTreeElement structElem
+ = (StructureTreeElement) ip.getTrait(Trait.STRUCTURE_TREE_ELEMENT);
+ action.setStructureTreeElement(structElem);
Link link = new Link(action, ipRect);
this.deferredLinks.add(link);
}
@@ -1003,8 +1015,9 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
String fontName = getInternalFontNameForArea(text);
int size = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue();
- String ptr = (String)text.getTrait(Trait.PTR); // used for accessibility
- establishStructurePointer(ptr);
+ StructureTreeElement structElem
+ = (StructureTreeElement) text.getTrait(Trait.STRUCTURE_TREE_ELEMENT);
+ establishStructureTreeElement(structElem);
// This assumes that *all* CIDFonts use a /ToUnicode mapping
Typeface tf = getTypeface(fontName);
diff --git a/src/java/org/apache/fop/render/intermediate/IFSerializer.java b/src/java/org/apache/fop/render/intermediate/IFSerializer.java
index 471a982ca..7b9d95849 100644
--- a/src/java/org/apache/fop/render/intermediate/IFSerializer.java
+++ b/src/java/org/apache/fop/render/intermediate/IFSerializer.java
@@ -31,19 +31,18 @@ import java.util.Locale;
import java.util.Map;
import org.w3c.dom.Document;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import org.apache.xmlgraphics.util.QName;
import org.apache.xmlgraphics.util.XMLizable;
-import org.apache.fop.accessibility.StructureTree;
+import org.apache.fop.accessibility.StructureTreeEventHandler;
+import org.apache.fop.fo.extensions.InternalElementMapping;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.render.PrintRendererConfigurator;
import org.apache.fop.render.RenderingContext;
+import org.apache.fop.render.intermediate.IFStructureTreeBuilder.IFStructureTreeElement;
import org.apache.fop.render.intermediate.extensions.AbstractAction;
import org.apache.fop.render.intermediate.extensions.Bookmark;
import org.apache.fop.render.intermediate.extensions.BookmarkTree;
@@ -54,9 +53,11 @@ import org.apache.fop.traits.BorderProps;
import org.apache.fop.traits.RuleStyle;
import org.apache.fop.util.ColorUtil;
import org.apache.fop.util.DOM2SAX;
+import org.apache.fop.util.LanguageTags;
import org.apache.fop.util.XMLConstants;
import org.apache.fop.util.XMLUtil;
+
/**
* IFPainter implementation that serializes the intermediate format to XML.
*/
@@ -71,11 +72,7 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
private String currentID = "";
- /**
- * Default constructor.
- */
- public IFSerializer() {
- }
+ private IFStructureTreeBuilder structureTreeBuilder;
/** {@inheritDoc} */
@Override
@@ -150,6 +147,14 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
}
}
+ @Override
+ public StructureTreeEventHandler getStructureTreeEventHandler() {
+ if (structureTreeBuilder == null) {
+ structureTreeBuilder = new IFStructureTreeBuilder();
+ }
+ return structureTreeBuilder;
+ }
+
/** {@inheritDoc} */
@Override
public void startDocument() throws IFException {
@@ -160,12 +165,27 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
handler.startPrefixMapping(XLINK_PREFIX, XLINK_NAMESPACE);
handler.startPrefixMapping(DocumentNavigationExtensionConstants.PREFIX,
DocumentNavigationExtensionConstants.NAMESPACE);
+ handler.startPrefixMapping(InternalElementMapping.STANDARD_PREFIX,
+ InternalElementMapping.URI);
handler.startElement(EL_DOCUMENT);
} catch (SAXException e) {
throw new IFException("SAX error in startDocument()", e);
}
}
+ @Override
+ public void setDocumentLocale(Locale locale) {
+ AttributesImpl atts = new AttributesImpl();
+ atts.addAttribute(XML_NAMESPACE, "lang", "xml:lang", XMLUtil.CDATA,
+ LanguageTags.toLanguageTag(locale));
+ try {
+ handler.startElement(EL_LOCALE, atts);
+ handler.endElement(EL_LOCALE);
+ } catch (SAXException e) {
+ throw new RuntimeException("Unable to create the " + EL_LOCALE + " element.", e);
+ }
+ }
+
/** {@inheritDoc} */
@Override
public void startDocumentHeader() throws IFException {
@@ -227,20 +247,14 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
Locale lang = getContext().getLanguage();
if (lang != null) {
atts.addAttribute(XML_NAMESPACE, "lang", "xml:lang", XMLUtil.CDATA,
- XMLUtil.toRFC3066(lang));
+ LanguageTags.toLanguageTag(lang));
}
XMLUtil.addAttribute(atts, XMLConstants.XML_SPACE, "preserve");
addForeignAttributes(atts);
handler.startElement(EL_PAGE_SEQUENCE, atts);
if (this.getUserAgent().isAccessibilityEnabled()) {
- StructureTree structureTree = getUserAgent().getStructureTree();
- handler.startElement(EL_STRUCTURE_TREE); // add structure tree
- NodeList nodes = structureTree.getPageSequence(pageSequenceIndex++);
- for (int i = 0, n = nodes.getLength(); i < n; i++) {
- Node node = nodes.item(i);
- new DOM2SAX(handler).writeFragment(node);
- }
- handler.endElement(EL_STRUCTURE_TREE);
+ assert (structureTreeBuilder != null);
+ structureTreeBuilder.replayEventsForPageSequence(handler, pageSequenceIndex++);
}
} catch (SAXException e) {
throw new IFException("SAX error in startPageSequence()", e);
@@ -250,6 +264,7 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
/** {@inheritDoc} */
public void endPageSequence() throws IFException {
try {
+
handler.endElement(EL_PAGE_SEQUENCE);
} catch (SAXException e) {
throw new IFException("SAX error in endPageSequence()", e);
@@ -428,7 +443,7 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
addAttribute(atts, "width", Integer.toString(rect.width));
addAttribute(atts, "height", Integer.toString(rect.height));
addForeignAttributes(atts);
- addStructurePointerAttribute(atts);
+ addStructureReference(atts);
handler.element(EL_IMAGE, atts);
} catch (SAXException e) {
throw new IFException("SAX error in startGroup()", e);
@@ -456,7 +471,7 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
addAttribute(atts, "width", Integer.toString(rect.width));
addAttribute(atts, "height", Integer.toString(rect.height));
addForeignAttributes(atts);
- addStructurePointerAttribute(atts);
+ addStructureReference(atts);
handler.startElement(EL_IMAGE, atts);
new DOM2SAX(handler).writeDocument(doc, true);
handler.endElement(EL_IMAGE);
@@ -571,7 +586,7 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
if (dx != null) {
addAttribute(atts, "dx", IFUtil.toString(dx));
}
- addStructurePointerAttribute(atts);
+ addStructureReference(atts);
handler.startElement(EL_TEXT, atts);
char[] chars = text.toCharArray();
handler.characters(chars, 0, chars.length);
@@ -671,13 +686,22 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
XMLUtil.addAttribute(atts, localName, value);
}
- private void addStructurePointerAttribute(AttributesImpl atts) {
- String ptr = getContext().getStructurePointer();
- if (ptr != null) {
- addAttribute(atts, "ptr", ptr);
+ private void addStructureReference(AttributesImpl atts) {
+ IFStructureTreeElement structureTreeElement
+ = (IFStructureTreeElement) getContext().getStructureTreeElement();
+ if (structureTreeElement != null) {
+ addStructRefAttribute(atts, structureTreeElement.getId());
}
}
+ private void addStructRefAttribute(AttributesImpl atts, String id) {
+ atts.addAttribute(InternalElementMapping.URI,
+ InternalElementMapping.STRUCT_REF,
+ InternalElementMapping.STANDARD_PREFIX + ":" + InternalElementMapping.STRUCT_REF,
+ XMLConstants.CDATA,
+ id);
+ }
+
private void addID() throws SAXException {
String id = getContext().getID();
if (!currentID.equals(id)) {
@@ -762,7 +786,8 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
atts.addAttribute(null, "rect", "rect",
XMLConstants.CDATA, IFUtil.toString(link.getTargetRect()));
if (getUserAgent().isAccessibilityEnabled()) {
- addAttribute(atts, "ptr", link.getAction().getStructurePointer());
+ addStructRefAttribute(atts,
+ ((IFStructureTreeElement) link.getAction().getStructureTreeElement()).getId());
}
try {
handler.startElement(DocumentNavigationExtensionConstants.LINK, atts);
@@ -806,5 +831,4 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
throw new IFException("SAX error serializing object", e);
}
}
-
}
diff --git a/src/java/org/apache/fop/render/intermediate/IFSerializerMaker.java b/src/java/org/apache/fop/render/intermediate/IFSerializerMaker.java
index 699fd0549..c0060ab8e 100644
--- a/src/java/org/apache/fop/render/intermediate/IFSerializerMaker.java
+++ b/src/java/org/apache/fop/render/intermediate/IFSerializerMaker.java
@@ -31,6 +31,9 @@ public class IFSerializerMaker extends AbstractIFDocumentHandlerMaker {
public IFDocumentHandler makeIFDocumentHandler(FOUserAgent ua) {
IFSerializer handler = new IFSerializer();
handler.setContext(new IFContext(ua));
+ if (ua.isAccessibilityEnabled()) {
+ ua.setStructureTreeEventHandler(handler.getStructureTreeEventHandler());
+ }
return handler;
}
diff --git a/src/java/org/apache/fop/render/intermediate/IFStructureTreeBuilder.java b/src/java/org/apache/fop/render/intermediate/IFStructureTreeBuilder.java
new file mode 100644
index 000000000..3d9885914
--- /dev/null
+++ b/src/java/org/apache/fop/render/intermediate/IFStructureTreeBuilder.java
@@ -0,0 +1,239 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.intermediate;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+import org.xml.sax.helpers.DefaultHandler;
+
+import org.apache.fop.accessibility.StructureTree2SAXEventAdapter;
+import org.apache.fop.accessibility.StructureTreeElement;
+import org.apache.fop.accessibility.StructureTreeEventHandler;
+import org.apache.fop.fo.extensions.InternalElementMapping;
+import org.apache.fop.util.XMLUtil;
+
+/**
+ * Saves structure tree events as SAX events in order to replay them when it's
+ * time to stream the structure tree to the output.
+ */
+final class IFStructureTreeBuilder implements StructureTreeEventHandler {
+
+ static final class IFStructureTreeElement implements StructureTreeElement {
+
+ private final String id;
+
+ IFStructureTreeElement() {
+ this.id = null;
+ }
+
+ IFStructureTreeElement(String id) {
+ this.id = id;
+ }
+
+ public String getId() {
+ return id;
+ }
+ }
+
+ /** A SAX handler that records events to replay them later. */
+ static class SAXEventRecorder extends DefaultHandler {
+
+ private final List<SAXEventRecorder.Event> events = new ArrayList<SAXEventRecorder.Event>();
+
+ private abstract static class Event {
+ abstract void replay(ContentHandler handler) throws SAXException;
+ }
+
+ private abstract static class Element extends SAXEventRecorder.Event {
+
+ protected final String uri;
+ protected final String localName;
+ protected final String qName;
+
+ private Element(String uri, String localName, String qName) {
+ this.uri = uri;
+ this.localName = localName;
+ this.qName = qName;
+ }
+ }
+
+ private static final class StartElement extends SAXEventRecorder.Element {
+
+ private final Attributes attributes;
+
+ private StartElement(String uri, String localName, String qName,
+ Attributes attributes) {
+ super(uri, localName, qName);
+ this.attributes = attributes;
+ }
+
+ @Override
+ void replay(ContentHandler handler) throws SAXException {
+ handler.startElement(uri, localName, qName, attributes);
+ }
+ }
+
+ private static final class EndElement extends SAXEventRecorder.Element {
+
+ private EndElement(String uri, String localName, String qName) {
+ super(uri, localName, qName);
+ }
+
+ @Override
+ void replay(ContentHandler handler) throws SAXException {
+ handler.endElement(uri, localName, qName);
+ }
+ }
+
+ private static final class StartPrefixMapping extends SAXEventRecorder.Event {
+
+ private final String prefix;
+ private final String uri;
+
+ private StartPrefixMapping(String prefix, String uri) {
+ this.prefix = prefix;
+ this.uri = uri;
+ }
+
+ @Override
+ void replay(ContentHandler handler) throws SAXException {
+ handler.startPrefixMapping(prefix, uri);
+ }
+ }
+
+ private static final class EndPrefixMapping extends SAXEventRecorder.Event {
+
+ private final String prefix;
+
+ private EndPrefixMapping(String prefix) {
+ this.prefix = prefix;
+ }
+
+ @Override
+ void replay(ContentHandler handler) throws SAXException {
+ handler.endPrefixMapping(prefix);
+ }
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName,
+ Attributes attributes) throws SAXException {
+ events.add(new StartElement(uri, localName, qName, attributes));
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ events.add(new EndElement(uri, localName, qName));
+ }
+
+ @Override
+ public void startPrefixMapping(String prefix, String uri) throws SAXException {
+ events.add(new StartPrefixMapping(prefix, uri));
+ }
+
+ @Override
+ public void endPrefixMapping(String prefix) throws SAXException {
+ events.add(new EndPrefixMapping(prefix));
+ }
+
+ /**
+ * Replays the recorded events.
+ *
+ * @param handler {@code ContentHandler} to replay events on
+ */
+ public void replay(ContentHandler handler) throws SAXException {
+ for (SAXEventRecorder.Event e : events) {
+ e.replay(handler);
+ }
+ }
+ }
+
+ private StructureTreeEventHandler delegate;
+
+ private final List<SAXEventRecorder> pageSequenceEventRecorders
+ = new ArrayList<SAXEventRecorder>();
+
+ private int idCounter;
+
+ /**
+ * Replay SAX events for a page sequence.
+ * @param handler The handler that receives SAX events
+ * @param pageSequenceIndex The index of the page sequence
+ * @throws SAXException
+ */
+ public void replayEventsForPageSequence(ContentHandler handler,
+ int pageSequenceIndex) throws SAXException {
+ pageSequenceEventRecorders.get(pageSequenceIndex).replay(handler);
+ }
+
+ public void startPageSequence(Locale locale) {
+ SAXEventRecorder eventRecorder = new SAXEventRecorder();
+ pageSequenceEventRecorders.add(eventRecorder);
+ delegate = StructureTree2SAXEventAdapter.newInstance(eventRecorder);
+ delegate.startPageSequence(locale);
+ }
+
+ public void endPageSequence() {
+ delegate.endPageSequence();
+ }
+
+ public StructureTreeElement startNode(String name, Attributes attributes) {
+ delegate.startNode(name, attributes);
+ return new IFStructureTreeElement();
+ }
+
+ public void endNode(String name) {
+ delegate.endNode(name);
+ }
+
+ public StructureTreeElement startImageNode(String name, Attributes attributes) {
+ String id = getNextID();
+ AttributesImpl atts = addIDAttribute(attributes, id);
+ delegate.startImageNode(name, atts);
+ return new IFStructureTreeElement(id);
+ }
+
+ public StructureTreeElement startReferencedNode(String name, Attributes attributes) {
+ String id = getNextID();
+ AttributesImpl atts = addIDAttribute(attributes, id);
+ delegate.startReferencedNode(name, atts);
+ return new IFStructureTreeElement(id);
+ }
+
+ private String getNextID() {
+ return Integer.toHexString(idCounter++);
+ }
+
+ private AttributesImpl addIDAttribute(Attributes attributes, String id) {
+ AttributesImpl atts = new AttributesImpl(attributes);
+ atts.addAttribute(InternalElementMapping.URI,
+ InternalElementMapping.STRUCT_ID,
+ InternalElementMapping.STANDARD_PREFIX + ":" + InternalElementMapping.STRUCT_ID,
+ XMLUtil.CDATA,
+ id);
+ return atts;
+ }
+}
diff --git a/src/java/org/apache/fop/render/intermediate/extensions/AbstractAction.java b/src/java/org/apache/fop/render/intermediate/extensions/AbstractAction.java
index 340b2e068..a2595d320 100644
--- a/src/java/org/apache/fop/render/intermediate/extensions/AbstractAction.java
+++ b/src/java/org/apache/fop/render/intermediate/extensions/AbstractAction.java
@@ -21,13 +21,15 @@ package org.apache.fop.render.intermediate.extensions;
import org.apache.xmlgraphics.util.XMLizable;
+import org.apache.fop.accessibility.StructureTreeElement;
+
/**
* Abstract base class for document actions, like "go-to" actions with absolute page coordinates.
*/
public abstract class AbstractAction implements XMLizable {
private String id;
- private String structurePointer;
+ private StructureTreeElement structureTreeElement;
/**
* Sets an ID to make the action referencable.
@@ -47,18 +49,18 @@ public abstract class AbstractAction implements XMLizable {
/**
* Sets the structure element corresponding to this action.
- * @param structurePointer a reference to the structure element
+ * @param structureTreeElement a reference to the structure element
*/
- public void setStructurePointer(String structurePointer) {
- this.structurePointer = structurePointer;
+ public void setStructureTreeElement(StructureTreeElement structureTreeElement) {
+ this.structureTreeElement = structureTreeElement;
}
/**
* Returns the structure element corresponding to this action.
* @return the reference to the structure element
*/
- public String getStructurePointer() {
- return structurePointer;
+ public StructureTreeElement getStructureTreeElement() {
+ return structureTreeElement;
}
/**
diff --git a/src/java/org/apache/fop/render/intermediate/extensions/DocumentNavigationHandler.java b/src/java/org/apache/fop/render/intermediate/extensions/DocumentNavigationHandler.java
index 1e613d7eb..c174a74a9 100644
--- a/src/java/org/apache/fop/render/intermediate/extensions/DocumentNavigationHandler.java
+++ b/src/java/org/apache/fop/render/intermediate/extensions/DocumentNavigationHandler.java
@@ -21,6 +21,7 @@ package org.apache.fop.render.intermediate.extensions;
import java.awt.Point;
import java.awt.Rectangle;
+import java.util.Map;
import java.util.Stack;
import org.xml.sax.Attributes;
@@ -30,6 +31,8 @@ import org.xml.sax.helpers.DefaultHandler;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.fop.accessibility.StructureTreeElement;
+import org.apache.fop.fo.extensions.InternalElementMapping;
import org.apache.fop.render.intermediate.IFDocumentNavigationHandler;
import org.apache.fop.render.intermediate.IFException;
import org.apache.fop.util.XMLUtil;
@@ -48,14 +51,20 @@ public class DocumentNavigationHandler extends DefaultHandler
private IFDocumentNavigationHandler navHandler;
- private String structurePointer;
+ private StructureTreeElement structureTreeElement;
+
+ private Map<String, StructureTreeElement> structureTreeElements;
/**
* Main constructor.
* @param navHandler the navigation handler that will receive the events
+ * @param structureTreeElements the elements representing the structure of the document
*/
- public DocumentNavigationHandler(IFDocumentNavigationHandler navHandler) {
+ public DocumentNavigationHandler(IFDocumentNavigationHandler navHandler,
+ Map<String, StructureTreeElement> structureTreeElements) {
this.navHandler = navHandler;
+ assert structureTreeElements != null;
+ this.structureTreeElements = structureTreeElements;
}
/** {@inheritDoc} */
@@ -98,7 +107,8 @@ public class DocumentNavigationHandler extends DefaultHandler
throw new SAXException(localName + " must be the root element!");
}
Rectangle targetRect = XMLUtil.getAttributeAsRectangle(attributes, "rect");
- structurePointer = attributes.getValue("ptr");
+ structureTreeElement = structureTreeElements.get(attributes.getValue(
+ InternalElementMapping.URI, InternalElementMapping.STRUCT_REF));
Link link = new Link(null, targetRect);
objectStack.push(link);
} else if (GOTO_XY.getLocalName().equals(localName)) {
@@ -121,8 +131,8 @@ public class DocumentNavigationHandler extends DefaultHandler
}
action = new GoToXYAction(id, pageIndex, location);
}
- if (structurePointer != null) {
- action.setStructurePointer(structurePointer);
+ if (structureTreeElement != null) {
+ action.setStructureTreeElement(structureTreeElement);
}
objectStack.push(action);
} else if (GOTO_URI.getLocalName().equals(localName)) {
@@ -134,8 +144,8 @@ public class DocumentNavigationHandler extends DefaultHandler
if (id != null) {
action.setID(id);
}
- if (structurePointer != null) {
- action.setStructurePointer(structurePointer);
+ if (structureTreeElement != null) {
+ action.setStructureTreeElement(structureTreeElement);
}
objectStack.push(action);
} else {
diff --git a/src/java/org/apache/fop/render/intermediate/util/IFDocumentHandlerProxy.java b/src/java/org/apache/fop/render/intermediate/util/IFDocumentHandlerProxy.java
index 3d89e812e..64c876fb1 100644
--- a/src/java/org/apache/fop/render/intermediate/util/IFDocumentHandlerProxy.java
+++ b/src/java/org/apache/fop/render/intermediate/util/IFDocumentHandlerProxy.java
@@ -20,9 +20,12 @@
package org.apache.fop.render.intermediate.util;
import java.awt.Dimension;
+import java.util.Locale;
import javax.xml.transform.Result;
+import org.apache.fop.accessibility.DummyStructureTreeEventHandler;
+import org.apache.fop.accessibility.StructureTreeEventHandler;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.render.intermediate.IFContext;
import org.apache.fop.render.intermediate.IFDocumentHandler;
@@ -94,6 +97,11 @@ public class IFDocumentHandlerProxy implements IFDocumentHandler {
}
/** {@inheritDoc} */
+ public StructureTreeEventHandler getStructureTreeEventHandler() {
+ return DummyStructureTreeEventHandler.INSTANCE;
+ }
+
+ /** {@inheritDoc} */
public void setResult(Result result) throws IFException {
this.delegate.setResult(result);
}
@@ -104,6 +112,12 @@ public class IFDocumentHandlerProxy implements IFDocumentHandler {
}
/** {@inheritDoc} */
+ public void setDocumentLocale(Locale locale) {
+ this.delegate.setDocumentLocale(locale);
+
+ }
+
+ /** {@inheritDoc} */
public void startDocumentHeader() throws IFException {
this.delegate.startDocumentHeader();
}
@@ -184,4 +198,4 @@ public class IFDocumentHandlerProxy implements IFDocumentHandler {
this.delegate.handleExtensionObject(extension);
}
-} \ No newline at end of file
+}
diff --git a/src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java b/src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java
index 26595bca1..9b76d0620 100644
--- a/src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java
+++ b/src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java
@@ -22,8 +22,6 @@ package org.apache.fop.render.pdf;
import java.util.HashMap;
import java.util.Map;
-import org.w3c.dom.Node;
-
import org.apache.fop.events.EventBroadcaster;
import org.apache.fop.pdf.PDFName;
import org.apache.fop.pdf.PDFObject;
@@ -37,9 +35,11 @@ final class FOToPDFRoleMap {
/**
* Standard structure types defined by the PDF Reference, Fourth Edition (PDF 1.5).
*/
- private static final Map STANDARD_STRUCTURE_TYPES = new HashMap();
+ private static final Map<String, PDFName> STANDARD_STRUCTURE_TYPES
+ = new HashMap<String, PDFName>();
- private static final Map DEFAULT_MAPPINGS = new java.util.HashMap();
+ private static final Map<String, Mapper> DEFAULT_MAPPINGS
+ = new java.util.HashMap<String, Mapper>();
private static final PDFName THEAD;
private static final PDFName NON_STRUCT;
@@ -172,7 +172,7 @@ final class FOToPDFRoleMap {
* @return the structure type or null if no match could be found
*/
public static PDFName mapFormattingObject(String fo, PDFObject parent) {
- Mapper mapper = (Mapper)DEFAULT_MAPPINGS.get(fo);
+ Mapper mapper = (Mapper) DEFAULT_MAPPINGS.get(fo);
if (mapper != null) {
return mapper.getStructureType(parent);
} else {
@@ -180,27 +180,32 @@ final class FOToPDFRoleMap {
}
}
- public static PDFName mapFormattingObject(Node fo, PDFObject parent,
- EventBroadcaster eventBroadcaster) {
+ /**
+ * Maps a Formatting Object to a PDFName representing the associated structure type.
+ * @param fo the formatting object's local name
+ * @param role the value of the formatting object's role property
+ * @param parent the parent of the structure element to be mapped
+ * @param eventBroadcaster the event broadcaster
+ * @return the structure type or null if no match could be found
+ */
+ public static PDFName mapFormattingObject(String fo, String role,
+ PDFObject parent, EventBroadcaster eventBroadcaster) {
PDFName type = null;
- Node role = fo.getAttributes().getNamedItemNS(null, "role");
if (role == null) {
- type = mapFormattingObject(fo.getLocalName(), parent);
+ type = mapFormattingObject(fo, parent);
} else {
- String customType = role.getNodeValue();
- type = (PDFName) STANDARD_STRUCTURE_TYPES.get(customType);
+ type = (PDFName) STANDARD_STRUCTURE_TYPES.get(role);
if (type == null) {
- String foName = fo.getLocalName();
- type = mapFormattingObject(foName, parent);
+ type = mapFormattingObject(fo, parent);
PDFEventProducer.Provider.get(eventBroadcaster).nonStandardStructureType(fo,
- foName, customType, type.toString().substring(1));
+ fo, role, type.toString().substring(1));
}
}
assert type != null;
return type;
}
- private static interface Mapper {
+ private interface Mapper {
PDFName getStructureType(PDFObject parent);
}
@@ -222,7 +227,7 @@ final class FOToPDFRoleMap {
public PDFName getStructureType(PDFObject parent) {
PDFStructElem grandParent = (PDFStructElem)
- ((PDFStructElem)parent).getParentStructElem();
+ ((PDFStructElem) parent).getParentStructElem();
//TODO What to do with cells from table-footer? Currently they are mapped on TD.
PDFName type;
if (THEAD.equals(grandParent.getStructureType())) {
diff --git a/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java b/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java
index c1d959dd1..5be8c3001 100644
--- a/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java
+++ b/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java
@@ -25,15 +25,16 @@ import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
+import java.util.HashMap;
+import java.util.Locale;
import java.util.Map;
-import org.w3c.dom.NodeList;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.xmp.Metadata;
+import org.apache.fop.accessibility.StructureTreeEventHandler;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.fo.extensions.xmp.XMPMetadata;
import org.apache.fop.pdf.PDFAnnotList;
@@ -45,28 +46,26 @@ import org.apache.fop.render.extensions.prepress.PageBoundaries;
import org.apache.fop.render.extensions.prepress.PageScale;
import org.apache.fop.render.intermediate.AbstractBinaryWritingIFDocumentHandler;
import org.apache.fop.render.intermediate.IFContext;
-import org.apache.fop.render.intermediate.IFDocumentHandler;
import org.apache.fop.render.intermediate.IFDocumentHandlerConfigurator;
import org.apache.fop.render.intermediate.IFDocumentNavigationHandler;
import org.apache.fop.render.intermediate.IFException;
import org.apache.fop.render.intermediate.IFPainter;
import org.apache.fop.render.pdf.extensions.PDFEmbeddedFileExtensionAttachment;
-import org.apache.fop.util.XMLUtil;
/**
- * {@link IFDocumentHandler} implementation that produces PDF.
+ * {@link org.apache.fop.render.intermediate.IFDocumentHandler} implementation that produces PDF.
*/
public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler {
/** logging instance */
private static Log log = LogFactory.getLog(PDFDocumentHandler.class);
- private int pageSequenceIndex;
-
private boolean accessEnabled;
private PDFLogicalStructureHandler logicalStructureHandler;
+ private PDFStructureTreeBuilder structureTreeBuilder;
+
/** the PDF Document being created */
protected PDFDocument pdfDoc;
@@ -92,8 +91,7 @@ public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler {
protected PageReference currentPageRef;
/** Used for bookmarks/outlines. */
- protected Map<Integer, PageReference> pageReferences
- = new java.util.HashMap<Integer, PageReference>();
+ protected Map<Integer, PageReference> pageReferences = new HashMap<Integer, PageReference>();
private final PDFDocumentNavigationHandler documentNavigationHandler
= new PDFDocumentNavigationHandler(this);
@@ -145,15 +143,23 @@ public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler {
this.pdfDoc = pdfUtil.setupPDFDocument(this.outputStream);
this.accessEnabled = getUserAgent().isAccessibilityEnabled();
if (accessEnabled) {
- pdfDoc.getRoot().makeTagged();
- logicalStructureHandler = new PDFLogicalStructureHandler(pdfDoc,
- getUserAgent().getEventBroadcaster());
+ setupAccessibility();
}
} catch (IOException e) {
throw new IFException("I/O error in startDocument()", e);
}
}
+ private void setupAccessibility() {
+ pdfDoc.getRoot().makeTagged();
+ logicalStructureHandler = new PDFLogicalStructureHandler(pdfDoc);
+ // TODO this is ugly. All the necessary information should be available
+ // at creation time in order to enforce immutability
+ structureTreeBuilder.setPdfFactory(pdfDoc.getFactory());
+ structureTreeBuilder.setLogicalStructureHandler(logicalStructureHandler);
+ structureTreeBuilder.setEventBroadcaster(getUserAgent().getEventBroadcaster());
+ }
+
/** {@inheritDoc} */
public void endDocumentHeader() throws IFException {
pdfUtil.generateDefaultXMPMetadata();
@@ -178,18 +184,7 @@ public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler {
/** {@inheritDoc} */
public void startPageSequence(String id) throws IFException {
- //TODO page sequence title
-
- if (this.pdfDoc.getRoot().getLanguage() == null
- && getContext().getLanguage() != null) {
- //No document-level language set, so we use the first page-sequence's language
- this.pdfDoc.getRoot().setLanguage(XMLUtil.toRFC3066(getContext().getLanguage()));
- }
-
- if (accessEnabled) {
- NodeList nodes = getUserAgent().getStructureTree().getPageSequence(pageSequenceIndex++);
- logicalStructureHandler.processStructureTree(nodes, getContext().getLanguage());
- }
+ //nop
}
/** {@inheritDoc} */
@@ -289,9 +284,9 @@ public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler {
/** {@inheritDoc} */
public void handleExtensionObject(Object extension) throws IFException {
if (extension instanceof XMPMetadata) {
- pdfUtil.renderXMPMetadata((XMPMetadata)extension);
+ pdfUtil.renderXMPMetadata((XMPMetadata) extension);
} else if (extension instanceof Metadata) {
- XMPMetadata wrapper = new XMPMetadata(((Metadata)extension));
+ XMPMetadata wrapper = new XMPMetadata(((Metadata) extension));
pdfUtil.renderXMPMetadata(wrapper);
} else if (extension instanceof PDFEmbeddedFileExtensionAttachment) {
PDFEmbeddedFileExtensionAttachment embeddedFile
@@ -307,6 +302,11 @@ public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler {
}
}
+ /** {@inheritDoc} */
+ public void setDocumentLocale(Locale locale) {
+ pdfDoc.getRoot().setLanguage(locale);
+ }
+
PageReference getPageReference(int pageIndex) {
return this.pageReferences.get(Integer.valueOf(pageIndex));
}
@@ -332,4 +332,11 @@ public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler {
}
}
+ @Override
+ public StructureTreeEventHandler getStructureTreeEventHandler() {
+ if (structureTreeBuilder == null) {
+ structureTreeBuilder = new PDFStructureTreeBuilder();
+ }
+ return structureTreeBuilder;
+ }
}
diff --git a/src/java/org/apache/fop/render/pdf/PDFDocumentHandlerMaker.java b/src/java/org/apache/fop/render/pdf/PDFDocumentHandlerMaker.java
index f4ba03d5b..1186db3ae 100644
--- a/src/java/org/apache/fop/render/pdf/PDFDocumentHandlerMaker.java
+++ b/src/java/org/apache/fop/render/pdf/PDFDocumentHandlerMaker.java
@@ -36,6 +36,9 @@ public class PDFDocumentHandlerMaker extends AbstractIFDocumentHandlerMaker {
public IFDocumentHandler makeIFDocumentHandler(FOUserAgent ua) {
PDFDocumentHandler handler = new PDFDocumentHandler();
handler.setContext(new IFContext(ua));
+ if (ua.isAccessibilityEnabled()) {
+ ua.setStructureTreeEventHandler(handler.getStructureTreeEventHandler());
+ }
return handler;
}
diff --git a/src/java/org/apache/fop/render/pdf/PDFDocumentNavigationHandler.java b/src/java/org/apache/fop/render/pdf/PDFDocumentNavigationHandler.java
index c8fa481d4..2236778b5 100644
--- a/src/java/org/apache/fop/render/pdf/PDFDocumentNavigationHandler.java
+++ b/src/java/org/apache/fop/render/pdf/PDFDocumentNavigationHandler.java
@@ -31,6 +31,7 @@ import org.apache.fop.pdf.PDFFactory;
import org.apache.fop.pdf.PDFGoTo;
import org.apache.fop.pdf.PDFLink;
import org.apache.fop.pdf.PDFOutline;
+import org.apache.fop.pdf.PDFStructElem;
import org.apache.fop.render.intermediate.IFDocumentNavigationHandler;
import org.apache.fop.render.intermediate.IFException;
import org.apache.fop.render.intermediate.extensions.AbstractAction;
@@ -111,10 +112,9 @@ public class PDFDocumentNavigationHandler implements IFDocumentNavigationHandler
PDFLink pdfLink = getPDFDoc().getFactory().makeLink(
targetRect2D, pdfAction);
if (pdfLink != null) {
- String ptr = link.getAction().getStructurePointer();
- if (documentHandler.getUserAgent().isAccessibilityEnabled()
- && ptr != null && ptr.length() > 0) {
- documentHandler.getLogicalStructureHandler().addLinkContentItem(pdfLink, ptr);
+ PDFStructElem structure = (PDFStructElem) link.getAction().getStructureTreeElement();
+ if (documentHandler.getUserAgent().isAccessibilityEnabled() && structure != null) {
+ documentHandler.getLogicalStructureHandler().addLinkContentItem(pdfLink, structure);
}
documentHandler.currentPage.addAnnotation(pdfLink);
}
diff --git a/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java b/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java
index 4fd66109a..88a6e9c22 100644
--- a/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java
+++ b/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java
@@ -19,16 +19,8 @@
package org.apache.fop.render.pdf;
-import java.util.HashMap;
import java.util.Locale;
-import java.util.Map;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-import org.apache.fop.events.EventBroadcaster;
-import org.apache.fop.fo.extensions.ExtensionElementMapping;
-import org.apache.fop.fo.extensions.InternalElementMapping;
import org.apache.fop.pdf.PDFArray;
import org.apache.fop.pdf.PDFDictionary;
import org.apache.fop.pdf.PDFDocument;
@@ -53,13 +45,6 @@ class PDFLogicalStructureHandler {
private final PDFDocument pdfDoc;
- private final EventBroadcaster eventBroadcaster;
-
- /**
- * Map of references to the corresponding structure elements.
- */
- private final Map structTreeMap = new HashMap();
-
private final PDFParentTree parentTree = new PDFParentTree();
private int parentTreeKey;
@@ -108,23 +93,16 @@ class PDFLogicalStructureHandler {
*
* @param pdfDoc a document
*/
- PDFLogicalStructureHandler(PDFDocument pdfDoc, EventBroadcaster eventBroadcaster) {
+ PDFLogicalStructureHandler(PDFDocument pdfDoc) {
this.pdfDoc = pdfDoc;
- this.eventBroadcaster = eventBroadcaster;
PDFStructTreeRoot structTreeRoot = pdfDoc.getFactory().makeStructTreeRoot(parentTree);
rootStructureElement = pdfDoc.getFactory().makeStructureElement(
FOToPDFRoleMap.mapFormattingObject("root", structTreeRoot), structTreeRoot);
structTreeRoot.addKid(rootStructureElement);
}
- /**
- * Converts the given structure tree into PDF.
- *
- * @param structureTree the structure tree of the current page sequence
- * @param language language set on the page sequence
- */
- void processStructureTree(NodeList structureTree, Locale language) {
- pdfDoc.enforceLanguageOnRoot();
+
+ PDFStructElem createPageSequence(Locale language) {
PDFStructElem structElemPart = pdfDoc.getFactory().makeStructureElement(
FOToPDFRoleMap.mapFormattingObject("page-sequence", rootStructureElement),
rootStructureElement);
@@ -132,49 +110,7 @@ class PDFLogicalStructureHandler {
if (language != null) {
structElemPart.setLanguage(language);
}
-
- for (int i = 0, n = structureTree.getLength(); i < n; i++) {
- Node node = structureTree.item(i);
- assert node.getLocalName().equals("flow")
- || node.getLocalName().equals("static-content");
- PDFStructElem structElemSect = pdfDoc.getFactory().makeStructureElement(
- FOToPDFRoleMap.mapFormattingObject(node.getLocalName(), structElemPart),
- structElemPart);
- structElemPart.addKid(structElemSect);
- NodeList childNodes = node.getChildNodes();
- for (int j = 0, m = childNodes.getLength(); j < m; j++) {
- processNode(childNodes.item(j), structElemSect, true);
- }
- }
- }
-
- private void processNode(Node node, PDFStructElem parent, boolean addKid) {
- Node attr = node.getAttributes().getNamedItemNS(InternalElementMapping.URI, "ptr");
- assert attr != null;
- String ptr = attr.getNodeValue();
- PDFStructElem structElem = pdfDoc.getFactory().makeStructureElement(
- FOToPDFRoleMap.mapFormattingObject(node, parent, eventBroadcaster), parent);
- // TODO necessary? If a page-sequence is empty (e.g., contains a single
- // empty fo:block), should the block still be added to the structure
- // tree? This is not being done for descendant empty elements...
- if (addKid) {
- parent.addKid(structElem);
- }
- String nodeName = node.getLocalName();
- if (nodeName.equals("external-graphic") || nodeName.equals("instream-foreign-object")) {
- Node altTextNode = node.getAttributes().getNamedItemNS(
- ExtensionElementMapping.URI, "alt-text");
- if (altTextNode != null) {
- structElem.put("Alt", altTextNode.getNodeValue());
- } else {
- structElem.put("Alt", "No alternate text specified");
- }
- }
- structTreeMap.put(ptr, structElem);
- NodeList nodes = node.getChildNodes();
- for (int i = 0, n = nodes.getLength(); i < n; i++) {
- processNode(nodes.item(i), structElem, false);
- }
+ return structElemPart;
}
private int getNextParentTreeKey() {
@@ -208,96 +144,79 @@ class PDFLogicalStructureHandler {
parentTree.getNums().put(currentPage.getStructParents(), pageParentTreeArray);
}
- private MarkedContentInfo addToParentTree(String structurePointer) {
- PDFStructElem parent = (PDFStructElem) structTreeMap.get(structurePointer);
- if (parent == null) {
- return ARTIFACT;
- } else {
- pageParentTreeArray.add(parent);
- String type = parent.getStructureType().toString();
- int mcid = pageParentTreeArray.length() - 1;
- return new MarkedContentInfo(type, mcid, parent);
- }
+ private MarkedContentInfo addToParentTree(PDFStructElem structureTreeElement) {
+ PDFStructElem parent = (structureTreeElement instanceof PDFStructElem.Placeholder)
+ ? structureTreeElement.getParentStructElem()
+ : structureTreeElement;
+ pageParentTreeArray.add(parent);
+ String type = parent.getStructureType().toString();
+ int mcid = pageParentTreeArray.length() - 1;
+ return new MarkedContentInfo(type, mcid, structureTreeElement);
}
/**
* Adds a content item corresponding to text into the structure tree, if
* there is a structure element associated to it.
*
- * @param structurePointer reference to the parent structure element of the
- * piece of text
+ * @param structElem the parent structure element of the piece of text
* @return the necessary information for bracketing the content as a
* marked-content sequence. If there is no element in the structure tree
* associated to that content, returns an instance whose
* {@link MarkedContentInfo#tag} value is <code>null</code>. The content
* must then be treated as an artifact.
*/
- MarkedContentInfo addTextContentItem(String structurePointer) {
- MarkedContentInfo mci = addToParentTree(structurePointer);
- if (mci != ARTIFACT) {
+ MarkedContentInfo addTextContentItem(PDFStructElem structElem) {
+ if (structElem == null) {
+ return ARTIFACT;
+ } else {
+ MarkedContentInfo mci = addToParentTree(structElem);
PDFDictionary contentItem = new PDFDictionary();
contentItem.put("Type", MCR);
contentItem.put("Pg", this.currentPage);
contentItem.put("MCID", mci.mcid);
mci.parent.addKid(contentItem);
+ return mci;
}
- return mci;
}
/**
* Adds a content item corresponding to an image into the structure tree, if
* there is a structure element associated to it.
*
- * @param structurePointer reference to the parent structure element of the
- * image
+ * @param structElem the parent structure element of the image
* @return the necessary information for bracketing the content as a
* marked-content sequence. If there is no element in the structure tree
* associated to that image, returns an instance whose
- * {@link MarkedContentInfo#tag} value is <code>null</code>. The image
- * must then be treated as an artifact.
+ * {@link MarkedContentInfo#tag} value is <code>null</code>. The image must
+ * then be treated as an artifact.
*/
- MarkedContentInfo addImageContentItem(String structurePointer) {
- MarkedContentInfo mci = addToParentTree(structurePointer);
- if (mci != ARTIFACT) {
+ MarkedContentInfo addImageContentItem(PDFStructElem structElem) {
+ if (structElem == null) {
+ return ARTIFACT;
+ } else {
+ MarkedContentInfo mci = addToParentTree(structElem);
mci.parent.setMCIDKid(mci.mcid);
mci.parent.setPage(this.currentPage);
+ return mci;
}
- return mci;
}
- // While the PDF spec allows images to be referred as PDF objects, this
- // makes the Acrobat Pro checker complain that the image is not accessible.
- // Its alt-text is still read aloud though. Using marked-content sequences
- // like for text works.
-// MarkedContentInfo addImageObject(String parentReference) {
-// MarkedContentInfo mci = addToParentTree(parentReference);
-// if (mci != ARTIFACT) {
-// PDFDictionary contentItem = new PDFDictionary();
-// contentItem.put("Type", OBJR);
-// contentItem.put("Pg", this.currentPage);
-// contentItem.put("Obj", null);
-// mci.parent.addKid(contentItem);
-// }
-// return mci;
-// }
-
/**
* Adds a content item corresponding to the given link into the structure
* tree.
*
* @param link a link
- * @param structurePointer reference to the corresponding parent structure element
+ * @param structureTreeElement its parent structure element
*/
- void addLinkContentItem(PDFLink link, String structurePointer) {
+ void addLinkContentItem(PDFLink link, PDFStructElem structureTreeElement) {
int structParent = getNextParentTreeKey();
link.setStructParent(structParent);
PDFDictionary contentItem = new PDFDictionary();
contentItem.put("Type", OBJR);
contentItem.put("Pg", this.currentPage);
contentItem.put("Obj", link);
- PDFStructElem parent = (PDFStructElem) structTreeMap.get(structurePointer);
- parentTree.getNums().put(structParent, parent);
- parent.addKid(contentItem);
+ parentTree.getNums().put(structParent, structureTreeElement);
+ structureTreeElement.addKid(contentItem);
}
}
diff --git a/src/java/org/apache/fop/render/pdf/PDFPainter.java b/src/java/org/apache/fop/render/pdf/PDFPainter.java
index 11af216a2..f2fbfd014 100644
--- a/src/java/org/apache/fop/render/pdf/PDFPainter.java
+++ b/src/java/org/apache/fop/render/pdf/PDFPainter.java
@@ -37,6 +37,7 @@ import org.apache.fop.fonts.SingleByteFont;
import org.apache.fop.fonts.Typeface;
import org.apache.fop.pdf.PDFDocument;
import org.apache.fop.pdf.PDFNumber;
+import org.apache.fop.pdf.PDFStructElem;
import org.apache.fop.pdf.PDFTextUtil;
import org.apache.fop.pdf.PDFXObject;
import org.apache.fop.render.RenderingContext;
@@ -133,24 +134,24 @@ public class PDFPainter extends AbstractIFPainter {
PDFXObject xobject = getPDFDoc().getXObject(uri);
if (xobject != null) {
if (accessEnabled) {
- String ptr = getContext().getStructurePointer();
- prepareImageMCID(ptr);
+ PDFStructElem structElem = (PDFStructElem) getContext().getStructureTreeElement();
+ prepareImageMCID(structElem);
placeImageAccess(rect, xobject);
} else {
placeImage(rect, xobject);
}
} else {
if (accessEnabled) {
- String ptr = getContext().getStructurePointer();
- prepareImageMCID(ptr);
+ PDFStructElem structElem = (PDFStructElem) getContext().getStructureTreeElement();
+ prepareImageMCID(structElem);
}
drawImageUsingURI(uri, rect);
flushPDFDoc();
}
}
- private void prepareImageMCID(String ptr) {
- imageMCI = logicalStructureHandler.addImageContentItem(ptr);
+ private void prepareImageMCID(PDFStructElem structElem) {
+ imageMCI = logicalStructureHandler.addImageContentItem(structElem);
}
/** {@inheritDoc} */
@@ -194,8 +195,8 @@ public class PDFPainter extends AbstractIFPainter {
/** {@inheritDoc} */
public void drawImage(Document doc, Rectangle rect) throws IFException {
if (accessEnabled) {
- String ptr = getContext().getStructurePointer();
- prepareImageMCID(ptr);
+ PDFStructElem structElem = (PDFStructElem) getContext().getStructureTreeElement();
+ prepareImageMCID(structElem);
}
drawImageUsingDocument(doc, rect);
flushPDFDoc();
@@ -294,8 +295,8 @@ public class PDFPainter extends AbstractIFPainter {
String text)
throws IFException {
if (accessEnabled) {
- String ptr = getContext().getStructurePointer();
- MarkedContentInfo mci = logicalStructureHandler.addTextContentItem(ptr);
+ PDFStructElem structElem = (PDFStructElem) getContext().getStructureTreeElement();
+ MarkedContentInfo mci = logicalStructureHandler.addTextContentItem(structElem);
if (generator.getTextUtil().isInTextObject()) {
generator.separateTextElements(mci.tag, mci.mcid);
}
diff --git a/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java b/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java
new file mode 100644
index 000000000..11eba4ea4
--- /dev/null
+++ b/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.pdf;
+
+import java.util.LinkedList;
+import java.util.Locale;
+
+import org.xml.sax.Attributes;
+
+import org.apache.fop.accessibility.StructureTreeElement;
+import org.apache.fop.accessibility.StructureTreeEventHandler;
+import org.apache.fop.events.EventBroadcaster;
+import org.apache.fop.fo.extensions.ExtensionElementMapping;
+import org.apache.fop.pdf.PDFFactory;
+import org.apache.fop.pdf.PDFStructElem;
+
+class PDFStructureTreeBuilder implements StructureTreeEventHandler {
+
+ private PDFFactory pdfFactory;
+
+ private PDFLogicalStructureHandler logicalStructureHandler;
+
+ private EventBroadcaster eventBroadcaster;
+
+ private LinkedList<PDFStructElem> ancestors = new LinkedList<PDFStructElem>();
+
+ void setPdfFactory(PDFFactory pdfFactory) {
+ this.pdfFactory = pdfFactory;
+ }
+
+ void setLogicalStructureHandler(PDFLogicalStructureHandler logicalStructureHandler) {
+ this.logicalStructureHandler = logicalStructureHandler;
+ }
+
+ void setEventBroadcaster(EventBroadcaster eventBroadcaster) {
+ this.eventBroadcaster = eventBroadcaster;
+ }
+
+ public void startPageSequence(Locale locale) {
+ ancestors = new LinkedList<PDFStructElem>();
+ ancestors.add(logicalStructureHandler.createPageSequence(locale));
+ }
+
+ public void endPageSequence() {
+ }
+
+ public StructureTreeElement startNode(String name, Attributes attributes) {
+ PDFStructElem parent = ancestors.getFirst();
+ String role = attributes.getValue("role");
+ PDFStructElem created;
+ created = pdfFactory.makeStructureElement(
+ FOToPDFRoleMap.mapFormattingObject(name, role, parent, eventBroadcaster), parent);
+ parent.addKid(created);
+ ancestors.addFirst(created);
+ return created;
+ }
+
+ public void endNode(String name) {
+ removeFirstAncestor();
+ }
+
+ private void removeFirstAncestor() {
+ ancestors.removeFirst();
+ }
+
+ public StructureTreeElement startImageNode(String name, Attributes attributes) {
+ PDFStructElem parent = ancestors.getFirst();
+ String role = attributes.getValue("role");
+ PDFStructElem created;
+ created = pdfFactory.makeStructureElement(
+ FOToPDFRoleMap.mapFormattingObject(name, role, parent, eventBroadcaster), parent);
+ parent.addKid(created);
+ String altTextNode = attributes.getValue(ExtensionElementMapping.URI, "alt-text");
+ if (altTextNode != null) {
+ created.put("Alt", altTextNode);
+ } else {
+ created.put("Alt", "No alternate text specified");
+ }
+ ancestors.addFirst(created);
+ return created;
+ }
+
+ public StructureTreeElement startReferencedNode(String name, Attributes attributes) {
+ PDFStructElem parent = ancestors.getFirst();
+ String role = attributes.getValue("role");
+ PDFStructElem created;
+ if ("#PCDATA".equals(name)) {
+ created = new PDFStructElem.Placeholder(parent, name);
+ } else {
+ created = pdfFactory.makeStructureElement(
+ FOToPDFRoleMap.mapFormattingObject(name, role, parent,
+ eventBroadcaster), parent);
+ }
+ parent.addKid(created);
+ ancestors.addFirst(created);
+ return created;
+ }
+
+}
diff --git a/src/java/org/apache/fop/render/rtf/RTFHandler.java b/src/java/org/apache/fop/render/rtf/RTFHandler.java
index 9abde32ce..22c0c8b76 100644
--- a/src/java/org/apache/fop/render/rtf/RTFHandler.java
+++ b/src/java/org/apache/fop/render/rtf/RTFHandler.java
@@ -937,10 +937,10 @@ public class RTFHandler extends FOEventHandler {
*/
//TODO: do this only, if the labels content <> previous labels content
if (list.getChildCount() > 0) {
- this.endListBody();
+ this.endListBody(null);
this.endList((ListBlock) li.getParent());
this.startList((ListBlock) li.getParent());
- this.startListBody();
+ this.startListBody(null);
list = (RtfList)builderContext.getContainer(
RtfList.class, true, this);
@@ -965,7 +965,7 @@ public class RTFHandler extends FOEventHandler {
}
/** {@inheritDoc} */
- public void startListLabel() {
+ public void startListLabel(ListItemLabel listItemLabel) {
if (bDefer) {
return;
}
@@ -985,7 +985,7 @@ public class RTFHandler extends FOEventHandler {
}
/** {@inheritDoc} */
- public void endListLabel() {
+ public void endListLabel(ListItemLabel listItemLabel) {
if (bDefer) {
return;
}
@@ -994,20 +994,20 @@ public class RTFHandler extends FOEventHandler {
}
/** {@inheritDoc} */
- public void startListBody() {
+ public void startListBody(ListItemBody listItemBody) {
}
/** {@inheritDoc} */
- public void endListBody() {
+ public void endListBody(ListItemBody listItemBody) {
}
// Static Regions
/** {@inheritDoc} */
- public void startStatic() {
+ public void startStatic(StaticContent staticContent) {
}
/** {@inheritDoc} */
- public void endStatic() {
+ public void endStatic(StaticContent statisContent) {
}
/** {@inheritDoc} */
@@ -1050,7 +1050,7 @@ public class RTFHandler extends FOEventHandler {
}
/** {@inheritDoc} */
- public void endLink() {
+ public void endLink(BasicLink basicLink) {
if (bDefer) {
return;
}
@@ -1090,7 +1090,7 @@ public class RTFHandler extends FOEventHandler {
}
/** {@inheritDoc} */
- public void foreignObject(InstreamForeignObject ifo) {
+ public void endInstreamForeignObject(InstreamForeignObject ifo) {
if (bDefer) {
return;
}
@@ -1337,7 +1337,7 @@ public class RTFHandler extends FOEventHandler {
}
/** {@inheritDoc} */
- public void leader(Leader l) {
+ public void startLeader(Leader l) {
if (bDefer) {
return;
}
@@ -1353,8 +1353,10 @@ public class RTFHandler extends FOEventHandler {
RtfTextrun textrun = container.getTextrun();
textrun.addLeader(rtfAttr);
-
- } catch (Exception e) {
+ } catch (IOException e) {
+ log.error("startLeader: " + e.getMessage());
+ throw new RuntimeException(e.getMessage());
+ } catch (FOPException e) {
log.error("startLeader: " + e.getMessage());
throw new RuntimeException(e.getMessage());
}
@@ -1362,11 +1364,9 @@ public class RTFHandler extends FOEventHandler {
/**
* @param text FOText object
- * @param data Array of characters to process.
- * @param start Offset for characters to process.
- * @param length Portion of array to process.
+ * @param characters CharSequence of the characters to process.
*/
- public void text(FOText text, char[] data, int start, int length) {
+ public void text(FOText text, CharSequence characters) {
if (bDefer) {
return;
}
@@ -1381,7 +1381,7 @@ public class RTFHandler extends FOEventHandler {
= TextAttributesConverter.convertCharacterAttributes(text);
textrun.pushInlineAttributes(rtfAttr);
- textrun.addString(new String(data, start, length - start));
+ textrun.addString(characters.toString());
textrun.popInlineAttributes();
} catch (IOException ioe) {
handleIOTrouble(ioe);
@@ -1518,9 +1518,9 @@ public class RTFHandler extends FOEventHandler {
}
} else if (foNode instanceof StaticContent) {
if (bStart) {
- startStatic();
+ startStatic(null);
} else {
- endStatic();
+ endStatic(null);
}
} else if (foNode instanceof ExternalGraphic) {
if (bStart) {
@@ -1528,7 +1528,7 @@ public class RTFHandler extends FOEventHandler {
}
} else if (foNode instanceof InstreamForeignObject) {
if (bStart) {
- foreignObject( (InstreamForeignObject) foNode );
+ endInstreamForeignObject( (InstreamForeignObject) foNode );
}
} else if (foNode instanceof Block) {
if (bStart) {
@@ -1547,7 +1547,7 @@ public class RTFHandler extends FOEventHandler {
if (bStart) {
startLink( (BasicLink) foNode);
} else {
- endLink();
+ endLink(null);
}
} else if (foNode instanceof Inline) {
if (bStart) {
@@ -1558,7 +1558,7 @@ public class RTFHandler extends FOEventHandler {
} else if (foNode instanceof FOText) {
if (bStart) {
FOText text = (FOText) foNode;
- text(text, text.getCharArray(), 0, text.length());
+ text(text, text.getCharSequence());
}
} else if (foNode instanceof Character) {
if (bStart) {
@@ -1591,9 +1591,9 @@ public class RTFHandler extends FOEventHandler {
}
} else if (foNode instanceof ListItemBody) {
if (bStart) {
- startListBody();
+ startListBody(null);
} else {
- endListBody();
+ endListBody(null);
}
} else if (foNode instanceof ListItem) {
if (bStart) {
@@ -1603,9 +1603,9 @@ public class RTFHandler extends FOEventHandler {
}
} else if (foNode instanceof ListItemLabel) {
if (bStart) {
- startListLabel();
+ startListLabel(null);
} else {
- endListLabel();
+ endListLabel(null);
}
} else if (foNode instanceof Table) {
if (bStart) {
@@ -1651,7 +1651,7 @@ public class RTFHandler extends FOEventHandler {
}
} else if (foNode instanceof Leader) {
if (bStart) {
- leader((Leader) foNode);
+ startLeader((Leader) foNode);
}
} else if (foNode instanceof PageNumberCitation) {
if (bStart) {
diff --git a/src/java/org/apache/fop/render/xml/XMLRenderer.java b/src/java/org/apache/fop/render/xml/XMLRenderer.java
index d2cd55abe..504133c09 100644
--- a/src/java/org/apache/fop/render/xml/XMLRenderer.java
+++ b/src/java/org/apache/fop/render/xml/XMLRenderer.java
@@ -35,8 +35,6 @@ import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.apache.xmlgraphics.util.QName;
@@ -82,15 +80,12 @@ import org.apache.fop.area.inline.TextArea;
import org.apache.fop.area.inline.WordArea;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.extensions.ExtensionAttachment;
-import org.apache.fop.fo.extensions.ExtensionElementMapping;
-import org.apache.fop.fo.extensions.InternalElementMapping;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.render.Renderer;
import org.apache.fop.render.RendererContext;
import org.apache.fop.render.XMLHandler;
import org.apache.fop.util.ColorUtil;
-import org.apache.fop.util.DOM2SAX;
/**
* Renderer that renders areas to XML for debugging purposes.
@@ -110,8 +105,6 @@ public class XMLRenderer extends AbstractXMLRenderer {
/** If not null, the XMLRenderer will mimic another renderer by using its font setup. */
protected Renderer mimic;
- private int pageSequenceIndex;
-
/**
* @param userAgent the user agent that contains configuration details. This cannot be null.
*/
@@ -452,29 +445,6 @@ public class XMLRenderer extends AbstractXMLRenderer {
}
transferForeignObjects(pageSequence);
startElement("pageSequence", atts);
- if (this.getUserAgent().isAccessibilityEnabled()) {
- String structureTreeElement = "structureTree";
- startElement(structureTreeElement);
- try {
- this.handler.startPrefixMapping("foi", InternalElementMapping.URI);
- this.handler.startPrefixMapping("fox", ExtensionElementMapping.URI);
- NodeList nodes = getUserAgent().getStructureTree().getPageSequence(
- pageSequenceIndex++);
- for (int i = 0, n = nodes.getLength(); i < n; i++) {
- Node node = nodes.item(i);
- try {
- new DOM2SAX(handler).writeFragment(node);
- } catch (SAXException e) {
- handleSAXException(e);
- }
- }
- this.handler.endPrefixMapping("fox");
- this.handler.endPrefixMapping("foi");
- } catch (SAXException se) {
- handleSAXException(se);
- }
- endElement(structureTreeElement);
- }
handleExtensionAttachments(pageSequence.getExtensionAttachments());
LineArea seqTitle = pageSequence.getTitle();
if (seqTitle != null) {
diff --git a/src/java/org/apache/fop/util/LanguageTags.java b/src/java/org/apache/fop/util/LanguageTags.java
new file mode 100644
index 000000000..662fab908
--- /dev/null
+++ b/src/java/org/apache/fop/util/LanguageTags.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.util;
+
+import java.util.Locale;
+
+/**
+ * Provides utility methods for manipulating language tags compliant with the
+ * RFC 3066 specification available at http://www.ietf.org/rfc/rfc3066.txt. A
+ * typical language tag is a 2-letter language code sometimes followed by a country
+ * code. For example: en, en-US.
+ */
+public final class LanguageTags {
+
+ private LanguageTags() {
+ }
+
+ /**
+ * Converts the given locale to an RFC 3066 compliant language tag.
+ *
+ * @param locale a locale
+ * @return the corresponding language tag
+ */
+ public static String toLanguageTag(Locale locale) {
+ StringBuffer sb = new StringBuffer(5);
+ sb.append(locale.getLanguage());
+ String country = locale.getCountry();
+ if (country.length() > 0) {
+ sb.append('-');
+ sb.append(country);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Converts an RFC 3066 compliant language tag to a locale.
+ *
+ * @param languageTag language tag to convert
+ * @return the corresponding locale
+ */
+ public static Locale toLocale(String languageTag) {
+ String[] parts = languageTag.split("-");
+ if (parts.length == 1) {
+ return new Locale(parts[0]);
+ } else {
+ return new Locale(parts[0], parts[1]);
+ }
+ }
+}
diff --git a/src/java/org/apache/fop/util/XMLUtil.java b/src/java/org/apache/fop/util/XMLUtil.java
index 0a55ce573..d4397c2c7 100644
--- a/src/java/org/apache/fop/util/XMLUtil.java
+++ b/src/java/org/apache/fop/util/XMLUtil.java
@@ -21,7 +21,6 @@ package org.apache.fop.util;
import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;
-import java.util.Locale;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
@@ -174,39 +173,4 @@ public final class XMLUtil implements XMLConstants {
atts.addAttribute("", localName, localName, XMLUtil.CDATA, value);
}
- /**
- * Converts a {@link Locale} instance to an RFC 3066 compliant language identifier.
- * @param language the language
- * @return the formatted language identifier
- */
- public static String toRFC3066(Locale language) {
- if (language == null || language.getLanguage().length() == 0) {
- return null;
- }
- StringBuffer sb = new StringBuffer();
- sb.append(language.getLanguage());
- if (language.getCountry().length() > 0) {
- sb.append('-');
- sb.append(language.getCountry());
- }
- return sb.toString();
- }
-
- /**
- * Converts an RFC 3066 compliant language identifier to a {@link Locale} instance.
- * @param lang the language string
- * @return the converted locale instance
- */
- public static Locale convertRFC3066ToLocale(String lang) {
- if (lang == null || lang.length() == 0) {
- return null;
- }
- String[] parts = lang.split("-");
- if (parts.length == 1) {
- return new Locale(parts[0]);
- } else {
- return new Locale(parts[0], parts[1]);
- }
- }
-
}
diff --git a/status.xml b/status.xml
index b395abe1e..a5d800c61 100644
--- a/status.xml
+++ b/status.xml
@@ -61,6 +61,9 @@
documents. Example: the fix of marks layering will be such a case when it's done.
-->
<release version="FOP Trunk" date="TBD">
+ <action context="Code" dev="PH" type="add" due-to="VH and PH">
+ Improvements of the Accessibility feature
+ </action>
<action context="Code" dev="CB" type="add" fixes-bug="52416" due-to="Luis Bernardo">
Suppress unnecessary "font not found warnings" when generating AFP with raster fonts
</action>
diff --git a/test/accessibility/README b/test/accessibility/README
index 391d39055..1d2e04361 100644
--- a/test/accessibility/README
+++ b/test/accessibility/README
@@ -1,11 +1,8 @@
This directory contains sample FO files for testing the accessibility features
of FOP.
-To every FO file in this directory correspond two PDF files in the pdf/
-sub-directory: one generated by the painter, one by the renderer. For example,
-the text_1.fo file has been rendered into pdf/text_1_painter_orig.pdf and
-pdf/text_1_renderer_orig.pdf. The configuration file config-painter.xconf (resp.
-config-renderer.xconf) was used.
+Every FO file in this directory has a corresponding PDF file in the pdf/
+sub-directory. The fop.xconf configuration file was used.
The PDF files have been checked with Adobe Acrobat Professional 9, using both
the full accessibility checker and the read-aloud feature. The checker reports
@@ -22,7 +19,7 @@ problem yet part or all of the document cannot be read aloud.)
The purpose of this infrastructure is to be able to quickly re-test the
accessibility processing chain when any change has been made to it. The
-configuration files disable the compression of the PDF streams, so it is
+configuration file disables the compression of the PDF streams, so it is
possible to compare a re-generated PDF with the original one by using a simple
diff tool. The files will not be identical because of the different creation
dates (and the ID key in the trailer), but apart from that there should be no
@@ -32,21 +29,13 @@ The rationale is that using a diff tool is much quicker and less tedious than
running Acrobat's accessibility checker and read-aloud feature every time.
-To re-generate the PDF files using the painter:
- ../../fop -c config-painter.xconf text_1.fo pdf/text_1_painter.pdf
- diff pdf/text_1_painter_orig.pdf pdf/text_1_painter.pdf
+To re-generate the PDF files:
+ ../../fop -c fop.xconf text_1.fo pdf/text_1.new.pdf
+ diff pdf/text_1_painter.pdf pdf/text_1.new.pdf
Or, going through the intermediate format:
- ../../fop -c config-painter.xconf text_1.fo -if application/pdf text_1_if.xml
- ../../fop -c config-painter.xconf -ifin text_1_if.xml pdf/text_1_painter.pdf
- diff pdf/text_1_painter_orig.pdf pdf/text_1_painter.pdf
-
-To re-generate the PDF files using the legacy renderer:
- ../../fop -c config-renderer.xconf text_1.fo pdf/text_1_renderer.pdf
- diff pdf/text_1_renderer_orig.pdf pdf/text_1_renderer.pdf
-Or, going through the intermediate format:
- ../../fop -c config-renderer.xconf text_1.fo -at application/pdf text_1_at.xml
- ../../fop -c config-renderer.xconf -atin text_1_at.xml pdf/text_1_renderer.pdf
- diff pdf/text_1_renderer_orig.pdf pdf/text_1_renderer.pdf
+ ../../fop -c fop.xconf text_1.fo -if application/pdf text_1_if.xml
+ ../../fop -c fop.xconf -ifin text_1_if.xml pdf/text_1.new.pdf
+ diff pdf/text_1.pdf pdf/text_1.new.pdf
$Id$
diff --git a/test/accessibility/background-image_jpg_repeat.fo b/test/accessibility/background-image_jpg_repeat.fo
index 2c8f7f66d..727162e49 100644
--- a/test/accessibility/background-image_jpg_repeat.fo
+++ b/test/accessibility/background-image_jpg_repeat.fo
@@ -16,14 +16,14 @@
limitations under the License.
-->
<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
<fo:layout-master-set>
<fo:simple-page-master master-name="page"
page-height="220pt" page-width="320pt" margin="10pt">
<fo:region-body background-image="../resources/images/bgimg72dpi.jpg"/>
</fo:simple-page-master>
</fo:layout-master-set>
- <fo:page-sequence master-reference="page" language="en" country="GB">
+ <fo:page-sequence master-reference="page">
<fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
<fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
formatting objects (XSL-FO) and an output independent formatter. It is a Java application
diff --git a/test/accessibility/background-image_jpg_single.fo b/test/accessibility/background-image_jpg_single.fo
index 2250c24e2..335353e03 100644
--- a/test/accessibility/background-image_jpg_single.fo
+++ b/test/accessibility/background-image_jpg_single.fo
@@ -16,7 +16,7 @@
limitations under the License.
-->
<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
<fo:layout-master-set>
<fo:simple-page-master master-name="page"
page-height="220pt" page-width="320pt" margin="10pt">
@@ -25,7 +25,7 @@
background-position-vertical="50%"/>
</fo:simple-page-master>
</fo:layout-master-set>
- <fo:page-sequence master-reference="page" language="en" country="GB">
+ <fo:page-sequence master-reference="page">
<fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
<fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
formatting objects (XSL-FO) and an output independent formatter. It is a Java application
diff --git a/test/accessibility/background-image_png_repeat.fo b/test/accessibility/background-image_png_repeat.fo
index 7506c0f2b..5e4a8ba0d 100644
--- a/test/accessibility/background-image_png_repeat.fo
+++ b/test/accessibility/background-image_png_repeat.fo
@@ -16,14 +16,14 @@
limitations under the License.
-->
<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
<fo:layout-master-set>
<fo:simple-page-master master-name="page"
page-height="220pt" page-width="320pt" margin="10pt">
<fo:region-body background-image="../resources/images/bgimg72dpi.png"/>
</fo:simple-page-master>
</fo:layout-master-set>
- <fo:page-sequence master-reference="page" language="en" country="GB">
+ <fo:page-sequence master-reference="page">
<fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
<fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
formatting objects (XSL-FO) and an output independent formatter. It is a Java application
diff --git a/test/accessibility/background-image_png_single.fo b/test/accessibility/background-image_png_single.fo
index 1f60e9411..90067ec53 100644
--- a/test/accessibility/background-image_png_single.fo
+++ b/test/accessibility/background-image_png_single.fo
@@ -16,7 +16,7 @@
limitations under the License.
-->
<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
<fo:layout-master-set>
<fo:simple-page-master master-name="page"
page-height="220pt" page-width="320pt" margin="10pt">
@@ -25,7 +25,7 @@
background-position-vertical="50%"/>
</fo:simple-page-master>
</fo:layout-master-set>
- <fo:page-sequence master-reference="page" language="en" country="GB">
+ <fo:page-sequence master-reference="page">
<fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
<fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
formatting objects (XSL-FO) and an output independent formatter. It is a Java application
diff --git a/test/accessibility/background-image_svg_repeat.fo b/test/accessibility/background-image_svg_repeat.fo
index 6e71409d0..02520b6cf 100644
--- a/test/accessibility/background-image_svg_repeat.fo
+++ b/test/accessibility/background-image_svg_repeat.fo
@@ -16,14 +16,14 @@
limitations under the License.
-->
<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
<fo:layout-master-set>
<fo:simple-page-master master-name="page"
page-height="220pt" page-width="320pt" margin="10pt">
<fo:region-body background-image="../resources/images/rgb-circles.svg"/>
</fo:simple-page-master>
</fo:layout-master-set>
- <fo:page-sequence master-reference="page" language="en" country="GB">
+ <fo:page-sequence master-reference="page">
<fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
<fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
formatting objects (XSL-FO) and an output independent formatter. It is a Java application
diff --git a/test/accessibility/background-image_svg_single.fo b/test/accessibility/background-image_svg_single.fo
index 9dc67c86c..3029f32ec 100644
--- a/test/accessibility/background-image_svg_single.fo
+++ b/test/accessibility/background-image_svg_single.fo
@@ -16,7 +16,7 @@
limitations under the License.
-->
<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
<fo:layout-master-set>
<fo:simple-page-master master-name="page"
page-height="220pt" page-width="320pt" margin="10pt">
@@ -25,7 +25,7 @@
background-position-vertical="50%"/>
</fo:simple-page-master>
</fo:layout-master-set>
- <fo:page-sequence master-reference="page" language="en" country="GB">
+ <fo:page-sequence master-reference="page">
<fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
<fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
formatting objects (XSL-FO) and an output independent formatter. It is a Java application
diff --git a/test/accessibility/complete.fo b/test/accessibility/complete.fo
index 81df372b5..75684750c 100644
--- a/test/accessibility/complete.fo
+++ b/test/accessibility/complete.fo
@@ -17,7 +17,7 @@
-->
<!-- $Id$ -->
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
- xmlns:fox="http://xmlgraphics.apache.org/fop/extensions">
+ xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
<fo:layout-master-set>
<fo:simple-page-master master-name="page"
page-height="220pt" page-width="320pt" margin="10pt">
@@ -25,7 +25,7 @@
<fo:region-before extent="12pt"/>
</fo:simple-page-master>
</fo:layout-master-set>
- <fo:page-sequence master-reference="page" language="en" country="GB">
+ <fo:page-sequence master-reference="page">
<fo:static-content flow-name="xsl-region-before">
<fo:block font-size="8pt" text-align-last="justify">This is the page header<fo:leader/>Page
<fo:page-number/></fo:block>
@@ -117,7 +117,7 @@
<fo:block>And now we are going to see how a second page sequence is handled.</fo:block>
</fo:flow>
</fo:page-sequence>
- <fo:page-sequence master-reference="page" language="en" country="GB">
+ <fo:page-sequence master-reference="page">
<fo:static-content flow-name="xsl-region-before">
<fo:block font-size="8pt" text-align-last="justify">This is the page header<fo:leader/>Page
<fo:page-number/></fo:block>
diff --git a/test/accessibility/config-renderer.xconf b/test/accessibility/config-renderer.xconf
deleted file mode 100644
index 4b55e393f..000000000
--- a/test/accessibility/config-renderer.xconf
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<fop version="1.0">
- <prefer-renderer>true</prefer-renderer>
- <accessibility>true</accessibility>
- <source-resolution>144</source-resolution>
- <use-cache>false</use-cache>
- <font-base>../resources/fonts/</font-base>
- <renderers>
- <renderer mime="application/pdf">
- <filterList>
- <value>null</value>
- </filterList>
- <filterList type="image">
- <value>flate</value>
- <value>ascii-85</value>
- </filterList>
- <fonts>
- <font embed-url="DejaVuLGCSerif.ttf">
- <font-triplet name="DejaVu" style="normal" weight="normal"/>
- </font>
- </fonts>
- </renderer>
- </renderers>
-</fop>
diff --git a/test/accessibility/config-painter.xconf b/test/accessibility/fop.xconf
index 8c5dc2bd5..8c5dc2bd5 100644
--- a/test/accessibility/config-painter.xconf
+++ b/test/accessibility/fop.xconf
diff --git a/test/accessibility/image_jpg.fo b/test/accessibility/image_jpg.fo
index be0e24bee..5fe36f61a 100644
--- a/test/accessibility/image_jpg.fo
+++ b/test/accessibility/image_jpg.fo
@@ -17,14 +17,14 @@
-->
<!-- $Id$ -->
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
- xmlns:fox="http://xmlgraphics.apache.org/fop/extensions">
+ xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
<fo:layout-master-set>
<fo:simple-page-master master-name="page"
page-height="220pt" page-width="320pt" margin="10pt">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
- <fo:page-sequence master-reference="page" language="en" country="GB">
+ <fo:page-sequence master-reference="page">
<fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
<fo:block>This document contains an image in the JPEG format: <fo:external-graphic
src="../resources/images/cmyk.jpg"
diff --git a/test/accessibility/image_png.fo b/test/accessibility/image_png.fo
index 3bcd12f4f..b529aa8c8 100644
--- a/test/accessibility/image_png.fo
+++ b/test/accessibility/image_png.fo
@@ -17,14 +17,14 @@
-->
<!-- $Id$ -->
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
- xmlns:fox="http://xmlgraphics.apache.org/fop/extensions">
+ xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
<fo:layout-master-set>
<fo:simple-page-master master-name="page"
page-height="220pt" page-width="320pt" margin="10pt">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
- <fo:page-sequence master-reference="page" language="en" country="GB">
+ <fo:page-sequence master-reference="page">
<fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
<fo:block>This document contains an image in the PNG format: <fo:external-graphic
src="../resources/images/fop-logo-color-24bit.png"
diff --git a/test/accessibility/image_svg.fo b/test/accessibility/image_svg.fo
index 4fac16be5..bbc77fe65 100644
--- a/test/accessibility/image_svg.fo
+++ b/test/accessibility/image_svg.fo
@@ -17,14 +17,14 @@
-->
<!-- $Id$ -->
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
- xmlns:fox="http://xmlgraphics.apache.org/fop/extensions">
+ xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
<fo:layout-master-set>
<fo:simple-page-master master-name="page"
page-height="220pt" page-width="320pt" margin="10pt">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
- <fo:page-sequence master-reference="page" language="en" country="GB">
+ <fo:page-sequence master-reference="page">
<fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
<fo:block>This document contains an image in the SVG format: <fo:external-graphic
src="../resources/images/circles.svg"
diff --git a/test/accessibility/image_wmf.fo b/test/accessibility/image_wmf.fo
index 729b48586..1a4de777b 100644
--- a/test/accessibility/image_wmf.fo
+++ b/test/accessibility/image_wmf.fo
@@ -17,14 +17,14 @@
-->
<!-- $Id$ -->
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
- xmlns:fox="http://xmlgraphics.apache.org/fop/extensions">
+ xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
<fo:layout-master-set>
<fo:simple-page-master master-name="page"
page-height="320pt" page-width="320pt" margin="10pt">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
- <fo:page-sequence master-reference="page" language="en" country="GB">
+ <fo:page-sequence master-reference="page">
<fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
<fo:block>This document contains an image in the WMF format: <fo:external-graphic
src="../resources/images/testChart.wmf"
diff --git a/test/accessibility/leader.fo b/test/accessibility/leader.fo
index 91c9243e0..ffd768021 100644
--- a/test/accessibility/leader.fo
+++ b/test/accessibility/leader.fo
@@ -16,14 +16,14 @@
limitations under the License.
-->
<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
<fo:layout-master-set>
<fo:simple-page-master master-name="page"
page-height="220pt" page-width="320pt" margin="10pt">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
- <fo:page-sequence master-reference="page" language="en" country="GB">
+ <fo:page-sequence master-reference="page">
<fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify"
text-align-last="justify">
<fo:block>This is a text followed by a leader with leader-pattern=​"use-content", the
diff --git a/test/accessibility/links.fo b/test/accessibility/links.fo
index 66f0f66f4..36250e332 100644
--- a/test/accessibility/links.fo
+++ b/test/accessibility/links.fo
@@ -17,14 +17,14 @@
-->
<!-- $Id$ -->
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
- xmlns:fox="http://xmlgraphics.apache.org/fop/extensions">
+ xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
<fo:layout-master-set>
<fo:simple-page-master master-name="page"
page-height="220pt" page-width="320pt" margin="10pt">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
- <fo:page-sequence master-reference="page" language="en" country="GB">
+ <fo:page-sequence master-reference="page">
<fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
<fo:block>This is a <fo:wrapper color="blue"><fo:basic-link
internal-destination="FOP">link</fo:basic-link></fo:wrapper> to the next
diff --git a/test/accessibility/pdf/background-image_jpg_repeat_painter_orig.pdf b/test/accessibility/pdf/background-image_jpg_repeat.pdf
index c7c27f9d1..221761757 100644
--- a/test/accessibility/pdf/background-image_jpg_repeat_painter_orig.pdf
+++ b/test/accessibility/pdf/background-image_jpg_repeat.pdf
Binary files differ
diff --git a/test/accessibility/pdf/background-image_jpg_repeat_renderer_orig.pdf b/test/accessibility/pdf/background-image_jpg_repeat_renderer_orig.pdf
deleted file mode 100644
index ee5d89d40..000000000
--- a/test/accessibility/pdf/background-image_jpg_repeat_renderer_orig.pdf
+++ /dev/null
Binary files differ
diff --git a/test/accessibility/pdf/background-image_jpg_single_painter_orig.pdf b/test/accessibility/pdf/background-image_jpg_single.pdf
index 080f0b876..232afdd05 100644
--- a/test/accessibility/pdf/background-image_jpg_single_painter_orig.pdf
+++ b/test/accessibility/pdf/background-image_jpg_single.pdf
Binary files differ
diff --git a/test/accessibility/pdf/background-image_jpg_single_renderer_orig.pdf b/test/accessibility/pdf/background-image_jpg_single_renderer_orig.pdf
deleted file mode 100644
index 4d04ca427..000000000
--- a/test/accessibility/pdf/background-image_jpg_single_renderer_orig.pdf
+++ /dev/null
Binary files differ
diff --git a/test/accessibility/pdf/background-image_png_repeat_painter_orig.pdf b/test/accessibility/pdf/background-image_png_repeat.pdf
index a10e1357e..52da4020a 100644
--- a/test/accessibility/pdf/background-image_png_repeat_painter_orig.pdf
+++ b/test/accessibility/pdf/background-image_png_repeat.pdf
Binary files differ
diff --git a/test/accessibility/pdf/background-image_png_repeat_renderer_orig.pdf b/test/accessibility/pdf/background-image_png_repeat_renderer_orig.pdf
deleted file mode 100644
index 982c50cc9..000000000
--- a/test/accessibility/pdf/background-image_png_repeat_renderer_orig.pdf
+++ /dev/null
Binary files differ
diff --git a/test/accessibility/pdf/background-image_png_single.pdf b/test/accessibility/pdf/background-image_png_single.pdf
new file mode 100644
index 000000000..356e4885c
--- /dev/null
+++ b/test/accessibility/pdf/background-image_png_single.pdf
Binary files differ
diff --git a/test/accessibility/pdf/background-image_png_single_painter_orig.pdf b/test/accessibility/pdf/background-image_png_single_painter_orig.pdf
deleted file mode 100644
index 1e9ff00b4..000000000
--- a/test/accessibility/pdf/background-image_png_single_painter_orig.pdf
+++ /dev/null
Binary files differ
diff --git a/test/accessibility/pdf/background-image_png_single_renderer_orig.pdf b/test/accessibility/pdf/background-image_png_single_renderer_orig.pdf
deleted file mode 100644
index 2c7084dd8..000000000
--- a/test/accessibility/pdf/background-image_png_single_renderer_orig.pdf
+++ /dev/null
Binary files differ
diff --git a/test/accessibility/pdf/background-image_svg_repeat_painter_orig.pdf b/test/accessibility/pdf/background-image_svg_repeat.pdf
index c641fbbe5..0bce2404d 100644
--- a/test/accessibility/pdf/background-image_svg_repeat_painter_orig.pdf
+++ b/test/accessibility/pdf/background-image_svg_repeat.pdf
Binary files differ
diff --git a/test/accessibility/pdf/background-image_svg_repeat_renderer_orig.pdf b/test/accessibility/pdf/background-image_svg_repeat_renderer_orig.pdf
deleted file mode 100644
index 65d71109e..000000000
--- a/test/accessibility/pdf/background-image_svg_repeat_renderer_orig.pdf
+++ /dev/null
Binary files differ
diff --git a/test/accessibility/pdf/background-image_svg_single_painter_orig.pdf b/test/accessibility/pdf/background-image_svg_single.pdf
index 09a9ad895..3e4afcdcf 100644
--- a/test/accessibility/pdf/background-image_svg_single_painter_orig.pdf
+++ b/test/accessibility/pdf/background-image_svg_single.pdf
Binary files differ
diff --git a/test/accessibility/pdf/background-image_svg_single_renderer_orig.pdf b/test/accessibility/pdf/background-image_svg_single_renderer_orig.pdf
deleted file mode 100644
index b7c5a71e9..000000000
--- a/test/accessibility/pdf/background-image_svg_single_renderer_orig.pdf
+++ /dev/null
Binary files differ
diff --git a/test/accessibility/pdf/complete.pdf b/test/accessibility/pdf/complete.pdf
new file mode 100644
index 000000000..cffb9e2cb
--- /dev/null
+++ b/test/accessibility/pdf/complete.pdf
Binary files differ
diff --git a/test/accessibility/pdf/complete_painter_orig.pdf b/test/accessibility/pdf/complete_painter_orig.pdf
deleted file mode 100644
index caf7a41f8..000000000
--- a/test/accessibility/pdf/complete_painter_orig.pdf
+++ /dev/null
Binary files differ
diff --git a/test/accessibility/pdf/complete_renderer_orig.pdf b/test/accessibility/pdf/complete_renderer_orig.pdf
deleted file mode 100644
index e7e4ed6c1..000000000
--- a/test/accessibility/pdf/complete_renderer_orig.pdf
+++ /dev/null
Binary files differ
diff --git a/test/accessibility/pdf/image_jpg_painter_orig.pdf b/test/accessibility/pdf/image_jpg.pdf
index 1336f99eb..cb004bbd2 100644
--- a/test/accessibility/pdf/image_jpg_painter_orig.pdf
+++ b/test/accessibility/pdf/image_jpg.pdf
Binary files differ
diff --git a/test/accessibility/pdf/image_jpg_renderer_orig.pdf b/test/accessibility/pdf/image_jpg_renderer_orig.pdf
deleted file mode 100644
index 62be9c16c..000000000
--- a/test/accessibility/pdf/image_jpg_renderer_orig.pdf
+++ /dev/null
Binary files differ
diff --git a/test/accessibility/pdf/image_png.pdf b/test/accessibility/pdf/image_png.pdf
new file mode 100644
index 000000000..c3289374f
--- /dev/null
+++ b/test/accessibility/pdf/image_png.pdf
Binary files differ
diff --git a/test/accessibility/pdf/image_png_painter_orig.pdf b/test/accessibility/pdf/image_png_painter_orig.pdf
deleted file mode 100644
index b22c157b0..000000000
--- a/test/accessibility/pdf/image_png_painter_orig.pdf
+++ /dev/null
Binary files differ
diff --git a/test/accessibility/pdf/image_png_renderer_orig.pdf b/test/accessibility/pdf/image_png_renderer_orig.pdf
deleted file mode 100644
index efd5d2bdd..000000000
--- a/test/accessibility/pdf/image_png_renderer_orig.pdf
+++ /dev/null
Binary files differ
diff --git a/test/accessibility/pdf/image_svg_painter_orig.pdf b/test/accessibility/pdf/image_svg.pdf
index 1f5393c43..c3fce5b0e 100644
--- a/test/accessibility/pdf/image_svg_painter_orig.pdf
+++ b/test/accessibility/pdf/image_svg.pdf
Binary files differ
diff --git a/test/accessibility/pdf/image_svg_renderer_orig.pdf b/test/accessibility/pdf/image_svg_renderer_orig.pdf
deleted file mode 100644
index 9c020706d..000000000
--- a/test/accessibility/pdf/image_svg_renderer_orig.pdf
+++ /dev/null
Binary files differ
diff --git a/test/accessibility/pdf/image_wmf.pdf b/test/accessibility/pdf/image_wmf.pdf
new file mode 100644
index 000000000..b9ec8c55a
--- /dev/null
+++ b/test/accessibility/pdf/image_wmf.pdf
Binary files differ
diff --git a/test/accessibility/pdf/image_wmf_painter_orig.pdf b/test/accessibility/pdf/image_wmf_painter_orig.pdf
deleted file mode 100644
index 599b4c5ff..000000000
--- a/test/accessibility/pdf/image_wmf_painter_orig.pdf
+++ /dev/null
Binary files differ
diff --git a/test/accessibility/pdf/image_wmf_renderer_orig.pdf b/test/accessibility/pdf/image_wmf_renderer_orig.pdf
deleted file mode 100644
index c82134915..000000000
--- a/test/accessibility/pdf/image_wmf_renderer_orig.pdf
+++ /dev/null
Binary files differ
diff --git a/test/accessibility/pdf/leader_painter_orig.pdf b/test/accessibility/pdf/leader.pdf
index cf77a5c96..c7432e751 100644
--- a/test/accessibility/pdf/leader_painter_orig.pdf
+++ b/test/accessibility/pdf/leader.pdf
Binary files differ
diff --git a/test/accessibility/pdf/leader_renderer_orig.pdf b/test/accessibility/pdf/leader_renderer_orig.pdf
deleted file mode 100644
index 27c3afbde..000000000
--- a/test/accessibility/pdf/leader_renderer_orig.pdf
+++ /dev/null
Binary files differ
diff --git a/test/accessibility/pdf/links_painter_orig.pdf b/test/accessibility/pdf/links.pdf
index ee37c72d6..91d7c2592 100644
--- a/test/accessibility/pdf/links_painter_orig.pdf
+++ b/test/accessibility/pdf/links.pdf
Binary files differ
diff --git a/test/accessibility/pdf/links_renderer_orig.pdf b/test/accessibility/pdf/links_renderer_orig.pdf
deleted file mode 100644
index 2bae65033..000000000
--- a/test/accessibility/pdf/links_renderer_orig.pdf
+++ /dev/null
Binary files differ
diff --git a/test/accessibility/pdf/role_painter_orig.pdf b/test/accessibility/pdf/role.pdf
index 1eaaf1a9d..acb435027 100644
--- a/test/accessibility/pdf/role_painter_orig.pdf
+++ b/test/accessibility/pdf/role.pdf
Binary files differ
diff --git a/test/accessibility/pdf/role_non-standard_painter_orig.pdf b/test/accessibility/pdf/role_non-standard.pdf
index f8b1c9d2c..fcf614ed1 100644
--- a/test/accessibility/pdf/role_non-standard_painter_orig.pdf
+++ b/test/accessibility/pdf/role_non-standard.pdf
Binary files differ
diff --git a/test/accessibility/pdf/role_non-standard_renderer_orig.pdf b/test/accessibility/pdf/role_non-standard_renderer_orig.pdf
deleted file mode 100644
index 1700d7c03..000000000
--- a/test/accessibility/pdf/role_non-standard_renderer_orig.pdf
+++ /dev/null
Binary files differ
diff --git a/test/accessibility/pdf/role_renderer_orig.pdf b/test/accessibility/pdf/role_renderer_orig.pdf
deleted file mode 100644
index fc8e002a8..000000000
--- a/test/accessibility/pdf/role_renderer_orig.pdf
+++ /dev/null
Binary files differ
diff --git a/test/accessibility/pdf/text_1_painter_orig.pdf b/test/accessibility/pdf/text_1.pdf
index 2ad8a12f2..596419c9d 100644
--- a/test/accessibility/pdf/text_1_painter_orig.pdf
+++ b/test/accessibility/pdf/text_1.pdf
Binary files differ
diff --git a/test/accessibility/pdf/text_1_renderer_orig.pdf b/test/accessibility/pdf/text_1_renderer_orig.pdf
deleted file mode 100644
index 67d39890c..000000000
--- a/test/accessibility/pdf/text_1_renderer_orig.pdf
+++ /dev/null
Binary files differ
diff --git a/test/accessibility/pdf/text_2_painter_orig.pdf b/test/accessibility/pdf/text_2.pdf
index 21ad6d0d8..19fff21a4 100644
--- a/test/accessibility/pdf/text_2_painter_orig.pdf
+++ b/test/accessibility/pdf/text_2.pdf
Binary files differ
diff --git a/test/accessibility/pdf/text_2_renderer_orig.pdf b/test/accessibility/pdf/text_2_renderer_orig.pdf
deleted file mode 100644
index 6a5956c66..000000000
--- a/test/accessibility/pdf/text_2_renderer_orig.pdf
+++ /dev/null
Binary files differ
diff --git a/test/accessibility/pdf/text_font-embedding_painter_orig.pdf b/test/accessibility/pdf/text_font-embedding.pdf
index d5c61c040..0288449d5 100644
--- a/test/accessibility/pdf/text_font-embedding_painter_orig.pdf
+++ b/test/accessibility/pdf/text_font-embedding.pdf
Binary files differ
diff --git a/test/accessibility/pdf/text_font-embedding_renderer_orig.pdf b/test/accessibility/pdf/text_font-embedding_renderer_orig.pdf
deleted file mode 100644
index f8669cb98..000000000
--- a/test/accessibility/pdf/text_font-embedding_renderer_orig.pdf
+++ /dev/null
Binary files differ
diff --git a/test/accessibility/role.fo b/test/accessibility/role.fo
index e284cde9c..ced8a4d44 100644
--- a/test/accessibility/role.fo
+++ b/test/accessibility/role.fo
@@ -16,14 +16,14 @@
limitations under the License.
-->
<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
<fo:layout-master-set>
<fo:simple-page-master master-name="page"
page-height="220pt" page-width="320pt" margin="10pt">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
- <fo:page-sequence master-reference="page" language="en" country="GB">
+ <fo:page-sequence master-reference="page">
<fo:flow flow-name="xsl-region-body" hyphenate="true" font-family="sans-serif">
<fo:block role="H1" font-weight="bold" font-size="150%"
space-before.minimum="1.5em"
diff --git a/test/accessibility/role_non-standard.fo b/test/accessibility/role_non-standard.fo
index b6641aa2b..d3e1a9852 100644
--- a/test/accessibility/role_non-standard.fo
+++ b/test/accessibility/role_non-standard.fo
@@ -16,14 +16,14 @@
limitations under the License.
-->
<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
<fo:layout-master-set>
<fo:simple-page-master master-name="page"
page-height="220pt" page-width="320pt" margin="10pt">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
- <fo:page-sequence master-reference="page" language="en" country="GB">
+ <fo:page-sequence master-reference="page">
<fo:flow flow-name="xsl-region-body" hyphenate="true" font-family="sans-serif">
<fo:block role="H1" font-weight="bold" font-size="150%"
space-before.minimum="1.5em"
diff --git a/test/accessibility/text_1.fo b/test/accessibility/text_1.fo
index 2a90f6c14..31ad31514 100644
--- a/test/accessibility/text_1.fo
+++ b/test/accessibility/text_1.fo
@@ -16,14 +16,14 @@
limitations under the License.
-->
<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
<fo:layout-master-set>
<fo:simple-page-master master-name="page"
page-height="220pt" page-width="320pt" margin="10pt">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
- <fo:page-sequence master-reference="page" language="en" country="GB">
+ <fo:page-sequence master-reference="page">
<fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
<fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
formatting objects (XSL-FO) and an output independent formatter. It is a Java application
diff --git a/test/accessibility/text_2.fo b/test/accessibility/text_2.fo
index 5eff059b6..f5693110e 100644
--- a/test/accessibility/text_2.fo
+++ b/test/accessibility/text_2.fo
@@ -16,14 +16,14 @@
limitations under the License.
-->
<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
<fo:layout-master-set>
<fo:simple-page-master master-name="page"
page-height="220pt" page-width="320pt" margin="10pt">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
- <fo:page-sequence master-reference="page" language="en" country="GB">
+ <fo:page-sequence master-reference="page">
<fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
<fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
formatting objects (XSL-FO) and an output independent formatter. It is a Java application
diff --git a/test/accessibility/text_font-embedding.fo b/test/accessibility/text_font-embedding.fo
index 1d3abe027..10c1c99d9 100644
--- a/test/accessibility/text_font-embedding.fo
+++ b/test/accessibility/text_font-embedding.fo
@@ -16,14 +16,14 @@
limitations under the License.
-->
<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
<fo:layout-master-set>
<fo:simple-page-master master-name="page"
page-height="220pt" page-width="320pt" margin="10pt">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
- <fo:page-sequence master-reference="page" language="en" country="GB">
+ <fo:page-sequence master-reference="page">
<fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify" font-family="DejaVu">
<fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
formatting objects (XSL-FO) and an output independent formatter. It is a Java application
diff --git a/test/java/org/apache/fop/StandardTestSuite.java b/test/java/org/apache/fop/StandardTestSuite.java
index bb59c8605..808542306 100644
--- a/test/java/org/apache/fop/StandardTestSuite.java
+++ b/test/java/org/apache/fop/StandardTestSuite.java
@@ -76,7 +76,8 @@ import org.apache.fop.pdf.PDFLibraryTestSuite;
MinOptMaxTestCase.class,
AdobeStandardEncodingTestCase.class,
AFMParserTestCase.class,
- FontEventProcessingTestCase.class
+ FontEventProcessingTestCase.class,
+ org.apache.fop.render.intermediate.IFStructureTreeBuilderTestCase.class
})
public class StandardTestSuite {
}
diff --git a/test/java/org/apache/fop/accessibility/fo/DOMResultUtil.java b/test/java/org/apache/fop/accessibility/fo/DOMResultUtil.java
new file mode 100644
index 000000000..5b4e264f2
--- /dev/null
+++ b/test/java/org/apache/fop/accessibility/fo/DOMResultUtil.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.accessibility.fo;
+
+import java.io.File;
+
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+/**
+ * Utility class to stream an instance of {@link DOMResult} into a file. May be
+ * useful for debugging.
+ */
+final class DOMResultUtil {
+
+ private DOMResultUtil() {
+ }
+
+ /**
+ * Streams the given result into a file of the given name.
+ *
+ * @param result the result of a transformation
+ * @param filename name of the file into which to stream the result
+ * @throws TransformerException if a problem occurs when streaming
+ */
+ public static void streamToFile(DOMResult result, String filename) throws TransformerException {
+ DOMSource source = new DOMSource(result.getNode());
+ TransformerFactory tFactory = TransformerFactory.newInstance();
+ Transformer transformer = tFactory.newTransformer();
+ transformer.transform(source, new StreamResult(new File(filename)));
+ }
+
+}
diff --git a/test/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverterTestCase.java b/test/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverterTestCase.java
new file mode 100644
index 000000000..9c53bdde3
--- /dev/null
+++ b/test/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverterTestCase.java
@@ -0,0 +1,223 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.accessibility.fo;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.custommonkey.xmlunit.Diff;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import org.apache.fop.accessibility.StructureTree2SAXEventAdapter;
+import org.apache.fop.accessibility.StructureTreeEventHandler;
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.fo.FODocumentParser;
+import org.apache.fop.fo.FODocumentParser.FOEventHandlerFactory;
+import org.apache.fop.fo.FOEventHandler;
+import org.apache.fop.fo.LoadingException;
+import org.apache.fop.fotreetest.DummyFOEventHandler;
+
+public class FO2StructureTreeConverterTestCase {
+
+ private interface FOLoader {
+
+ InputStream getFoInputStream();
+ }
+
+ private static final String STRUCTURE_TREE_SEQUENCE_NAME = "structure-tree-sequence";
+
+ private FOLoader foLoader;
+
+ @Test
+ public void testCompleteDocument() throws Exception {
+ foLoader = new FOLoader() {
+ public InputStream getFoInputStream() {
+ return getResource("/org/apache/fop/fo/complete_document.fo");
+ }
+ };
+ testConverter();
+ }
+
+ @Test
+ public void testTableFooters() throws Exception {
+ foLoader = new FOLoader() {
+ public InputStream getFoInputStream() {
+ return getResource("table-footers.fo");
+ }
+ };
+ testConverter();
+ }
+
+ @Test
+ public void testCompleteContentWrappedInTableFooter() throws Exception {
+ Source xslt = new StreamSource(getResource("wrapCompleteDocumentInTableFooter.xsl"));
+ Transformer transformer = createTransformer(xslt);
+ InputStream originalFO = getResource("/org/apache/fop/fo/complete_document.fo");
+ ByteArrayOutputStream transformedFoOutput = new ByteArrayOutputStream();
+ transformer.transform(new StreamSource(originalFO), new StreamResult(transformedFoOutput));
+ final byte[] transformedFoOutputBytes = transformedFoOutput.toByteArray();
+ foLoader = new FOLoader() {
+ public InputStream getFoInputStream() {
+ return new ByteArrayInputStream(transformedFoOutputBytes);
+ }
+ };
+ testConverter();
+ }
+
+ private Transformer createTransformer(Source xslt) throws TransformerFactoryConfigurationError,
+ TransformerConfigurationException {
+ TransformerFactory transformerFactory = TransformerFactory.newInstance();
+ return transformerFactory.newTransformer(xslt);
+ }
+
+ private static InputStream getResource(String name) {
+ return FO2StructureTreeConverterTestCase.class.getResourceAsStream(name);
+ }
+
+ private void testConverter() throws Exception {
+ DOMResult expectedStructureTree = loadExpectedStructureTree();
+ DOMResult actualStructureTree = buildActualStructureTree();
+ final Diff diff = createDiff(expectedStructureTree, actualStructureTree);
+ assertTrue(diff.toString(), diff.identical());
+ }
+
+ private DOMResult loadExpectedStructureTree() {
+ DOMResult expectedStructureTree = new DOMResult();
+ InputStream xslt = getResource("fo2StructureTree.xsl");
+ runXSLT(xslt, foLoader.getFoInputStream(), expectedStructureTree);
+ return expectedStructureTree;
+ }
+
+ private static void runXSLT(InputStream xslt, InputStream doc, Result result) {
+ Source fo = new StreamSource(doc);
+ try {
+ Transformer transformer = TransformerFactory.newInstance()
+ .newTransformer(new StreamSource(xslt));
+ transformer.transform(fo, result);
+ } catch (TransformerConfigurationException e) {
+ throw new RuntimeException(e);
+ } catch (TransformerException e) {
+ throw new RuntimeException(e);
+ } finally {
+ closeStream(xslt);
+ closeStream(doc);
+ }
+ }
+
+ private static void closeStream(InputStream stream) {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private DOMResult buildActualStructureTree() throws Exception {
+ DOMResult actualStructureTree = new DOMResult();
+ createStructureTreeFromDocument(foLoader.getFoInputStream(), actualStructureTree);
+ return actualStructureTree;
+ }
+
+ private static void createStructureTreeFromDocument(InputStream foInputStream,
+ Result result) throws Exception {
+ TransformerHandler tHandler = createTransformerHandler(result);
+ startStructureTreeSequence(tHandler);
+ StructureTreeEventHandler structureTreeEventHandler
+ = StructureTree2SAXEventAdapter.newInstance(tHandler);
+ FODocumentParser documentParser = createDocumentParser(structureTreeEventHandler);
+ FOUserAgent userAgent = createFOUserAgent(documentParser);
+ parseDocument(foInputStream, documentParser, userAgent);
+ endStructureTreeSequence(tHandler);
+ }
+
+ private static TransformerHandler createTransformerHandler(Result domResult)
+ throws TransformerConfigurationException, TransformerFactoryConfigurationError {
+ SAXTransformerFactory factory = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
+ TransformerHandler transformerHandler = factory.newTransformerHandler();
+ transformerHandler.setResult(domResult);
+ return transformerHandler;
+ }
+
+ private static void startStructureTreeSequence(TransformerHandler tHandler) throws SAXException {
+ tHandler.startDocument();
+ tHandler.startElement("", STRUCTURE_TREE_SEQUENCE_NAME, STRUCTURE_TREE_SEQUENCE_NAME,
+ new AttributesImpl());
+ }
+
+ private static FODocumentParser createDocumentParser(
+ final StructureTreeEventHandler structureTreeEventHandler) {
+ return FODocumentParser.newInstance(new FOEventHandlerFactory() {
+ public FOEventHandler newFOEventHandler(FOUserAgent foUserAgent) {
+ return new FO2StructureTreeConverter(structureTreeEventHandler,
+ new DummyFOEventHandler(foUserAgent));
+ }
+ });
+ }
+
+ private static FOUserAgent createFOUserAgent(FODocumentParser documentParser) {
+ FOUserAgent userAgent = documentParser.createFOUserAgent();
+ userAgent.setAccessibility(true);
+ return userAgent;
+ }
+
+ private static void parseDocument(InputStream foInputStream, FODocumentParser documentParser,
+ FOUserAgent userAgent) throws FOPException, LoadingException {
+ try {
+ documentParser.parse(foInputStream, userAgent);
+ } finally {
+ closeStream(foInputStream);
+ }
+ }
+
+ private static void endStructureTreeSequence(TransformerHandler tHandler) throws SAXException {
+ tHandler.endElement("", STRUCTURE_TREE_SEQUENCE_NAME, STRUCTURE_TREE_SEQUENCE_NAME);
+ tHandler.endDocument();
+ }
+
+ private static Diff createDiff(DOMResult expected, DOMResult actual) {
+ Diff diff = new Diff(getDocument(expected), getDocument(actual));
+ return diff;
+ }
+
+ private static Document getDocument(DOMResult result) {
+ return (Document) result.getNode();
+ }
+}
diff --git a/src/java/org/apache/fop/accessibility/reduceFOTree.xsl b/test/java/org/apache/fop/accessibility/fo/fo2StructureTree.xsl
index 0d93a2506..ce326f3b1 100644
--- a/src/java/org/apache/fop/accessibility/reduceFOTree.xsl
+++ b/test/java/org/apache/fop/accessibility/fo/fo2StructureTree.xsl
@@ -29,8 +29,24 @@
</xsl:copy>
</xsl:template>
+
+ <!-- Ignore fo:root -->
+ <xsl:template match="fo:root">
+ <structure-tree-sequence>
+ <xsl:apply-templates/>
+ </structure-tree-sequence>
+ </xsl:template>
+
+ <!-- fo:page-sequence maps to structure-tree -->
+ <xsl:template match="fo:page-sequence">
+ <structure-tree xmlns="http://xmlgraphics.apache.org/fop/intermediate">
+ <xsl:apply-templates/>
+ </structure-tree>
+ </xsl:template>
+
+
<!-- Declarations and Pagination and Layout Formatting Objects -->
- <xsl:template match="fo:root|fo:page-sequence|fo:static-content|fo:flow">
+ <xsl:template match="fo:static-content|fo:flow">
<xsl:call-template name="copy"/>
</xsl:template>
@@ -53,10 +69,18 @@
</xsl:template>
<!-- Formatting Objects for Tables -->
- <xsl:template match="fo:table-and-caption|fo:table-caption|fo:table">
+ <xsl:template match="fo:table-and-caption|fo:table-caption">
<xsl:call-template name="copy"/>
</xsl:template>
+ <xsl:template match="fo:table">
+ <xsl:copy>
+ <xsl:apply-templates select="@*"/>
+ <xsl:apply-templates select="*[name() != 'fo:table-footer']"/>
+ <xsl:apply-templates select="fo:table-footer"/>
+ </xsl:copy>
+ </xsl:template>
+
<xsl:template match="fo:table-header|fo:table-footer|fo:table-body|fo:table-row|fo:table-cell">
<xsl:call-template name="copy"/>
</xsl:template>
@@ -84,17 +108,28 @@
<!-- Discard descendants of fo:leader -->
<xsl:template match="fo:leader"/>
-
- <!-- Keep foi:ptr, fox:alt-text and role attributes, discard everything else -->
- <xsl:template match="@foi:ptr|@fox:alt-text|@role">
+
+ <!-- Keep fox:alt-text and role attributes, discard everything else -->
+ <xsl:template match="@fox:alt-text|@role">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="@*"/>
- <!-- Discard text -->
+ <!-- Discard text nodes... -->
<xsl:template match="text()"/>
+ <!-- ...except those that will result into marked content -->
+ <xsl:template match="fo:title/text()
+ |fo:block/text()
+ |fo:bidi-override/text()
+ |fo:inline/text()
+ |fo:basic-link/text()
+ |fo:wrapper/text()
+ |fo:marker/text()">
+ <marked-content xmlns="http://xmlgraphics.apache.org/fop/intermediate"/>
+ </xsl:template>
+
</xsl:stylesheet>
diff --git a/test/java/org/apache/fop/accessibility/fo/table-footers.fo b/test/java/org/apache/fop/accessibility/fo/table-footers.fo
new file mode 100644
index 000000000..6dcb9b68d
--- /dev/null
+++ b/test/java/org/apache/fop/accessibility/fo/table-footers.fo
@@ -0,0 +1,195 @@
+<?xml version="1.0" standalone="no"?>
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="440pt" page-width="420pt" margin="10pt">
+ <fo:region-body display-align="center"/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page">
+ <fo:flow flow-name="xsl-region-body" line-height="10pt" font-size="8pt">
+ <fo:table width="100% - 6pt" table-layout="fixed"
+ border-collapse="separate" border="2pt solid black" border-separation="2pt" padding="1pt"
+ start-indent="3pt" end-indent="3pt" space-after="2pt">
+ <fo:table-header start-indent="0" end-indent="0">
+ <fo:table-cell background-color="#E0E0E0" padding="2pt">
+ <fo:block>Start Outer Header</fo:block>
+ <fo:table width="100% - 6pt" table-layout="fixed"
+ border="2pt solid red" padding="1pt"
+ start-indent="3pt" end-indent="3pt" space-after="2pt">
+ <fo:table-header start-indent="0" end-indent="0">
+ <fo:table-cell background-color="#FFB0B0" padding="2pt">
+ <fo:block>Inner Header 1.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell background-color="#FFB0B0" padding="2pt">
+ <fo:block>Inner Header 1.2</fo:block>
+ </fo:table-cell>
+ </fo:table-header>
+ <fo:table-footer start-indent="0" end-indent="0">
+ <fo:table-cell background-color="#FFB0B0" padding="2pt">
+ <fo:block>Inner Footer 1.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell background-color="#FFB0B0" padding="2pt">
+ <fo:block>Inner Footer 1.2</fo:block>
+ </fo:table-cell>
+ </fo:table-footer>
+ <fo:table-body start-indent="0" end-indent="0">
+ <fo:table-row>
+ <fo:table-cell background-color="#FFB0B0" padding="2pt">
+ <fo:block>Inner Body 1.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell background-color="#FFB0B0" padding="2pt">
+ <fo:block>Inner Body 1.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ <fo:table-row>
+ <fo:table-cell background-color="#FFB0B0" padding="2pt">
+ <fo:block>Inner Body 2.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell background-color="#FFB0B0" padding="2pt">
+ <fo:block>Inner Body 2.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ <fo:block>End Outer Header</fo:block>
+ </fo:table-cell>
+ </fo:table-header>
+ <fo:table-footer start-indent="0" end-indent="0">
+ <fo:table-cell background-color="#E0E0E0" padding="2pt">
+ <fo:block>Start Outer Footer</fo:block>
+ <fo:table width="100% - 6pt" table-layout="fixed"
+ border="2pt solid green" padding="1pt"
+ start-indent="3pt" end-indent="3pt" space-after="2pt">
+ <fo:table-header start-indent="0" end-indent="0">
+ <fo:table-cell background-color="lightgreen" padding="2pt">
+ <fo:block>Inner Header 1.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell background-color="lightgreen" padding="2pt">
+ <fo:block>Inner Header 1.2</fo:block>
+ </fo:table-cell>
+ </fo:table-header>
+ <fo:table-footer start-indent="0" end-indent="0">
+ <fo:table-cell background-color="lightgreen" padding="2pt">
+ <fo:block>Start Inner Footer 1.1</fo:block>
+ <fo:table width="100% - 6pt" table-layout="fixed"
+ border="2pt solid yellow" padding="1pt"
+ start-indent="3pt" end-indent="3pt" space-after="2pt">
+ <fo:table-header start-indent="0" end-indent="0">
+ <fo:table-cell background-color="yellow" padding="2pt">
+ <fo:block>Inner Inner Header 1.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell background-color="yellow" padding="2pt">
+ <fo:block>Inner Inner Header 1.2</fo:block>
+ </fo:table-cell>
+ </fo:table-header>
+ <fo:table-footer start-indent="0" end-indent="0">
+ <fo:table-cell background-color="yellow" padding="2pt">
+ <fo:block>Inner Inner Footer 1.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell background-color="yellow" padding="2pt">
+ <fo:block>Inner Inner Footer 1.2</fo:block>
+ </fo:table-cell>
+ </fo:table-footer>
+ <fo:table-body start-indent="0" end-indent="0">
+ <fo:table-row>
+ <fo:table-cell background-color="yellow" padding="2pt">
+ <fo:block>Inner Inner Body 1.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell background-color="yellow" padding="2pt">
+ <fo:block>Inner Inner Body 1.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ <fo:table-row>
+ <fo:table-cell background-color="yellow" padding="2pt">
+ <fo:block>Inner Inner Body 2.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell background-color="yellow" padding="2pt">
+ <fo:block>Inner Inner Body 2.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ <fo:block>End Inner Footer 1.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell background-color="lightgreen" padding="2pt">
+ <fo:block>Inner Footer 1.2</fo:block>
+ </fo:table-cell>
+ </fo:table-footer>
+ <fo:table-body start-indent="0" end-indent="0">
+ <fo:table-row>
+ <fo:table-cell background-color="lightgreen" padding="2pt">
+ <fo:block>Inner Body 1.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell background-color="lightgreen" padding="2pt">
+ <fo:block>Inner Body 1.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ <fo:table-row>
+ <fo:table-cell background-color="lightgreen" padding="2pt">
+ <fo:block>Inner Body 2.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell background-color="lightgreen" padding="2pt">
+ <fo:block>Inner Body 2.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ <fo:block>End Outer Footer</fo:block>
+ </fo:table-cell>
+ </fo:table-footer>
+ <fo:table-body start-indent="0" end-indent="0">
+ <fo:table-row>
+ <fo:table-cell background-color="#E0E0E0" padding="2pt">
+ <fo:block>Outer Body Cell 1</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ <fo:table-row>
+ <fo:table-cell background-color="#E0E0E0" padding="2pt">
+ <fo:block>Start Outer Body Cell 2</fo:block>
+ <fo:table width="100% - 6pt" table-layout="fixed"
+ border="2pt solid blue" padding="1pt"
+ start-indent="3pt" end-indent="3pt" space-after="2pt">
+ <fo:table-header start-indent="0" end-indent="0">
+ <fo:table-cell background-color="lightblue" padding="2pt">
+ <fo:block>Inner Footer 1.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell background-color="lightblue" padding="2pt">
+ <fo:block>Inner Footer 1.2</fo:block>
+ </fo:table-cell>
+ </fo:table-header>
+ <fo:table-footer start-indent="0" end-indent="0">
+ <fo:table-cell background-color="lightblue" padding="2pt">
+ <fo:block>Inner Header 1.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell background-color="lightblue" padding="2pt">
+ <fo:block>Inner Header 1.2</fo:block>
+ </fo:table-cell>
+ </fo:table-footer>
+ <fo:table-body start-indent="0" end-indent="0">
+ <fo:table-row>
+ <fo:table-cell background-color="lightblue" padding="2pt">
+ <fo:block>Inner Body 1.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell background-color="lightblue" padding="2pt">
+ <fo:block>Inner Body 1.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ <fo:table-row>
+ <fo:table-cell background-color="lightblue" padding="2pt">
+ <fo:block>Inner Body 2.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell background-color="lightblue" padding="2pt">
+ <fo:block>Inner Body 2.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ <fo:block>End Outer Body Cell 2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ </fo:flow>
+ </fo:page-sequence>
+</fo:root>
diff --git a/test/java/org/apache/fop/accessibility/fo/wrapCompleteDocumentInTableFooter.xsl b/test/java/org/apache/fop/accessibility/fo/wrapCompleteDocumentInTableFooter.xsl
new file mode 100644
index 000000000..9608b2fb9
--- /dev/null
+++ b/test/java/org/apache/fop/accessibility/fo/wrapCompleteDocumentInTableFooter.xsl
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:fo="http://www.w3.org/1999/XSL/Format">
+
+ <xsl:template match="@*|node()" name="copy">
+ <xsl:copy>
+ <xsl:apply-templates select="@*|node()"/>
+ </xsl:copy>
+ </xsl:template>
+
+
+ <xsl:template match="/">
+ <fo:root>
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="500pt" page-width="300pt" margin="20pt">
+ <fo:region-body margin-top="20pt"/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <xsl:apply-templates select="//fo:page-sequence"/>
+ </fo:root>
+ </xsl:template>
+
+ <xsl:template match="fo:page-sequence">
+ <fo:page-sequence master-reference="page">
+ <xsl:apply-templates select="fo:flow"/>
+ </fo:page-sequence>
+ </xsl:template>
+
+ <xsl:template match="fo:flow">
+ <xsl:copy>
+ <xsl:apply-templates select="@*[not(starts-with(name(), 'space-before'))]"/>
+ <fo:table width="100%" table-layout="fixed">
+ <fo:table-footer>
+ <fo:table-cell background-color="#F0F0F0">
+ <xsl:apply-templates select="@*[starts-with(name(), 'space-before')]"/>
+ <xsl:apply-templates select="*"/>
+ </fo:table-cell>
+ </fo:table-footer>
+ <fo:table-body>
+ <fo:table-cell>
+ <fo:block>The content below is in the table footer.</fo:block>
+ </fo:table-cell>
+ </fo:table-body>
+ </fo:table>
+ </xsl:copy>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/test/java/org/apache/fop/fo/DelegatingFOEventHandlerTestCase.java b/test/java/org/apache/fop/fo/DelegatingFOEventHandlerTestCase.java
new file mode 100644
index 000000000..313379e02
--- /dev/null
+++ b/test/java/org/apache/fop/fo/DelegatingFOEventHandlerTestCase.java
@@ -0,0 +1,531 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.fo;
+
+import static org.junit.Assert.assertArrayEquals;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.fo.FODocumentParser.FOEventHandlerFactory;
+import org.apache.fop.fo.flow.BasicLink;
+import org.apache.fop.fo.flow.Block;
+import org.apache.fop.fo.flow.BlockContainer;
+import org.apache.fop.fo.flow.Character;
+import org.apache.fop.fo.flow.ExternalGraphic;
+import org.apache.fop.fo.flow.Footnote;
+import org.apache.fop.fo.flow.FootnoteBody;
+import org.apache.fop.fo.flow.Inline;
+import org.apache.fop.fo.flow.InstreamForeignObject;
+import org.apache.fop.fo.flow.Leader;
+import org.apache.fop.fo.flow.ListBlock;
+import org.apache.fop.fo.flow.ListItem;
+import org.apache.fop.fo.flow.ListItemBody;
+import org.apache.fop.fo.flow.ListItemLabel;
+import org.apache.fop.fo.flow.PageNumber;
+import org.apache.fop.fo.flow.PageNumberCitation;
+import org.apache.fop.fo.flow.PageNumberCitationLast;
+import org.apache.fop.fo.flow.Wrapper;
+import org.apache.fop.fo.flow.table.Table;
+import org.apache.fop.fo.flow.table.TableBody;
+import org.apache.fop.fo.flow.table.TableCell;
+import org.apache.fop.fo.flow.table.TableColumn;
+import org.apache.fop.fo.flow.table.TableFooter;
+import org.apache.fop.fo.flow.table.TableHeader;
+import org.apache.fop.fo.flow.table.TableRow;
+import org.apache.fop.fo.pagination.Flow;
+import org.apache.fop.fo.pagination.PageSequence;
+import org.apache.fop.fo.pagination.Root;
+import org.apache.fop.fo.pagination.StaticContent;
+
+/**
+ * Tests that {@link DelegatingFOEventHandler} does forward every event to its delegate
+ * event handler.
+ */
+public class DelegatingFOEventHandlerTestCase {
+
+ private InputStream document;
+
+ private List<String> expectedEvents;
+
+ private List<String> actualEvents;
+
+ private FODocumentParser documentParser;
+
+ private class DelegatingFOEventHandlerTester extends FOEventHandler {
+
+ DelegatingFOEventHandlerTester(FOUserAgent foUserAgent) {
+ super(foUserAgent);
+ }
+
+ private final StringBuilder eventBuilder = new StringBuilder();
+
+ @Override
+ public void startDocument() throws SAXException {
+ actualEvents.add("start document");
+ }
+
+ @Override
+ public void endDocument() throws SAXException {
+ actualEvents.add("end document");
+ }
+
+ @Override
+ public void startRoot(Root root) {
+ startElement(root);
+ }
+
+ @Override
+ public void endRoot(Root root) {
+ endElement(root);
+ }
+
+ @Override
+ public void startPageSequence(PageSequence pageSeq) {
+ startElement(pageSeq);
+ }
+
+ @Override
+ public void endPageSequence(PageSequence pageSeq) {
+ endElement(pageSeq);
+ }
+
+ @Override
+ public void startPageNumber(PageNumber pagenum) {
+ startElement(pagenum);
+ }
+
+ @Override
+ public void endPageNumber(PageNumber pagenum) {
+ endElement(pagenum);
+ }
+
+ @Override
+ public void startPageNumberCitation(PageNumberCitation pageCite) {
+ startElement(pageCite);
+ }
+
+ @Override
+ public void endPageNumberCitation(PageNumberCitation pageCite) {
+ endElement(pageCite);
+ }
+
+ @Override
+ public void startPageNumberCitationLast(PageNumberCitationLast pageLast) {
+ startElement(pageLast);
+ }
+
+ @Override
+ public void endPageNumberCitationLast(PageNumberCitationLast pageLast) {
+ endElement(pageLast);
+ }
+
+ @Override
+ public void startFlow(Flow fl) {
+ startElement(fl);
+ }
+
+ @Override
+ public void endFlow(Flow fl) {
+ endElement(fl);
+ }
+
+ @Override
+ public void startBlock(Block bl) {
+ startElement(bl);
+ }
+
+ @Override
+ public void endBlock(Block bl) {
+ endElement(bl);
+ }
+
+ @Override
+ public void startBlockContainer(BlockContainer blc) {
+ startElement(blc);
+ }
+
+ @Override
+ public void endBlockContainer(BlockContainer blc) {
+ endElement(blc);
+ }
+
+ @Override
+ public void startInline(Inline inl) {
+ startElement(inl);
+ }
+
+ @Override
+ public void endInline(Inline inl) {
+ endElement(inl);
+ }
+
+ @Override
+ public void startTable(Table tbl) {
+ startElement(tbl);
+ }
+
+ @Override
+ public void endTable(Table tbl) {
+ endElement(tbl);
+ }
+
+ @Override
+ public void startColumn(TableColumn tc) {
+ startElement(tc);
+ }
+
+ @Override
+ public void endColumn(TableColumn tc) {
+ endElement(tc);
+ }
+
+ @Override
+ public void startHeader(TableHeader header) {
+ startElement(header);
+ }
+
+ @Override
+ public void endHeader(TableHeader header) {
+ endElement(header);
+ }
+
+ @Override
+ public void startFooter(TableFooter footer) {
+ startElement(footer);
+ }
+
+ @Override
+ public void endFooter(TableFooter footer) {
+ endElement(footer);
+ }
+
+ @Override
+ public void startBody(TableBody body) {
+ startElement(body);
+ }
+
+ @Override
+ public void endBody(TableBody body) {
+ endElement(body);
+ }
+
+ @Override
+ public void startRow(TableRow tr) {
+ startElement(tr);
+ }
+
+ @Override
+ public void endRow(TableRow tr) {
+ endElement(tr);
+ }
+
+ @Override
+ public void startCell(TableCell tc) {
+ startElement(tc);
+ }
+
+ @Override
+ public void endCell(TableCell tc) {
+ endElement(tc);
+ }
+
+ @Override
+ public void startList(ListBlock lb) {
+ startElement(lb);
+ }
+
+ @Override
+ public void endList(ListBlock lb) {
+ endElement(lb);
+ }
+
+ @Override
+ public void startListItem(ListItem li) {
+ startElement(li);
+ }
+
+ @Override
+ public void endListItem(ListItem li) {
+ endElement(li);
+ }
+
+ @Override
+ public void startListLabel(ListItemLabel listItemLabel) {
+ startElement(listItemLabel);
+ }
+
+ @Override
+ public void endListLabel(ListItemLabel listItemLabel) {
+ endElement(listItemLabel);
+ }
+
+ @Override
+ public void startListBody(ListItemBody listItemBody) {
+ startElement(listItemBody);
+ }
+
+ @Override
+ public void endListBody(ListItemBody listItemBody) {
+ endElement(listItemBody);
+ }
+
+ @Override
+ public void startStatic(StaticContent staticContent) {
+ startElement(staticContent);
+ }
+
+ @Override
+ public void endStatic(StaticContent statisContent) {
+ endElement(statisContent);
+ }
+
+ @Override
+ public void startLink(BasicLink basicLink) {
+ startElement(basicLink);
+ }
+
+ @Override
+ public void endLink(BasicLink basicLink) {
+ endElement(basicLink);
+ }
+
+ @Override
+ public void image(ExternalGraphic eg) {
+ startElement(eg);
+ endElement(eg);
+ }
+
+ @Override
+ public void startInstreamForeignObject(InstreamForeignObject ifo) {
+ startElement(ifo);
+ }
+
+ @Override
+ public void endInstreamForeignObject(InstreamForeignObject ifo) {
+ endElement(ifo);
+ }
+
+ @Override
+ public void startFootnote(Footnote footnote) {
+ startElement(footnote);
+ }
+
+ @Override
+ public void endFootnote(Footnote footnote) {
+ endElement(footnote);
+ }
+
+ @Override
+ public void startFootnoteBody(FootnoteBody body) {
+ startElement(body);
+ }
+
+ @Override
+ public void endFootnoteBody(FootnoteBody body) {
+ endElement(body);
+ }
+
+ @Override
+ public void startLeader(Leader l) {
+ startElement(l);
+ }
+
+ @Override
+ public void endLeader(Leader l) {
+ endElement(l);
+ }
+
+ @Override
+ public void startWrapper(Wrapper wrapper) {
+ startElement(wrapper);
+ }
+
+ @Override
+ public void endWrapper(Wrapper wrapper) {
+ endElement(wrapper);
+ }
+
+ @Override
+ public void character(Character c) {
+ startElement(c);
+ endElement(c);
+ }
+
+ private void startElement(FObj node) {
+ addEvent("start ", node);
+ }
+
+ private void endElement(FObj node) {
+ addEvent("end ", node);
+ }
+
+ private void addEvent(String event, FObj node) {
+ eventBuilder.append(event);
+ eventBuilder.append(node.getLocalName());
+ addID(node);
+ actualEvents.add(eventBuilder.toString());
+ eventBuilder.setLength(0);
+ }
+
+ private void addID(FObj node) {
+ String id = node.getId();
+ if (id != null && id.length() > 0) {
+ eventBuilder.append(" id=\"");
+ eventBuilder.append(id);
+ eventBuilder.append("\"");
+ }
+ }
+ }
+
+ @Before
+ public void setUp() throws IOException {
+ setUpEvents();
+ loadDocument();
+ createDocumentParser();
+ }
+
+ private void setUpEvents() throws IOException {
+ loadDocument();
+ loadExpectedEvents();
+ actualEvents = new ArrayList<String>(expectedEvents.size());
+ }
+
+ private void loadDocument() {
+ document = getClass().getResourceAsStream("complete_document.fo");
+ }
+
+ private void loadExpectedEvents() throws IOException {
+ expectedEvents = new ArrayList<String>();
+ InputStream xslt = getClass().getResourceAsStream("extract-events.xsl");
+ try {
+ runXSLT(xslt);
+ } finally {
+ closeStream(xslt);
+ closeStream(document);
+ }
+ }
+
+ private void runXSLT(InputStream xslt) {
+ Transformer transformer = createTransformer(xslt);
+ Source fo = new StreamSource(document);
+ Result result = createTransformOutputHandler();
+ try {
+ transformer.transform(fo, result);
+ } catch (TransformerException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private Transformer createTransformer(InputStream xslt) {
+ TransformerFactory transformerFactory = TransformerFactory.newInstance();
+ try {
+ return transformerFactory.newTransformer(new StreamSource(xslt));
+ } catch (TransformerConfigurationException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private Result createTransformOutputHandler() {
+ return new SAXResult(new DefaultHandler() {
+
+ private final StringBuilder event = new StringBuilder();
+
+ @Override
+ public void startElement(String uri, String localName, String qName,
+ Attributes attributes) throws SAXException {
+ event.setLength(0);
+ }
+
+ @Override
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ event.append(ch, start, length);
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ expectedEvents.add(event.toString());
+ }
+
+ });
+ }
+
+ private void closeStream(InputStream stream) {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void createDocumentParser() {
+ documentParser = FODocumentParser.newInstance(new FOEventHandlerFactory() {
+
+ public FOEventHandler newFOEventHandler(FOUserAgent foUserAgent) {
+ return new DelegatingFOEventHandler(
+ new DelegatingFOEventHandlerTester(foUserAgent)) {
+ };
+ }
+ });
+ }
+
+ @Test
+ public void testFOEventHandler() throws Exception {
+ documentParser.parse(document);
+ assertArrayEquals(expectedEvents.toArray(), actualEvents.toArray());
+ }
+
+ @After
+ public void unloadDocument() throws IOException {
+ document.close();
+ }
+
+ /**
+ * Prints the given list to {@code System.out}, each element on a new line. For
+ * debugging purpose.
+ *
+ * @param list a list
+ */
+ public void printList(List<?> list) {
+ for (Object element : list) {
+ System.out.println(element);
+ }
+ }
+
+}
diff --git a/test/java/org/apache/fop/fo/FODocumentParser.java b/test/java/org/apache/fop/fo/FODocumentParser.java
new file mode 100644
index 000000000..a7574e49d
--- /dev/null
+++ b/test/java/org/apache/fop/fo/FODocumentParser.java
@@ -0,0 +1,161 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.fo;
+
+import java.io.InputStream;
+
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.apps.Fop;
+import org.apache.fop.apps.FopFactory;
+import org.apache.fop.events.EventListener;
+
+/**
+ * Parse an FO document and run the corresponding FO events through a given
+ * {@link FOEventHandler} instance. That instance is created using the helper
+ * {@link FOEventHandlerFactory}.
+ *
+ * <p>An instance of this class may not be used in multiple threads concurrently.<p>
+ *
+ * <p>An instance of this class may be used multiple times if the given
+ * {@link FOEventHandler} implementation can be used multiple times.
+ */
+public final class FODocumentParser {
+
+ private static final TransformerFactory TRANSFORMER_FACTORY = TransformerFactory.newInstance();
+
+ private static final FopFactory FOP_FACTORY = FopFactory.newInstance();
+
+ private final FOEventHandlerFactory foEventHandlerFactory;
+
+ private Fop fop;
+
+ private Transformer transformer;
+
+ private EventListener eventListener;
+
+ /**
+ * A factory to create custom instances of {@link FOEventHandler}.
+ */
+ public static interface FOEventHandlerFactory {
+
+ /**
+ * Creates a new {@code FOEventHandler} instance parameterized with the given FO user agent.
+ *
+ * @param foUserAgent an FO user agent
+ * @return a new {@code FOEventHandler} instance
+ */
+ FOEventHandler newFOEventHandler(FOUserAgent foUserAgent);
+ }
+
+ private FODocumentParser(FOEventHandlerFactory foeEventHandlerFactory) {
+ this.foEventHandlerFactory = foeEventHandlerFactory;
+ }
+
+ /**
+ * Creates and returns a new FO document parser. The given factory will be used to
+ * customize the handler that will receive FO events, using the
+ * {@link FOUserAgent#setFOEventHandlerOverride(FOEventHandler)} method.
+ *
+ * @param foEventHandlerFactory the factory to be used to create {@code
+ * FOEventHandler} instances
+ * @return a new parser
+ */
+ public static FODocumentParser newInstance(FOEventHandlerFactory foEventHandlerFactory) {
+ return new FODocumentParser(foEventHandlerFactory);
+ }
+
+ /**
+ * Sets the event listener to be used if events occurs when parsing the document.
+ *
+ * @param eventListener an event listener
+ */
+ public void setEventListener(EventListener eventListener) {
+ this.eventListener = eventListener;
+ }
+
+ /**
+ * Runs FOP on the given document.
+ *
+ * @param document XSL-FO document to parse
+ * @throws FOPException if an error occurs when initializing FOP
+ * @throws LoadingException if an error occurs when parsing the document
+ */
+ public void parse(InputStream document) throws FOPException, LoadingException {
+ parse(document, createFOUserAgent());
+ }
+
+ /**
+ * Runs FOP on the given document with the supplied {@link FOUserAgent}.
+ *
+ * @param document XSL-FO document to parse
+ * @param foUserAgent The user agent
+ * @throws FOPException if an error occurs when initializing FOP
+ * @throws LoadingException if an error occurs when parsing the document
+ */
+ public void parse(InputStream document, FOUserAgent foUserAgent)
+ throws FOPException, LoadingException {
+ fop = FOP_FACTORY.newFop(foUserAgent);
+ createTransformer();
+ runTransformer(document);
+ }
+
+ /**
+ * Creates a new {@link FOUserAgent}.
+ * @return It
+ */
+ public FOUserAgent createFOUserAgent() {
+ FOUserAgent userAgent = FOP_FACTORY.newFOUserAgent();
+ FOEventHandler foEventHandler = foEventHandlerFactory.newFOEventHandler(userAgent);
+ userAgent.setFOEventHandlerOverride(foEventHandler);
+ if (eventListener != null) {
+ userAgent.getEventBroadcaster().addEventListener(eventListener);
+ }
+ return userAgent;
+ }
+
+ private void createTransformer() {
+ try {
+ transformer = TRANSFORMER_FACTORY.newTransformer();
+ } catch (TransformerConfigurationException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void runTransformer(InputStream input) throws LoadingException, FOPException {
+ Source source = new StreamSource(input);
+ Result result = new SAXResult(fop.getDefaultHandler());
+ try {
+ transformer.transform(source, result);
+ } catch (TransformerException e) {
+ Throwable cause = e.getCause();
+ throw new LoadingException(cause == null ? e : cause);
+ }
+ }
+}
diff --git a/test/java/org/apache/fop/fo/FONodeMocks.java b/test/java/org/apache/fop/fo/FONodeMocks.java
new file mode 100644
index 000000000..1310d4a78
--- /dev/null
+++ b/test/java/org/apache/fop/fo/FONodeMocks.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.fo;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+
+import org.apache.xmlgraphics.image.loader.ImageException;
+import org.apache.xmlgraphics.image.loader.ImageManager;
+import org.apache.xmlgraphics.image.loader.ImageSessionContext;
+
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.apps.FopFactory;
+
+/**
+ * A helper class for creating mocks of {@link FONode} and its descendants.
+ */
+public final class FONodeMocks {
+
+ private FONodeMocks() { }
+
+ /**
+ * Creates and returns a mock {@link FONode} configured with a mock
+ * {@link FOEventHandler}. The FO event handler returns a mock {@link FOUserAgent},
+ * which in turn returns a mock {@link FopFactory}, which returns a mock
+ * {@link ImageManager}.
+ *
+ * @return a mock FO node
+ */
+ public static FONode mockFONode() {
+ FONode mockFONode = mock(FONode.class);
+ mockGetFOEventHandler(mockFONode);
+ return mockFONode;
+ }
+
+ private static void mockGetFOEventHandler(FONode mockFONode) {
+ FOEventHandler mockFOEventHandler = mock(FOEventHandler.class);
+ mockGetUserAgent(mockFOEventHandler);
+ when(mockFONode.getFOEventHandler()).thenReturn(mockFOEventHandler);
+ }
+
+ private static void mockGetUserAgent(FOEventHandler mockFOEventHandler) {
+ FOUserAgent mockFOUserAgent = mock(FOUserAgent.class);
+ mockGetFactory(mockFOUserAgent);
+ when(mockFOEventHandler.getUserAgent()).thenReturn(mockFOUserAgent);
+ }
+
+ private static void mockGetFactory(FOUserAgent mockFOUserAgent) {
+ FopFactory mockFopFactory = mock(FopFactory.class);
+ mockGetImageManager(mockFopFactory);
+ when(mockFOUserAgent.getFactory()).thenReturn(mockFopFactory);
+ }
+
+ private static void mockGetImageManager(FopFactory mockFopFactory) {
+ try {
+ ImageManager mockImageManager = mock(ImageManager.class);
+ when(mockImageManager.getImageInfo(anyString(), any(ImageSessionContext.class)))
+ .thenReturn(null);
+ when(mockFopFactory.getImageManager()).thenReturn(mockImageManager);
+ } catch (ImageException e) {
+ throw new RuntimeException(e);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/test/java/org/apache/fop/fo/LoadingException.java b/test/java/org/apache/fop/fo/LoadingException.java
new file mode 100644
index 000000000..a5d509209
--- /dev/null
+++ b/test/java/org/apache/fop/fo/LoadingException.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.fo;
+
+/**
+ * This class specifies an exceptional condition that occurred while an XSL-FO document
+ * was being parsed.
+ */
+public class LoadingException extends Exception {
+
+ private static final long serialVersionUID = 7529029475875542916L;
+
+ LoadingException(Throwable cause) {
+ super(cause);
+ }
+
+}
diff --git a/test/java/org/apache/fop/fo/complete_document.fo b/test/java/org/apache/fop/fo/complete_document.fo
new file mode 100644
index 000000000..5a34e9e9a
--- /dev/null
+++ b/test/java/org/apache/fop/fo/complete_document.fo
@@ -0,0 +1,176 @@
+<?xml version="1.0" standalone="no"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
+ xmlns:fox="http://xmlgraphics.apache.org/fop/extensions">
+
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="400pt" page-width="300pt" margin="20pt" margin-top="10pt">
+ <fo:region-body margin-top="20pt"/>
+ <fo:region-before extent="15pt"/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+
+ <fo:page-sequence master-reference="page">
+ <fo:static-content flow-name="xsl-region-before">
+ <fo:block id="1" font-size="7pt" text-align-last="justify" padding-bottom="2pt"
+ border-bottom="0.25pt solid black">This is the page header<fo:leader/>Page <fo:page-number
+ id="2"/></fo:block>
+ </fo:static-content>
+ <fo:static-content flow-name="xsl-footnote-separator">
+ <fo:block id="3"><fo:leader leader-length="100pt" leader-pattern="rule"/></fo:block>
+ </fo:static-content>
+ <fo:flow flow-name="xsl-region-body">
+ <fo:block id="4">This is a link to the <fo:wrapper id="5" color="blue"><fo:basic-link id="6"
+ internal-destination="second-start">next page-sequence</fo:basic-link></fo:wrapper>
+ (which starts on page <fo:page-number-citation id="7" ref-id="second-start"/> and ends on
+ page <fo:page-number-citation-last id="8" ref-id="second-end"/>).</fo:block>
+ <fo:block id="9" font-family="sans-serif" font-weight="bold" space-before="1em"
+ space-after="0.2em" role="H1"><fo:block id="10">A Title Block</fo:block></fo:block>
+ <fo:block id="11">This block of text contains a footnote<fo:footnote id="12"><fo:inline id="13"
+ baseline-shift="super" font-size="70%">1</fo:inline><fo:footnote-body id="14"><fo:block
+ id="15">A footnote with a link to the <fo:wrapper id="16" color="blue"><fo:basic-link
+ id="17" external-destination="http://xmlgraphics.apache.org/fop/">FOP
+ website</fo:basic-link></fo:wrapper></fo:block></fo:footnote-body></fo:footnote>
+ call.</fo:block>
+ <fo:table id="18" space-before="1em" width="100%" table-layout="fixed">
+ <fo:table-column id="19" column-width="proportional-column-width(1)"/>
+ <fo:table-column id="20" column-width="proportional-column-width(2)"/>
+ <fo:table-header id="21">
+ <fo:table-row id="22">
+ <fo:table-cell id="23" border="2pt solid black" padding="2pt 2pt 0">
+ <fo:block id="24">Header 1.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell id="25" border="2pt solid black" padding="2pt 2pt 0">
+ <fo:block id="26">Header 1.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-header>
+ <fo:table-footer id="27">
+ <fo:table-row id="28">
+ <fo:table-cell id="29" border="2pt solid black" padding="2pt 2pt 0">
+ <fo:block id="30">Footer 1.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell id="31" border="2pt solid black" padding="2pt 2pt 0">
+ <fo:block id="32">Footer 1.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-footer>
+ <fo:table-body id="33">
+ <fo:table-row id="34">
+ <fo:table-cell id="35" border="1pt solid black" padding="2pt 2pt 0">
+ <fo:block id="36">Cell 1.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell id="37" border="1pt solid black" padding="2pt 2pt 0">
+ <fo:block id="38">Cell 1.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ <fo:table-row id="39">
+ <fo:table-cell id="40" border="1pt solid black" padding="2pt 2pt 0">
+ <fo:block id="41">Cell 2.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell id="42" border="1pt solid black" padding="2pt 2pt 0">
+ <fo:block id="43">Cell 2.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ <fo:block-container id="44" space-before="1.2em">
+ <fo:block-container id="45" absolute-position="absolute" top="6pt" right="2.5pt"
+ inline-progression-dimension="37%" padding="3pt 1pt 2pt 3pt" border="1.5pt solid
+ darkblue">
+ <fo:block id="46" color="darkblue" font-size="80%">This is an absolutely positioned
+ block-container. Nullam interdum mattis ipsum sit amet molestie.</fo:block>
+ </fo:block-container>
+ <fo:block id="47" end-indent="37% + 15pt">Lorem ipsum dolor sit amet, consectetur adipiscing
+ elit. Integer vel lacinia diam. Etiam venenatis magna vel libero imperdiet
+ rhoncus.</fo:block>
+ </fo:block-container>
+ </fo:flow>
+ </fo:page-sequence>
+
+ <fo:page-sequence master-reference="page">
+ <fo:static-content id="48" flow-name="xsl-region-before">
+ <fo:block id="49" font-size="7pt" text-align-last="justify" padding-bottom="2pt"
+ border-bottom="0.25pt solid black">This is the page header<fo:leader id="50"/>Page
+ <fo:page-number id="51"/></fo:block>
+ </fo:static-content>
+ <fo:flow flow-name="xsl-region-body" text-align="justify" space-before.minimum="8pt"
+ space-before.optimum="10pt" space-before.maximum="12pt">
+ <fo:block id="second-start">Starting a new page-sequence.</fo:block>
+ <fo:block id="52" text-align="center">The <fo:external-graphic id="53"
+ src="test/resources/images/fop-logo-color-24bit.png"
+ inline-progression-dimension.maximum="50%" content-width="scale-to-fit"
+ alignment-adjust="-46%" alignment-baseline="middle" fox:alt-text="FOP Logo"/>
+ logo.</fo:block>
+ <fo:list-block id="54" provisional-distance-between-starts="15pt"
+ provisional-label-separation="0" space-before="inherit">
+ <fo:list-item id="55">
+ <fo:list-item-label id="56" end-indent="label-end()">
+ <fo:block id="57">1.</fo:block>
+ </fo:list-item-label>
+ <fo:list-item-body id="58" start-indent="body-start()">
+ <fo:block id="59">First item of a list</fo:block>
+ </fo:list-item-body>
+ </fo:list-item>
+ <fo:list-item id="60">
+ <fo:list-item-label id="61" end-indent="label-end()">
+ <fo:block id="62">2.</fo:block>
+ </fo:list-item-label>
+ <fo:list-item-body id="63" start-indent="body-start()">
+ <fo:block id="64">Second item of a list</fo:block>
+ </fo:list-item-body>
+ </fo:list-item>
+ <fo:list-item id="65">
+ <fo:list-item-label id="66" end-indent="label-end()">
+ <fo:block id="67">3.</fo:block>
+ </fo:list-item-label>
+ <fo:list-item-body id="68" start-indent="body-start()">
+ <fo:block id="69">Third item of a list</fo:block>
+ </fo:list-item-body>
+ </fo:list-item>
+ </fo:list-block>
+ <fo:block id="70" text-align="center"><fo:instream-foreign-object id="71"
+ inline-progression-dimension.maximum="50%" content-width="scale-to-fit"
+ fox:alt-text="An inline SVG">
+ <svg xmlns="http://www.w3.org/2000/svg" width="319" height="286.6">
+ <g style="fill-opacity:0.7; stroke:black; stroke-width:3"
+ transform="translate(0, 286.6) scale(1, -1) translate(100, 100)">
+ <circle cx="50" cy="86.6" r="80" style="fill:red;"/>
+ <circle cx="0" cy="0" r="80" style="fill:green;"/>
+ <circle cx="100" cy="0" r="80" style="fill:blue;"/>
+ </g>
+ </svg>
+ </fo:instream-foreign-object></fo:block>
+ <fo:block id="72" space-before="inherit">A block containing an <fo:inline id="73"
+ border="0.5pt solid black" padding="2pt" padding-bottom="0">inline</fo:inline>
+ element.</fo:block>
+ <fo:block id="74" space-before="inherit">A block containing a fancy <fo:character id="75"
+ border="1pt solid black" padding="0 2pt 1pt 2pt" font-family="Symbol" character="♦"/>
+ character.</fo:block>
+ <fo:block id="76" space-before="inherit" text-align-last="justify">A leader with special
+ content: <fo:leader id="77" leader-pattern="use-content"><fo:inline id="78"><fo:character
+ id="79" character=" "/><fo:inline id="80" border="0.5pt solid black"
+ padding-left="2pt" padding-right="2pt"><fo:character id="81" baseline-shift="-10%"
+ character="•"/></fo:inline></fo:inline></fo:leader>.</fo:block>
+ <fo:block id="second-end" space-before="inherit">Ending the page-sequence.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+
+</fo:root>
diff --git a/test/java/org/apache/fop/fo/extract-events.xsl b/test/java/org/apache/fop/fo/extract-events.xsl
new file mode 100644
index 000000000..6cf42c984
--- /dev/null
+++ b/test/java/org/apache/fop/fo/extract-events.xsl
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:fo="http://www.w3.org/1999/XSL/Format"
+ exclude-result-prefixes="fo">
+
+ <xsl:output indent="yes" omit-xml-declaration="yes"/>
+
+ <xsl:template match="/">
+ <event>
+ <xsl:text>start document</xsl:text>
+ </event>
+ <xsl:apply-templates/>
+ <event>
+ <xsl:text>end document</xsl:text>
+ </event>
+ </xsl:template>
+
+ <xsl:template match="fo:root">
+ <event>start root</event>
+ <xsl:apply-templates select="fo:page-sequence"/>
+ <event>end root</event>
+ </xsl:template>
+
+ <xsl:template match="fo:*">
+ <xsl:call-template name="process.node">
+ <xsl:with-param name="id">
+ <xsl:apply-templates select="@id"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:template>
+
+ <!-- Those elements do not retrieve the id property.
+ This will have to be fixed at some point. -->
+ <xsl:template match="fo:footnote|fo:footnote-body">
+ <xsl:call-template name="process.node"/>
+ </xsl:template>
+
+ <xsl:template name="process.node">
+ <xsl:param name="id" select="''"/>
+ <event>
+ <xsl:text>start </xsl:text>
+ <xsl:value-of select="local-name()"/>
+ <xsl:value-of select="$id"/>
+ </event>
+ <xsl:apply-templates/>
+ <event>
+ <xsl:text>end </xsl:text>
+ <xsl:value-of select="local-name()"/>
+ <xsl:value-of select="$id"/>
+ </event>
+ </xsl:template>
+
+ <xsl:template match="@id">
+ <xsl:text> id="</xsl:text>
+ <xsl:value-of select="."/>
+ <xsl:text>"</xsl:text>
+ </xsl:template>
+
+ <xsl:template match="text()"/>
+
+</xsl:stylesheet>
diff --git a/test/java/org/apache/fop/fo/flow/table/AbstractTableTest.java b/test/java/org/apache/fop/fo/flow/table/AbstractTableTest.java
index 69bbc8d8c..fb6ec6a25 100644
--- a/test/java/org/apache/fop/fo/flow/table/AbstractTableTest.java
+++ b/test/java/org/apache/fop/fo/flow/table/AbstractTableTest.java
@@ -19,33 +19,37 @@
package org.apache.fop.fo.flow.table;
+import java.io.FileInputStream;
import java.util.Iterator;
import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.fo.FODocumentParser;
import org.apache.fop.fo.FOEventHandler;
-import org.apache.fop.fotreetest.FOTreeUnitTester;
+import org.apache.fop.fo.FODocumentParser.FOEventHandlerFactory;
+import org.apache.fop.util.ConsoleEventListenerForTests;
/**
* Superclass for testcases related to tables, factoring the common stuff.
*/
-abstract class AbstractTableTest extends FOTreeUnitTester {
+abstract class AbstractTableTest {
- private FOTreeUnitTester.FOEventHandlerFactory tableHandlerFactory;
+ private FODocumentParser documentParser;
private TableHandler tableHandler;
- public AbstractTableTest() throws Exception {
- super();
- tableHandlerFactory = new FOEventHandlerFactory() {
- public FOEventHandler createFOEventHandler(FOUserAgent foUserAgent) {
+ protected void setUp(String filename) throws Exception {
+ createDocumentParser();
+ documentParser.setEventListener(new ConsoleEventListenerForTests(filename));
+ documentParser.parse(new FileInputStream("test/fotree/unittests/" + filename));
+ }
+
+ private void createDocumentParser() {
+ documentParser = FODocumentParser.newInstance(new FOEventHandlerFactory() {
+ public FOEventHandler newFOEventHandler(FOUserAgent foUserAgent) {
tableHandler = new TableHandler(foUserAgent);
return tableHandler;
}
- };
- }
-
- protected void setUp(String filename) throws Exception {
- setUp(filename, tableHandlerFactory);
+ });
}
protected TableHandler getTableHandler() {
diff --git a/test/java/org/apache/fop/fo/flow/table/CollapsedConditionalBorderTestCase.java b/test/java/org/apache/fop/fo/flow/table/CollapsedConditionalBorderTestCase.java
index 0c567b976..7c0301ca7 100644
--- a/test/java/org/apache/fop/fo/flow/table/CollapsedConditionalBorderTestCase.java
+++ b/test/java/org/apache/fop/fo/flow/table/CollapsedConditionalBorderTestCase.java
@@ -25,10 +25,11 @@ import java.awt.Color;
import java.util.Iterator;
import java.util.List;
+import org.junit.Test;
+
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FONode.FONodeIterator;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
-import org.junit.Test;
/**
* A testcase for the resolution of collapsed borders in the FO tree, taking
@@ -107,10 +108,6 @@ public class CollapsedConditionalBorderTestCase extends AbstractTableTest {
{{border8pt, Color.black}, {border6pt, Color.blue}, {border8pt, Color.black}, {border6pt, Color.blue}, {border4pt, Color.black}, {border4pt, Color.black}, {border4pt, Color.red}, {border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}, {border8pt, Color.black}, {border4pt, Color.blue}, {border4pt, Color.red}, {border6pt, Color.magenta}, {border6pt, Color.magenta}, {border6pt, Color.magenta}}
};
- public CollapsedConditionalBorderTestCase() throws Exception {
- super();
- }
-
private static GridUnit getGridUnit(TablePart part) {
return (GridUnit) ((List) ((List) part.getRowGroups().get(0)).get(0)).get(0);
}
diff --git a/test/java/org/apache/fop/fo/flow/table/ErrorCheckTest.java b/test/java/org/apache/fop/fo/flow/table/ErrorCheckTest.java
index 724259a75..b30c64c07 100644
--- a/test/java/org/apache/fop/fo/flow/table/ErrorCheckTest.java
+++ b/test/java/org/apache/fop/fo/flow/table/ErrorCheckTest.java
@@ -19,8 +19,10 @@
package org.apache.fop.fo.flow.table;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import org.apache.fop.fo.LoadingException;
import org.apache.fop.fo.ValidationException;
/**
@@ -28,16 +30,13 @@ import org.apache.fop.fo.ValidationException;
*/
abstract class ErrorCheckTest extends AbstractTableTest {
- public ErrorCheckTest() throws Exception {
- super();
- }
-
protected void launchTest(String filename) throws Exception {
try {
setUp(filename);
- fail();
- } catch (ValidationException e) {
+ fail("Expected ValidationException to be thrown");
+ } catch (LoadingException e) {
// TODO check location
+ assertTrue(e.getCause() instanceof ValidationException);
}
}
diff --git a/test/java/org/apache/fop/fo/flow/table/IllegalRowSpanTestCase.java b/test/java/org/apache/fop/fo/flow/table/IllegalRowSpanTestCase.java
index 024e15c2e..b2e7a2c9d 100644
--- a/test/java/org/apache/fop/fo/flow/table/IllegalRowSpanTestCase.java
+++ b/test/java/org/apache/fop/fo/flow/table/IllegalRowSpanTestCase.java
@@ -27,10 +27,6 @@ import org.junit.Test;
*/
public class IllegalRowSpanTestCase extends ErrorCheckTest {
- public IllegalRowSpanTestCase() throws Exception {
- super();
- }
-
@Test
public void testBody1() throws Exception {
launchTest("table/illegal-row-span_body_1.fo");
diff --git a/test/java/org/apache/fop/fo/flow/table/RowGroupBuilderTestCase.java b/test/java/org/apache/fop/fo/flow/table/RowGroupBuilderTestCase.java
index 3df0338ab..361517a66 100644
--- a/test/java/org/apache/fop/fo/flow/table/RowGroupBuilderTestCase.java
+++ b/test/java/org/apache/fop/fo/flow/table/RowGroupBuilderTestCase.java
@@ -35,10 +35,6 @@ import org.junit.Test;
*/
public class RowGroupBuilderTestCase extends AbstractTableTest {
- public RowGroupBuilderTestCase() throws Exception {
- super();
- }
-
/**
* Checks that the given table-body(header,footer) will return row groups as expected.
* More precisely, checks that the number of row groups corresponds to the size of the
diff --git a/test/java/org/apache/fop/fo/flow/table/TableColumnColumnNumberTestCase.java b/test/java/org/apache/fop/fo/flow/table/TableColumnColumnNumberTestCase.java
index 4f7d9e054..a21806559 100644
--- a/test/java/org/apache/fop/fo/flow/table/TableColumnColumnNumberTestCase.java
+++ b/test/java/org/apache/fop/fo/flow/table/TableColumnColumnNumberTestCase.java
@@ -23,9 +23,10 @@ import static org.junit.Assert.assertEquals;
import java.util.Iterator;
+import org.junit.Test;
+
import org.apache.fop.datatypes.PercentBaseContext;
import org.apache.fop.fo.FObj;
-import org.junit.Test;
public class TableColumnColumnNumberTestCase extends AbstractTableTest {
@@ -50,10 +51,6 @@ public class TableColumnColumnNumberTestCase extends AbstractTableTest {
private TablePercentBaseContext percentBaseContext = new TablePercentBaseContext();
- public TableColumnColumnNumberTestCase() throws Exception {
- super();
- }
-
private void checkColumn(Table t, int number, boolean isImplicit, int spans, int repeated, int width) {
TableColumn c = t.getColumn(number - 1);
// TODO a repeated column has a correct number only for its first occurrence
diff --git a/test/java/org/apache/fop/fo/flow/table/TooManyColumnsTestCase.java b/test/java/org/apache/fop/fo/flow/table/TooManyColumnsTestCase.java
index 284fd1d2f..76a5d196d 100644
--- a/test/java/org/apache/fop/fo/flow/table/TooManyColumnsTestCase.java
+++ b/test/java/org/apache/fop/fo/flow/table/TooManyColumnsTestCase.java
@@ -23,10 +23,6 @@ import org.junit.Test;
public class TooManyColumnsTestCase extends ErrorCheckTest {
- public TooManyColumnsTestCase() throws Exception {
- super();
- }
-
@Test
public void testBody1() throws Exception {
launchTest("table/too-many-columns_body_1.fo");
diff --git a/test/java/org/apache/fop/fo/flow/table/UnimplementedWarningNeutralizer.java b/test/java/org/apache/fop/fo/flow/table/UnimplementedWarningNeutralizer.java
new file mode 100644
index 000000000..1a5e38291
--- /dev/null
+++ b/test/java/org/apache/fop/fo/flow/table/UnimplementedWarningNeutralizer.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.fo.flow.table;
+
+/**
+ * This class aims at easing testing, by preventing the event notification system from
+ * getting in the way just to issue an Unimplemented Feature warning.
+ */
+public final class UnimplementedWarningNeutralizer {
+
+ private UnimplementedWarningNeutralizer() { }
+
+ /**
+ * Neutralizes Unimplemented Feature events from the {@link TableAndCaption} and
+ * {@link TableCaption} classes.
+ */
+ public static void neutralizeUnimplementedWarning() {
+ TableAndCaption.notImplementedWarningGiven = true;
+ TableCaption.notImplementedWarningGiven = true;
+ }
+}
diff --git a/test/java/org/apache/fop/fo/properties/AltTextHolderTestCase.java b/test/java/org/apache/fop/fo/properties/AltTextHolderTestCase.java
new file mode 100644
index 000000000..cd5d545ff
--- /dev/null
+++ b/test/java/org/apache/fop/fo/properties/AltTextHolderTestCase.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.fo.properties;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.Test;
+
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.FONodeMocks;
+import org.apache.fop.fo.PropertyList;
+import org.apache.fop.fo.expr.PropertyException;
+import org.apache.fop.fo.flow.AbstractGraphics;
+import org.apache.fop.fo.flow.ExternalGraphic;
+import org.apache.fop.fo.flow.InstreamForeignObject;
+
+
+/**
+ * Tests that the fox:alt-text property is correctly set on objects that support it.
+ */
+public class AltTextHolderTestCase {
+
+ private final String altText = "alternative text";
+
+ @Test
+ public void externalGraphicHasAltText() throws FOPException {
+ testAltTextGetter(new ExternalGraphic(mockFONode()));
+ }
+
+ @Test
+ public void instreamForeignObjectHasAltText() throws FOPException {
+ testAltTextGetter(new InstreamForeignObject(mockFONode()));
+ }
+
+ private FONode mockFONode() {
+ FONode mockFONode = FONodeMocks.mockFONode();
+ FOUserAgent mockFOUserAgent = mockFONode.getFOEventHandler().getUserAgent();
+ when(mockFOUserAgent.isAccessibilityEnabled()).thenReturn(true);
+ return mockFONode;
+ }
+
+ private void testAltTextGetter(AbstractGraphics g) throws FOPException {
+ g.bind(mockPropertyList());
+ assertEquals(altText, g.getAltText());
+ }
+
+ private PropertyList mockPropertyList() throws PropertyException {
+ PropertyList mockPropertyList = PropertyListMocks.mockPropertyList();
+ Property mockAltText = mock(Property.class);
+ when(mockAltText.getString()).thenReturn(altText);
+ when(mockPropertyList.get(Constants.PR_X_ALT_TEXT)).thenReturn(mockAltText);
+ return mockPropertyList;
+ }
+
+}
diff --git a/test/java/org/apache/fop/fo/properties/CommonAccessibilityHolderTestCase.java b/test/java/org/apache/fop/fo/properties/CommonAccessibilityHolderTestCase.java
new file mode 100644
index 000000000..352a39713
--- /dev/null
+++ b/test/java/org/apache/fop/fo/properties/CommonAccessibilityHolderTestCase.java
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.fo.properties;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+
+import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.FONodeMocks;
+import org.apache.fop.fo.PropertyList;
+import org.apache.fop.fo.expr.PropertyException;
+import org.apache.fop.fo.flow.table.UnimplementedWarningNeutralizer;
+
+/**
+ * This tests that all the FONodes that implement CommonAccessibilityHolder correctly configure
+ * the CommonAccessibility property.
+ */
+public class CommonAccessibilityHolderTestCase {
+
+ private static final List<Class<? extends CommonAccessibilityHolder>> IMPLEMENTATIONS
+ = new ArrayList<Class<? extends CommonAccessibilityHolder>>();
+
+ private final String role = "role";
+
+ private final String sourceDocument = "source document";
+
+ static {
+ /* This triggers 'unimplemented feature' FO validation events so that the event system is
+ * not triggered when testing, avoiding extra convoluted dependency stubbing. */
+ UnimplementedWarningNeutralizer.neutralizeUnimplementedWarning();
+
+ IMPLEMENTATIONS.add(org.apache.fop.fo.flow.BasicLink.class);
+ IMPLEMENTATIONS.add(org.apache.fop.fo.flow.Block.class);
+ IMPLEMENTATIONS.add(org.apache.fop.fo.pagination.bookmarks.Bookmark.class);
+ IMPLEMENTATIONS.add(org.apache.fop.fo.pagination.bookmarks.BookmarkTitle.class);
+ IMPLEMENTATIONS.add(org.apache.fop.fo.flow.ExternalGraphic.class);
+ IMPLEMENTATIONS.add(org.apache.fop.fo.flow.Footnote.class);
+ IMPLEMENTATIONS.add(org.apache.fop.fo.flow.FootnoteBody.class);
+ IMPLEMENTATIONS.add(org.apache.fop.fo.flow.InitialPropertySet.class);
+ IMPLEMENTATIONS.add(org.apache.fop.fo.flow.Inline.class);
+ IMPLEMENTATIONS.add(org.apache.fop.fo.flow.InstreamForeignObject.class);
+ IMPLEMENTATIONS.add(org.apache.fop.fo.flow.Leader.class);
+ IMPLEMENTATIONS.add(org.apache.fop.fo.flow.ListBlock.class);
+ IMPLEMENTATIONS.add(org.apache.fop.fo.flow.ListItem.class);
+ IMPLEMENTATIONS.add(org.apache.fop.fo.flow.ListItemBody.class);
+ IMPLEMENTATIONS.add(org.apache.fop.fo.flow.ListItemLabel.class);
+ IMPLEMENTATIONS.add(org.apache.fop.fo.flow.PageNumber.class);
+ IMPLEMENTATIONS.add(org.apache.fop.fo.flow.PageNumberCitation.class);
+ IMPLEMENTATIONS.add(org.apache.fop.fo.flow.PageNumberCitationLast.class);
+ IMPLEMENTATIONS.add(org.apache.fop.fo.pagination.Root.class);
+ IMPLEMENTATIONS.add(org.apache.fop.fo.flow.table.Table.class);
+ IMPLEMENTATIONS.add(org.apache.fop.fo.flow.table.TableAndCaption.class);
+ IMPLEMENTATIONS.add(org.apache.fop.fo.flow.table.TableBody.class);
+ IMPLEMENTATIONS.add(org.apache.fop.fo.flow.table.TableCaption.class);
+ IMPLEMENTATIONS.add(org.apache.fop.fo.flow.table.TableCell.class);
+ IMPLEMENTATIONS.add(org.apache.fop.fo.flow.table.TableFooter.class);
+ IMPLEMENTATIONS.add(org.apache.fop.fo.flow.table.TableHeader.class);
+ IMPLEMENTATIONS.add(org.apache.fop.fo.flow.table.TableRow.class);
+ IMPLEMENTATIONS.add(org.apache.fop.fo.pagination.Title.class);
+ }
+
+ /**
+ * Bind should be overridden to correctly configure the CommonAccessibility property
+ * @throws Exception -
+ */
+ @Test
+ public void bindMustSetRoleAndSourceDoc() throws Exception {
+ final PropertyList mockPList = mockPropertyList();
+ final FONode parent = FONodeMocks.mockFONode();
+ for (Class<? extends CommonAccessibilityHolder> clazz : IMPLEMENTATIONS) {
+ Constructor<? extends CommonAccessibilityHolder> constructor
+ = clazz.getConstructor(FONode.class);
+ CommonAccessibilityHolder sut = constructor.newInstance(parent);
+ ((FONode)sut).bind(mockPList);
+ String errorMessage = "Test failed for " + clazz + ": ";
+ assertEquals(errorMessage, role, sut.getCommonAccessibility().getRole());
+ assertEquals(errorMessage, sourceDocument,
+ sut.getCommonAccessibility().getSourceDocument());
+ }
+ }
+
+ private PropertyList mockPropertyList() throws PropertyException {
+ final PropertyList mockPList = PropertyListMocks.mockPropertyList();
+ PropertyListMocks.mockTableProperties(mockPList);
+ PropertyListMocks.mockCommonBorderPaddingBackgroundProps(mockPList);
+ mockRoleProperty(mockPList);
+ mockSourceDocProperty(mockPList);
+ return mockPList;
+ }
+
+ private void mockRoleProperty(PropertyList mockPList) throws PropertyException {
+ final Property mockRoleProperty = mock(Property.class);
+ when(mockRoleProperty.getString()).thenReturn(role);
+ when(mockPList.get(Constants.PR_ROLE)).thenReturn(mockRoleProperty);
+ }
+
+ private void mockSourceDocProperty(PropertyList mockPList) throws PropertyException {
+ final Property mockSourceDocProperty = mock(Property.class);
+ when(mockSourceDocProperty.getString()).thenReturn(sourceDocument);
+ when(mockPList.get(Constants.PR_SOURCE_DOCUMENT)).thenReturn(mockSourceDocProperty);
+ }
+
+}
diff --git a/test/java/org/apache/fop/fo/properties/PropertyListMocks.java b/test/java/org/apache/fop/fo/properties/PropertyListMocks.java
new file mode 100644
index 000000000..380f6e5a8
--- /dev/null
+++ b/test/java/org/apache/fop/fo/properties/PropertyListMocks.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.fo.properties;
+
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.PropertyList;
+import org.apache.fop.fo.expr.PropertyException;
+
+/**
+ * A helper class for mocking a property list.
+ */
+public final class PropertyListMocks {
+
+ private PropertyListMocks() { }
+
+ /**
+ * Creates and returns a mock property list returning a generic default for the
+ * {@link PropertyList#get(int)} method.
+ *
+ * @return a mock property list
+ */
+ public static PropertyList mockPropertyList() {
+ try {
+ final PropertyList mockPList = mock(PropertyList.class);
+ final Property mockGenericProperty = PropertyMocks.mockGenericProperty();
+ when(mockPList.get(anyInt())).thenReturn(mockGenericProperty);
+ return mockPList;
+ } catch (PropertyException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Overrides with working mock properties the values returned by
+ * {@link PropertyList#get(int)} for {@link Constants#PR_COLUMN_NUMBER},
+ * {@link Constants#PR_NUMBER_COLUMNS_SPANNED},
+ * {@link Constants#PR_NUMBER_ROWS_SPANNED} and {@link Constants#PR_BORDER_COLLAPSE}.
+ *
+ * @param mockPList a mock property list
+ */
+ public static void mockTableProperties(PropertyList mockPList) {
+ try {
+ final Property mockNumberProperty = PropertyMocks.mockNumberProperty();
+ when(mockPList.get(Constants.PR_COLUMN_NUMBER)).thenReturn(mockNumberProperty);
+ when(mockPList.get(Constants.PR_NUMBER_COLUMNS_SPANNED)).thenReturn(mockNumberProperty);
+ when(mockPList.get(Constants.PR_NUMBER_ROWS_SPANNED)).thenReturn(mockNumberProperty);
+
+ final Property borderCollapseProperty = mock(Property.class);
+ when(borderCollapseProperty.getEnum()).thenReturn(Constants.EN_SEPARATE);
+ when(mockPList.get(Constants.PR_BORDER_COLLAPSE)).thenReturn(borderCollapseProperty);
+ } catch (PropertyException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Overrides with a working mock property the value returned by
+ * {@link PropertyList#getBorderPaddingBackgroundProps()}.
+ *
+ * @param mockPList a mock property list
+ */
+ public static void mockCommonBorderPaddingBackgroundProps(PropertyList mockPList) {
+ try {
+ final CommonBorderPaddingBackground mockCommonBorderPaddingBackground
+ = mock(CommonBorderPaddingBackground.class);
+ when(mockPList.getBorderPaddingBackgroundProps())
+ .thenReturn(mockCommonBorderPaddingBackground);
+ } catch (PropertyException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/test/java/org/apache/fop/fo/properties/PropertyMocks.java b/test/java/org/apache/fop/fo/properties/PropertyMocks.java
new file mode 100644
index 000000000..40c923249
--- /dev/null
+++ b/test/java/org/apache/fop/fo/properties/PropertyMocks.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.fo.properties;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.apache.fop.datatypes.Numeric;
+import org.apache.fop.datatypes.PercentBaseContext;
+import org.apache.fop.fo.Constants;
+
+/**
+ * Helper class to create mocks of various kinds of properties.
+ */
+public final class PropertyMocks {
+
+ private PropertyMocks() { }
+
+ /**
+ * Creates and returns a generic mock property returning decent defaults for the
+ * {@link Property#getString()}, {@link Property#getEnum()} and
+ * {@link Property#getLengthRange()} methods.
+ *
+ * @return a mock all-purpose property
+ */
+ public static Property mockGenericProperty() {
+ final Property mockGenericProperty = mock(Property.class);
+ when(mockGenericProperty.getString()).thenReturn("A non-empty string");
+ when(mockGenericProperty.getEnum()).thenReturn(Constants.EN_SPACE);
+ LengthRangeProperty lengthRangeProperty = mockLengthRangeProperty();
+ when(mockGenericProperty.getLengthRange()).thenReturn(lengthRangeProperty);
+ return mockGenericProperty;
+ }
+
+ private static LengthRangeProperty mockLengthRangeProperty() {
+ final LengthRangeProperty mockLengthRangeProperty = mock(LengthRangeProperty.class);
+ final Property optimum = mockOptimumProperty();
+ when(mockLengthRangeProperty.getOptimum(any(PercentBaseContext.class)))
+ .thenReturn(optimum);
+ return mockLengthRangeProperty;
+ }
+
+ /**
+ * Creates and returns a mock property returning a decent default for the
+ * {@link Property#getNumeric()} method.
+ *
+ * @return a mock number property
+ */
+ public static Property mockNumberProperty() {
+ final Property mockNumberProperty = mock(Property.class);
+ final Numeric mockNumeric = mock(Numeric.class);
+ when(mockNumberProperty.getNumeric()).thenReturn(mockNumeric);
+ return mockNumberProperty;
+ }
+
+ private static Property mockOptimumProperty() {
+ final Property optimum = mock(Property.class);
+ when(optimum.isAuto()).thenReturn(true);
+ return optimum;
+ }
+
+}
diff --git a/test/java/org/apache/fop/fotreetest/FOTreeTestSuite.java b/test/java/org/apache/fop/fotreetest/FOTreeTestSuite.java
index 4a77ca000..b74afefc5 100644
--- a/test/java/org/apache/fop/fotreetest/FOTreeTestSuite.java
+++ b/test/java/org/apache/fop/fotreetest/FOTreeTestSuite.java
@@ -29,7 +29,9 @@ import org.junit.runners.Suite;
@Suite.SuiteClasses({
org.apache.fop.fo.flow.table.AllTests.class,
org.apache.fop.fo.pagination.AllTests.class,
- FOTreeTestCase.class })
-
+ org.apache.fop.fotreetest.FOTreeTestCase.class,
+ org.apache.fop.fo.properties.CommonAccessibilityHolderTestCase.class,
+ org.apache.fop.fo.DelegatingFOEventHandlerTestCase.class
+})
public final class FOTreeTestSuite {
}
diff --git a/test/java/org/apache/fop/fotreetest/FOTreeUnitTester.java b/test/java/org/apache/fop/fotreetest/FOTreeUnitTester.java
deleted file mode 100644
index 0906c266d..000000000
--- a/test/java/org/apache/fop/fotreetest/FOTreeUnitTester.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* $Id$ */
-
-package org.apache.fop.fotreetest;
-
-import java.io.File;
-
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-
-import org.apache.fop.apps.FOUserAgent;
-import org.apache.fop.apps.Fop;
-import org.apache.fop.apps.FopFactory;
-import org.apache.fop.fo.FOEventHandler;
-import org.apache.fop.util.ConsoleEventListenerForTests;
-import org.xml.sax.XMLReader;
-
-
-/**
- * Base class for unit-testing the FO tree building code. It performs the necessary setup
- * to parse an FO file and register a proper {@link FOEventHandler}. That handler will be
- * the entry point to test classes from the FObj hierarchy.
- */
-public abstract class FOTreeUnitTester {
-
- private XMLReader foReader;
-
- private FopFactory fopFactory;
-
- /**
- * Should be implemented by children testcases for properly setting up the custom
- * FOEventHandler needed to test FObj classes.
- */
- public abstract static class FOEventHandlerFactory {
-
- /**
- * This method is called by FOTreeUnitTester when creating a {@link Fop} instance.
- * That lets pass to the custom FOEventHandler the proper user agent that will be
- * used by this instance.
- *
- * @param foUserAgent the user agent needed by the Fop instance that will be used
- * to create the FO tree
- * @return the appropriate FOEventHandler for performing the tests
- */
- public abstract FOEventHandler createFOEventHandler(FOUserAgent foUserAgent);
- }
-
- public FOTreeUnitTester() throws Exception {
- // Stuff that needs to be set up only once and will be re-used for each test
- SAXParserFactory spf = SAXParserFactory.newInstance();
- spf.setNamespaceAware(true);
- spf.setValidating(false);
- SAXParser parser;
- parser = spf.newSAXParser();
- foReader = parser.getXMLReader();
- fopFactory = FopFactory.newInstance();
- }
-
- /**
- * Launches FOP on the given FO file.
- *
- * @param filename path to the test FO file
- * @param factory to create the appropriate FOEventHandler for performing tests
- */
- public void setUp(String filename, FOEventHandlerFactory factory) throws Exception {
- FOUserAgent ua = fopFactory.newFOUserAgent();
- ua.setFOEventHandlerOverride(factory.createFOEventHandler(ua));
- ua.getEventBroadcaster().addEventListener(
- new ConsoleEventListenerForTests(filename));
-
- Fop fop = fopFactory.newFop(ua);
-
- foReader.setContentHandler(fop.getDefaultHandler());
- foReader.setDTDHandler(fop.getDefaultHandler());
- foReader.setErrorHandler(fop.getDefaultHandler());
- foReader.setEntityResolver(fop.getDefaultHandler());
-
- foReader.parse(new File("test/fotree/unittests/" + filename).toURI().toURL().toExternalForm());
- }
-}
diff --git a/test/java/org/apache/fop/intermediate/IFParserTestCase.java b/test/java/org/apache/fop/intermediate/IFParserTestCase.java
index c37897dc1..7d4fb7ad8 100644
--- a/test/java/org/apache/fop/intermediate/IFParserTestCase.java
+++ b/test/java/org/apache/fop/intermediate/IFParserTestCase.java
@@ -48,6 +48,9 @@ import org.apache.fop.render.intermediate.IFSerializer;
@RunWith(Parameterized.class)
public class IFParserTestCase extends AbstractIFTest {
+ /** Set this to true to get the correspondence between test number and test file. */
+ private static final boolean DEBUG = false;
+
/**
* Gets the parameters for this test
*
@@ -56,7 +59,19 @@ public class IFParserTestCase extends AbstractIFTest {
*/
@Parameters
public static Collection<File[]> getParameters() throws IOException {
- return LayoutEngineTestUtils.getLayoutTestFiles();
+ Collection<File[]> testFiles = LayoutEngineTestUtils.getLayoutTestFiles();
+ if (DEBUG) {
+ printFiles(testFiles);
+ }
+ return testFiles;
+ }
+
+ private static void printFiles(Collection<File[]> files) {
+ int index = 0;
+ for (File[] file : files) {
+ assert file.length == 1;
+ System.out.println(String.format("%3d %s", index++, file[0]));
+ }
}
/**
diff --git a/test/java/org/apache/fop/render/intermediate/IFStructureTreeBuilderTestCase.java b/test/java/org/apache/fop/render/intermediate/IFStructureTreeBuilderTestCase.java
new file mode 100644
index 000000000..65c6b25a6
--- /dev/null
+++ b/test/java/org/apache/fop/render/intermediate/IFStructureTreeBuilderTestCase.java
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.intermediate;
+
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentMatcher;
+import org.mockito.InOrder;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import org.apache.fop.fo.FOElementMapping;
+import org.apache.fop.fo.extensions.ExtensionElementMapping;
+import org.apache.fop.fo.extensions.InternalElementMapping;
+import org.apache.fop.util.XMLUtil;
+
+public class IFStructureTreeBuilderTestCase {
+
+ private IFStructureTreeBuilder sut;
+
+ @Before
+ public void setUp() {
+ sut = new IFStructureTreeBuilder();
+ }
+
+ @Test
+ public void startAndEndPageSequence() throws SAXException {
+ final ContentHandler handler = mock(ContentHandler.class);
+
+ try {
+ sut.replayEventsForPageSequence(handler, 0);
+ fail("No page sequences created");
+ } catch (IndexOutOfBoundsException e) {
+ // Expected
+ }
+
+ sut.startPageSequence(null);
+ sut.endPageSequence();
+
+ sut.replayEventsForPageSequence(handler, 0);
+
+ InOrder inOrder = inOrder(handler);
+
+ inOrder.verify(handler).startPrefixMapping(
+ InternalElementMapping.STANDARD_PREFIX, InternalElementMapping.URI);
+ inOrder.verify(handler).startPrefixMapping(
+ ExtensionElementMapping.STANDARD_PREFIX, ExtensionElementMapping.URI);
+ inOrder.verify(handler).startElement(eq(IFConstants.NAMESPACE),
+ eq(IFConstants.EL_STRUCTURE_TREE),
+ eq(IFConstants.EL_STRUCTURE_TREE),
+ any(Attributes.class));
+ inOrder.verify(handler).endElement(eq(IFConstants.NAMESPACE),
+ eq(IFConstants.EL_STRUCTURE_TREE),
+ eq(IFConstants.EL_STRUCTURE_TREE));
+ inOrder.verify(handler).endPrefixMapping(ExtensionElementMapping.STANDARD_PREFIX);
+ inOrder.verify(handler).endPrefixMapping(InternalElementMapping.STANDARD_PREFIX);
+ }
+
+ @Test
+ public void startNode() throws Exception {
+ final String[] attributes = {"struct-id", "1"};
+ final String nodeName = "block";
+ final ContentHandler handler = mock(ContentHandler.class);
+
+ sut.startPageSequence(null);
+ sut.startNode(nodeName, createSimpleAttributes(attributes));
+ sut.endPageSequence();
+
+ sut.replayEventsForPageSequence(handler, 0);
+
+ verify(handler).startElement(eq(FOElementMapping.URI), eq(nodeName),
+ eq(FOElementMapping.STANDARD_PREFIX + ":" + nodeName),
+ AttributesMatcher.match(createSimpleAttributes(attributes)));
+ }
+
+ @Test
+ public void endNode() throws Exception {
+ final String nodeName = "block";
+ final ContentHandler handler = mock(ContentHandler.class);
+
+ sut.startPageSequence(null);
+ sut.endNode(nodeName);
+ sut.endPageSequence();
+
+ sut.replayEventsForPageSequence(handler, 0);
+
+ verify(handler).endElement(eq(FOElementMapping.URI), eq(nodeName),
+ eq(FOElementMapping.STANDARD_PREFIX + ":" + nodeName));
+ }
+
+ private static Attributes createSimpleAttributes(String... attributes) {
+ assert (attributes.length % 2 == 0);
+ final AttributesImpl atts = new AttributesImpl();
+ for (int i = 0; i < attributes.length; i += 2) {
+ String key = attributes[i];
+ String value = attributes[i + 1];
+ atts.addAttribute("", key, key, XMLUtil.CDATA, value);
+ }
+ return atts;
+ }
+
+ private static final class AttributesMatcher extends ArgumentMatcher<Attributes> {
+
+ private final Attributes expected;
+
+ private AttributesMatcher(Attributes expected) {
+ this.expected = expected;
+ }
+
+ public static Attributes match(Attributes expected) {
+ return argThat(new AttributesMatcher(expected));
+ }
+
+ public boolean matches(Object attributes) {
+ return attributesEqual(expected, (Attributes) attributes);
+ }
+
+ private static boolean attributesEqual(Attributes attributes1, Attributes attributes2) {
+ if (attributes1.getLength() != attributes2.getLength()) {
+ return false;
+ }
+ for (int i = 0; i < attributes1.getLength(); i++) {
+ if (attributes1.getLocalName(i) != attributes2.getLocalName(i)) {
+ return false;
+ }
+ if (attributes1.getQName(i) != attributes2.getQName(i)) {
+ return false;
+ }
+ if (attributes1.getType(i) != attributes2.getType(i)) {
+ return false;
+ }
+ if (attributes1.getURI(i) != attributes2.getURI(i)) {
+ return false;
+ }
+ if (attributes1.getValue(i) != attributes2.getValue(i)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+}
diff --git a/test/java/org/apache/fop/render/intermediate/SAXEventRecorderTestCase.java b/test/java/org/apache/fop/render/intermediate/SAXEventRecorderTestCase.java
new file mode 100644
index 000000000..c5aad66d0
--- /dev/null
+++ b/test/java/org/apache/fop/render/intermediate/SAXEventRecorderTestCase.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.intermediate;
+
+
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import org.apache.fop.render.intermediate.IFStructureTreeBuilder.SAXEventRecorder;
+import org.apache.fop.util.XMLUtil;
+
+/**
+ * Tests {@link SAXEventRecorder}.
+ */
+public class SAXEventRecorderTestCase {
+
+ private static final String URI = "http://www.example.com/";
+
+ private SAXEventRecorder sut;
+
+ @Before
+ public void setUp() {
+ sut = new SAXEventRecorder();
+ }
+
+ @Test
+ public void testStartEvent() throws SAXException {
+ final String localName = "element";
+ final String qName = "prefix:" + localName;
+ final Attributes attributes = new AttributesImpl();
+
+ sut.startElement(URI, localName, qName, attributes);
+ ContentHandler handler = mock(ContentHandler.class);
+ sut.replay(handler);
+ verify(handler).startElement(URI, localName, qName, attributes);
+ }
+
+ @Test
+ public void testEndEvent() throws SAXException {
+ final String localName = "element";
+ final String qName = "prefix:" + localName;
+ sut.endElement(URI, localName, qName);
+ ContentHandler handler = mock(ContentHandler.class);
+ sut.replay(handler);
+ verify(handler).endElement(URI, localName, qName);
+ }
+
+ @Test
+ public void testStartPrefixMapping() throws SAXException {
+ final String prefix = "prefix";
+
+ sut.startPrefixMapping(URI, prefix);
+ ContentHandler handler = mock(ContentHandler.class);
+ sut.replay(handler);
+ verify(handler).startPrefixMapping(URI, prefix);
+ }
+
+ @Test
+ public void testEndPrefixMapping() throws SAXException {
+ final String prefix = "prefix";
+
+ sut.endPrefixMapping(prefix);
+ ContentHandler handler = mock(ContentHandler.class);
+ sut.replay(handler);
+ verify(handler).endPrefixMapping(prefix);
+ }
+
+ @Test
+ public void completeTest() throws SAXException {
+ final String localName1 = "element";
+ final String qName1 = "prefix:" + localName1;
+ final Attributes attributes1 = createAttributes(URI, localName1, qName1, "value-1");
+ final String localName2 = "element2";
+ final String qName2 = "prefix:" + localName2;
+ final Attributes attributes2 = createAttributes(URI, localName2, qName2, "value-2");
+ final ContentHandler handler = mock(ContentHandler.class);
+ final String extensionUrl = "http://www.example.com/extension";
+ final String extensionPrefix = "ext";
+
+ sut.startPrefixMapping(extensionPrefix, extensionUrl);
+ sut.startElement(URI, localName1, qName1, attributes1);
+ sut.startElement(URI, localName2, qName2, attributes2);
+ sut.endElement(URI, localName2, qName2);
+ sut.endElement(URI, localName1, qName1);
+ sut.endPrefixMapping(extensionPrefix);
+
+ sut.replay(handler);
+
+ InOrder inOrder = inOrder(handler);
+ inOrder.verify(handler).startPrefixMapping(extensionPrefix, extensionUrl);
+ inOrder.verify(handler).startElement(URI, localName1, qName1, attributes1);
+ inOrder.verify(handler).startElement(URI, localName2, qName2, attributes2);
+ inOrder.verify(handler).endElement(URI, localName2, qName2);
+ inOrder.verify(handler).endElement(URI, localName1, qName1);
+ inOrder.verify(handler).endPrefixMapping(extensionPrefix);
+ }
+
+ private static Attributes createAttributes(String uri, String localName,
+ String qName, String value) {
+ final AttributesImpl atts = new AttributesImpl();
+ atts.addAttribute(uri, localName, qName, XMLUtil.CDATA, value);
+ return atts;
+ }
+
+}
diff --git a/test/java/org/apache/fop/util/XMLUtilTestCase.java b/test/java/org/apache/fop/util/LanguageTagsTestCase.java
index 4c1b999e1..f7383c720 100644
--- a/test/java/org/apache/fop/util/XMLUtilTestCase.java
+++ b/test/java/org/apache/fop/util/LanguageTagsTestCase.java
@@ -20,31 +20,39 @@
package org.apache.fop.util;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
import java.util.Locale;
import org.junit.Test;
/**
- * Tests {@link XMLUtil}.
+ * Tests {@link LanguageTags}.
*/
-public class XMLUtilTestCase {
+public class LanguageTagsTestCase {
+
+ @Test(expected = NullPointerException.class)
+ public void toLanguageTagRejectsNull() {
+ LanguageTags.toLanguageTag(null);
+ }
@Test
- public void testLocaleToRFC3066() throws Exception {
- assertNull(XMLUtil.toRFC3066(null));
- assertEquals("en", XMLUtil.toRFC3066(new Locale("en")));
- assertEquals("en-US", XMLUtil.toRFC3066(new Locale("en", "US")));
- assertEquals("en-US", XMLUtil.toRFC3066(new Locale("EN", "us")));
+ public void testToLanguageTag() throws Exception {
+ assertEquals("", LanguageTags.toLanguageTag(new Locale("")));
+ assertEquals("en", LanguageTags.toLanguageTag(new Locale("en")));
+ assertEquals("en-US", LanguageTags.toLanguageTag(new Locale("en", "US")));
+ assertEquals("en-US", LanguageTags.toLanguageTag(new Locale("EN", "us")));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void toLocaleRejectsNull() {
+ LanguageTags.toLocale(null);
}
@Test
public void testRFC3066ToLocale() throws Exception {
- assertNull(XMLUtil.convertRFC3066ToLocale(null));
- assertNull(XMLUtil.convertRFC3066ToLocale(""));
- assertEquals(new Locale("en"), XMLUtil.convertRFC3066ToLocale("en"));
- assertEquals(new Locale("en", "US"), XMLUtil.convertRFC3066ToLocale("en-US"));
- assertEquals(new Locale("en", "US"), XMLUtil.convertRFC3066ToLocale("EN-us"));
+ assertEquals(new Locale(""), LanguageTags.toLocale(""));
+ assertEquals(new Locale("en"), LanguageTags.toLocale("en"));
+ assertEquals(new Locale("en", "US"), LanguageTags.toLocale("en-US"));
+ assertEquals(new Locale("en", "US"), LanguageTags.toLocale("EN-us"));
}
}