aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Hancock <phancock@apache.org>2012-01-27 15:36:05 +0000
committerPeter Hancock <phancock@apache.org>2012-01-27 15:36:05 +0000
commit160d78ce1c348b96e9807f59f3d20bb2226e75c0 (patch)
tree2649855fe306b6206f7cd9d7b3cf81035b79cee3
parentc6fb066a02573904f7ca404605f14c800adf80c5 (diff)
downloadxmlgraphics-fop-160d78ce1c348b96e9807f59f3d20bb2226e75c0.tar.gz
xmlgraphics-fop-160d78ce1c348b96e9807f59f3d20bb2226e75c0.zip
Associate structure tree elements directly to render content
* Defer the binding of PCData to struct elems using a placeholder mechanism. * Translate text nodes to marked-content sequences in IF structure tree. * Replace ptr with structure tree element. * Re-order table footers so they appear at the end of the structure tree. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_ImproveAccessibility@1236718 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--build.xml1
-rw-r--r--src/java/org/apache/fop/accessibility/DummyStructureTreeEventHandler.java23
-rw-r--r--src/java/org/apache/fop/accessibility/StructureTree2SAXEventAdapter.java35
-rw-r--r--src/java/org/apache/fop/accessibility/StructureTreeElement.java (renamed from src/java/org/apache/fop/fo/properties/StructurePointerPropertySet.java)19
-rw-r--r--src/java/org/apache/fop/accessibility/StructureTreeEventHandler.java31
-rw-r--r--src/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java (renamed from src/java/org/apache/fop/accessibility/FO2StructureTreeConverter.java)390
-rw-r--r--src/java/org/apache/fop/accessibility/fo/FOEventRecorder.java508
-rw-r--r--src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java408
-rw-r--r--src/java/org/apache/fop/area/AreaTreeParser.java11
-rw-r--r--src/java/org/apache/fop/area/Trait.java6
-rw-r--r--src/java/org/apache/fop/fo/DelegatingFOEventHandler.java4
-rw-r--r--src/java/org/apache/fop/fo/FOEventHandler.java10
-rw-r--r--src/java/org/apache/fop/fo/FONode.java3
-rw-r--r--src/java/org/apache/fop/fo/FOText.java33
-rw-r--r--src/java/org/apache/fop/fo/FOTreeBuilder.java2
-rw-r--r--src/java/org/apache/fop/fo/extensions/InternalElementMapping.java9
-rw-r--r--src/java/org/apache/fop/fo/flow/AbstractGraphics.java15
-rw-r--r--src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java15
-rw-r--r--src/java/org/apache/fop/fo/flow/BasicLink.java15
-rw-r--r--src/java/org/apache/fop/fo/flow/Block.java14
-rw-r--r--src/java/org/apache/fop/fo/flow/Character.java15
-rw-r--r--src/java/org/apache/fop/fo/flow/Inline.java14
-rw-r--r--src/java/org/apache/fop/fo/flow/PageNumber.java15
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableFObj.java14
-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.java14
-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/PDFStructElem.java102
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFContext.java33
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFParser.java56
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFRenderer.java21
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFSerializer.java29
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFStructureTreeBuilder.java118
-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/pdf/PDFDocumentNavigationHandler.java8
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java84
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFPainter.java21
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java71
-rw-r--r--src/java/org/apache/fop/render/rtf/RTFHandler.java12
-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/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.pdfbin12814 -> 12806 bytes
-rw-r--r--test/accessibility/pdf/background-image_jpg_single.pdfbin12653 -> 12645 bytes
-rw-r--r--test/accessibility/pdf/background-image_png_repeat.pdfbin35437 -> 35429 bytes
-rw-r--r--test/accessibility/pdf/background-image_png_single.pdfbin58317 -> 58309 bytes
-rw-r--r--test/accessibility/pdf/background-image_svg_repeat.pdfbin17104 -> 17096 bytes
-rw-r--r--test/accessibility/pdf/background-image_svg_single.pdfbin9943 -> 9935 bytes
-rw-r--r--test/accessibility/pdf/complete.pdfbin96730 -> 96722 bytes
-rw-r--r--test/accessibility/pdf/image_jpg.pdfbin9078 -> 9070 bytes
-rw-r--r--test/accessibility/pdf/image_png.pdfbin57788 -> 57780 bytes
-rw-r--r--test/accessibility/pdf/image_svg.pdfbin14292 -> 14284 bytes
-rw-r--r--test/accessibility/pdf/image_wmf.pdfbin208454 -> 304960 bytes
-rw-r--r--test/accessibility/pdf/leader.pdfbin9379 -> 9371 bytes
-rw-r--r--test/accessibility/pdf/links.pdfbin9712 -> 9704 bytes
-rw-r--r--test/accessibility/pdf/role.pdfbin18976 -> 18968 bytes
-rw-r--r--test/accessibility/pdf/role_non-standard.pdfbin18990 -> 18982 bytes
-rw-r--r--test/accessibility/pdf/text_1.pdfbin7504 -> 7496 bytes
-rw-r--r--test/accessibility/pdf/text_2.pdfbin10346 -> 10338 bytes
-rw-r--r--test/accessibility/pdf/text_font-embedding.pdfbin19785 -> 19777 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/accessibility/fo/DOMResultUtil.java54
-rw-r--r--test/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverterTestCase.java (renamed from test/java/org/apache/fop/accessibility/FO2StructureTreeConverterTestCase.java)109
-rw-r--r--test/java/org/apache/fop/accessibility/fo/fo2StructureTree.xsl (renamed from test/java/org/apache/fop/accessibility/fo2StructureTree.xsl)23
-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/render/intermediate/IFStructureTreeBuilderTestCase.java2
88 files changed, 1968 insertions, 845 deletions
diff --git a/build.xml b/build.xml
index dda6493ae..8bc66cd95 100644
--- a/build.xml
+++ b/build.xml
@@ -581,6 +581,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"/>
diff --git a/src/java/org/apache/fop/accessibility/DummyStructureTreeEventHandler.java b/src/java/org/apache/fop/accessibility/DummyStructureTreeEventHandler.java
index 80a011bab..07daf2f73 100644
--- a/src/java/org/apache/fop/accessibility/DummyStructureTreeEventHandler.java
+++ b/src/java/org/apache/fop/accessibility/DummyStructureTreeEventHandler.java
@@ -33,20 +33,31 @@ public final class DummyStructureTreeEventHandler implements StructureTreeEventH
private DummyStructureTreeEventHandler() { }
- /** {@inheritDoc} */
public void startPageSequence(Locale locale) {
}
- /** {@inheritDoc} */
- public void startNode(String name, Attributes attributes) {
+ public void endPageSequence() {
+ }
+
+ public StructureTreeElement startNode(String name, Attributes attributes) {
+ return null;
}
- /** {@inheritDoc} */
public void endNode(String name) {
}
- /** {@inheritDoc} */
- public void endPageSequence() {
+ public StructureTreeElement startImageNode(String name, Attributes attributes) {
+ return null;
+ }
+
+ public void endImageNode(String name) {
+ }
+
+ public StructureTreeElement startReferencedNode(String name, Attributes attributes) {
+ return null;
+ }
+
+ public void endReferencedNode(String name) {
}
}
diff --git a/src/java/org/apache/fop/accessibility/StructureTree2SAXEventAdapter.java b/src/java/org/apache/fop/accessibility/StructureTree2SAXEventAdapter.java
index 240c384d6..2cd92a5ce 100644
--- a/src/java/org/apache/fop/accessibility/StructureTree2SAXEventAdapter.java
+++ b/src/java/org/apache/fop/accessibility/StructureTree2SAXEventAdapter.java
@@ -50,7 +50,6 @@ public final class StructureTree2SAXEventAdapter implements StructureTreeEventHa
return new StructureTree2SAXEventAdapter(contentHandler);
}
- /** {@inheritDoc} */
public void startPageSequence(Locale locale) {
try {
@@ -66,7 +65,6 @@ public final class StructureTree2SAXEventAdapter implements StructureTreeEventHa
}
}
- /** {@inheritDoc} */
public void endPageSequence() {
try {
contentHandler.endElement(IFConstants.NAMESPACE, IFConstants.EL_STRUCTURE_TREE,
@@ -81,18 +79,23 @@ public final class StructureTree2SAXEventAdapter implements StructureTreeEventHa
}
}
- /** {@inheritDoc} */
- public void startNode(String name, Attributes attributes) {
+ public StructureTreeElement startNode(String name, Attributes attributes) {
try {
- contentHandler.startElement(FOElementMapping.URI, name,
- FOElementMapping.STANDARD_PREFIX + ":" + name,
- attributes);
+ 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,
@@ -101,4 +104,20 @@ public final class StructureTree2SAXEventAdapter implements StructureTreeEventHa
throw new RuntimeException(e);
}
}
+
+ public StructureTreeElement startImageNode(String name, Attributes attributes) {
+ return startNode(name, attributes);
+ }
+
+ public void endImageNode(String name) {
+ endNode(name);
+ }
+
+ public StructureTreeElement startReferencedNode(String name, Attributes attributes) {
+ return startNode(name, attributes);
+ }
+
+ public void endReferencedNode(String name) {
+ endNode(name);
+ }
}
diff --git a/src/java/org/apache/fop/fo/properties/StructurePointerPropertySet.java b/src/java/org/apache/fop/accessibility/StructureTreeElement.java
index 5cce2822e..3a691c42c 100644
--- a/src/java/org/apache/fop/fo/properties/StructurePointerPropertySet.java
+++ b/src/java/org/apache/fop/accessibility/StructureTreeElement.java
@@ -17,18 +17,15 @@
/* $Id$ */
-package org.apache.fop.fo.properties;
-
/**
- * Defines property access methods for internal structure pointer extension properties.
+ *
*/
-public interface StructurePointerPropertySet {
-
- /**
- * 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
- */
- String getPtr();
+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
index d84d07870..4b94d61f1 100644
--- a/src/java/org/apache/fop/accessibility/StructureTreeEventHandler.java
+++ b/src/java/org/apache/fop/accessibility/StructureTreeEventHandler.java
@@ -32,24 +32,47 @@ 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 Map of node properties
+ *
+ * @param name the name of the structure tree node
+ * @param attributes the node properties
+ * @return the corresponding structure tree element
*/
- void startNode(String name, Attributes attributes);
+ StructureTreeElement startNode(String name, Attributes attributes);
/**
* Ends a structure tree node.
- * @param name The name of the 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/FO2StructureTreeConverter.java b/src/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java
index e6d0193b9..47c227e9a 100644
--- a/src/java/org/apache/fop/accessibility/FO2StructureTreeConverter.java
+++ b/src/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java
@@ -17,21 +17,17 @@
/* $Id$ */
-package org.apache.fop.accessibility;
+package org.apache.fop.accessibility.fo;
-import java.util.Locale;
+import java.util.Stack;
import org.xml.sax.SAXException;
-import org.xml.sax.helpers.AttributesImpl;
-import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.accessibility.StructureTreeEventHandler;
import org.apache.fop.fo.DelegatingFOEventHandler;
import org.apache.fop.fo.FOEventHandler;
-import org.apache.fop.fo.FONode;
-import org.apache.fop.fo.extensions.ExtensionElementMapping;
+import org.apache.fop.fo.FOText;
import org.apache.fop.fo.extensions.ExternalDocument;
-import org.apache.fop.fo.extensions.InternalElementMapping;
-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;
@@ -61,8 +57,6 @@ 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.fo.properties.CommonAccessibilityHolder;
-import org.apache.fop.util.XMLUtil;
/**
* Allows to create the structure tree of an FO document, by converting FO
@@ -70,354 +64,18 @@ import org.apache.fop.util.XMLUtil;
*/
public class FO2StructureTreeConverter extends DelegatingFOEventHandler {
- private int idCounter;
-
- /** Delegates to either {@link #foToStructureTreeEventAdapter} or {@link #eventSwallower}. */
+ /** The top of the {@link converters} stack. */
private FOEventHandler converter;
- private final FOEventHandler foToStructureTreeEventAdapter;
-
- /** The descendants of some elements like fo:leader must be ignored. */
- private final FOEventHandler eventSwallower;
-
- private final StructureTreeEventHandler structureTreeEventHandler;
-
- private final class FOToStructureTreeEventAdapter extends FOEventHandler {
-
- public FOToStructureTreeEventAdapter(FOUserAgent foUserAgent) {
- super(foUserAgent);
- }
-
- @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) {
- startElementWithID(bl);
- }
-
- @Override
- public void endBlock(Block bl) {
- endElement(bl);
- }
+ private final Stack<FOEventHandler> converters = new Stack<FOEventHandler>();
- @Override
- public void startBlockContainer(BlockContainer blc) {
- startElement(blc);
- }
+ private final Stack<FOEventRecorder> tableFooterRecorders = new Stack<FOEventRecorder>();
- @Override
- public void endBlockContainer(BlockContainer blc) {
- endElement(blc);
- }
+ private final FOEventHandler structureTreeEventTrigger;
- @Override
- public void startInline(Inline inl) {
- startElementWithID(inl);
- }
-
- @Override
- public void endInline(Inline inl) {
- endElement(inl);
- }
-
- @Override
- public void startTable(Table tbl) {
- startElementWithID(tbl);
- }
-
- @Override
- public void endTable(Table tbl) {
- endElement(tbl);
- }
-
- @Override
- public void startHeader(TableHeader header) {
- startElementWithID(header);
- }
-
- @Override
- public void endHeader(TableHeader header) {
- endElement(header);
- }
-
- @Override
- public void startFooter(TableFooter footer) {
- startElementWithID(footer);
- }
-
- @Override
- public void endFooter(TableFooter footer) {
- endElement(footer);
- }
-
- @Override
- public void startBody(TableBody body) {
- startElementWithID(body);
- }
-
- @Override
- public void endBody(TableBody body) {
- endElement(body);
- }
-
- @Override
- public void startRow(TableRow tr) {
- startElementWithID(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));
- }
- startElementWithID(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);
- }
-
-
- private void startElement(FONode node) {
- startElement(node, new AttributesImpl());
- }
-
- private void startElementWithID(FONode node) {
- startElementWithID(node, new AttributesImpl());
- }
-
- private void startElementWithIDAndAltText(AbstractGraphics node) {
- AttributesImpl attributes = new AttributesImpl();
- addAttribute(attributes, ExtensionElementMapping.URI, "alt-text",
- ExtensionElementMapping.STANDARD_PREFIX, node.getAltText());
- startElementWithID(node, attributes);
- }
-
- private void startElementWithID(FONode node, AttributesImpl attributes) {
- String id = Integer.toHexString(idCounter++);
- node.setPtr(id);
- addAttribute(attributes,
- InternalElementMapping.URI, "ptr", InternalElementMapping.STANDARD_PREFIX, id);
- startElement(node, attributes);
- }
-
- private void startElement(FONode node, AttributesImpl attributes) {
- String localName = node.getLocalName();
- if (node instanceof CommonAccessibilityHolder) {
- addRole((CommonAccessibilityHolder) node, attributes);
- }
- 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);
- }
-
- }
+ /** The descendants of some elements like fo:leader must be ignored. */
+ private final FOEventHandler eventSwallower = new FOEventHandler() {
+ };
/**
* Creates a new instance.
@@ -428,10 +86,8 @@ public class FO2StructureTreeConverter extends DelegatingFOEventHandler {
public FO2StructureTreeConverter(StructureTreeEventHandler structureTreeEventHandler,
FOEventHandler delegate) {
super(delegate);
- this.structureTreeEventHandler = structureTreeEventHandler;
- this.foToStructureTreeEventAdapter = new FOToStructureTreeEventAdapter(foUserAgent);
- this.converter = foToStructureTreeEventAdapter;
- this.eventSwallower = new FOEventHandler(foUserAgent) { };
+ this.structureTreeEventTrigger = new StructureTreeEventTrigger(structureTreeEventHandler);
+ this.converter = structureTreeEventTrigger;
}
@Override
@@ -557,11 +213,16 @@ public class FO2StructureTreeConverter extends DelegatingFOEventHandler {
@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);
}
@@ -592,6 +253,8 @@ public class FO2StructureTreeConverter extends DelegatingFOEventHandler {
@Override
public void startFooter(TableFooter footer) {
+ converters.push(converter);
+ converter = new FOEventRecorder();
converter.startFooter(footer);
super.startFooter(footer);
}
@@ -599,6 +262,10 @@ public class FO2StructureTreeConverter extends DelegatingFOEventHandler {
@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);
}
@@ -772,6 +439,7 @@ public class FO2StructureTreeConverter extends DelegatingFOEventHandler {
@Override
public void startLeader(Leader l) {
+ converters.push(converter);
converter = eventSwallower;
converter.startLeader(l);
super.startLeader(l);
@@ -780,7 +448,7 @@ public class FO2StructureTreeConverter extends DelegatingFOEventHandler {
@Override
public void endLeader(Leader l) {
converter.endLeader(l);
- converter = foToStructureTreeEventAdapter;
+ converter = converters.pop();
super.endLeader(l);
}
@@ -803,9 +471,9 @@ public class FO2StructureTreeConverter extends DelegatingFOEventHandler {
}
@Override
- public void characters(char[] data, int start, int length) {
- converter.characters(data, start, length);
- super.characters(data, start, length);
+ public void characters(FOText foText) {
+ converter.characters(foText);
+ super.characters(foText);
}
@Override
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..b5cd0a5a4
--- /dev/null
+++ b/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java
@@ -0,0 +1,408 @@
+/*
+ * 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/area/AreaTreeParser.java b/src/java/org/apache/fop/area/AreaTreeParser.java
index 545c9015d..29a363495 100644
--- a/src/java/org/apache/fop/area/AreaTreeParser.java
+++ b/src/java/org/apache/fop/area/AreaTreeParser.java
@@ -728,7 +728,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);
@@ -777,7 +776,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);
@@ -870,7 +868,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);
@@ -889,7 +886,6 @@ public class AreaTreeParser {
transferForeignObjects(attributes, image);
setAreaAttributes(attributes, image);
setTraits(attributes, image, SUBSET_COMMON);
- setPtr(image, attributes);
getCurrentViewport().setContent(image);
}
}
@@ -1174,13 +1170,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/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/DelegatingFOEventHandler.java b/src/java/org/apache/fop/fo/DelegatingFOEventHandler.java
index ed85bd1c9..e64106a80 100644
--- a/src/java/org/apache/fop/fo/DelegatingFOEventHandler.java
+++ b/src/java/org/apache/fop/fo/DelegatingFOEventHandler.java
@@ -387,8 +387,8 @@ public abstract class DelegatingFOEventHandler extends FOEventHandler {
}
@Override
- public void characters(char[] data, int start, int length) {
- delegate.characters(data, start, length);
+ public void characters(FOText foText) {
+ delegate.characters(foText);
}
@Override
diff --git a/src/java/org/apache/fop/fo/FOEventHandler.java b/src/java/org/apache/fop/fo/FOEventHandler.java
index 1f3514dea..bed1f3677 100644
--- a/src/java/org/apache/fop/fo/FOEventHandler.java
+++ b/src/java/org/apache/fop/fo/FOEventHandler.java
@@ -88,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
@@ -532,11 +536,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 4946f6d5c..622ff86d4 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,7 +913,7 @@ public abstract class FONode implements Cloneable {
}
- public void setPtr(String ptr) {
+ public void setStructureTreeElement(StructureTreeElement structureTreeElement) {
throw new UnsupportedOperationException();
}
diff --git a/src/java/org/apache/fop/fo/FOText.java b/src/java/org/apache/fop/fo/FOText.java
index 5db11f731..3858cdea9 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,14 @@ public class FOText extends FONode implements CharSequence {
this.charBuffer.rewind();
}
}
+
+ @Override
+ public void setStructureTreeElement(StructureTreeElement structureTreeElement) {
+ this.structureTreeElement = structureTreeElement;
+ }
+
+ 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 b053692d6..ece4e5448 100644
--- a/src/java/org/apache/fop/fo/FOTreeBuilder.java
+++ b/src/java/org/apache/fop/fo/FOTreeBuilder.java
@@ -33,7 +33,7 @@ import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.util.QName;
-import org.apache.fop.accessibility.FO2StructureTreeConverter;
+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;
diff --git a/src/java/org/apache/fop/fo/extensions/InternalElementMapping.java b/src/java/org/apache/fop/fo/extensions/InternalElementMapping.java
index e939841e1..687952d25 100644
--- a/src/java/org/apache/fop/fo/extensions/InternalElementMapping.java
+++ b/src/java/org/apache/fop/fo/extensions/InternalElementMapping.java
@@ -37,11 +37,18 @@ public class InternalElementMapping extends ElementMapping {
/** 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);
}
/**
diff --git a/src/java/org/apache/fop/fo/flow/AbstractGraphics.java b/src/java/org/apache/fop/fo/flow/AbstractGraphics.java
index 67a33d088..2b8fa8a0b 100644
--- a/src/java/org/apache/fop/fo/flow/AbstractGraphics.java
+++ b/src/java/org/apache/fop/fo/flow/AbstractGraphics.java
@@ -19,6 +19,7 @@
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;
@@ -31,7 +32,7 @@ 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">
@@ -40,7 +41,7 @@ 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, CommonAccessibilityHolder {
+ implements GraphicsProperties, StructureTreeElementHolder, CommonAccessibilityHolder {
// The value of properties relevant for fo:instream-foreign-object
// and external-graphics.
@@ -66,7 +67,7 @@ public abstract class AbstractGraphics extends FObj
private int textAlign;
private Length width;
private String altText;
- private String ptr; // used for accessibility
+ private StructureTreeElement structureTreeElement;
// Unused but valid items, commented out for performance:
// private CommonAccessibility commonAccessibility;
// private CommonAural commonAural;
@@ -226,13 +227,13 @@ public abstract class AbstractGraphics extends FObj
}
@Override
- public void setPtr(String ptr) {
- this.ptr = ptr;
+ public void setStructureTreeElement(StructureTreeElement structureTreeElement) {
+ this.structureTreeElement = structureTreeElement;
}
/** {@inheritDoc} */
- public String getPtr() {
- return ptr;
+ public StructureTreeElement getStructureTreeElement() {
+ return structureTreeElement;
}
public String getAltText() {
diff --git a/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java b/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java
index bbb632b29..108896d91 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;
@@ -37,7 +38,7 @@ 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">
@@ -46,7 +47,7 @@ import org.apache.fop.fo.properties.StructurePointerPropertySet;
* <code>fo:page-number-citation-last</code></a> objects.
*/
public abstract class AbstractPageNumberCitation extends FObj
- implements StructurePointerPropertySet, CommonAccessibilityHolder {
+ implements StructureTreeElementHolder, CommonAccessibilityHolder {
// The value of properties relevant for fo:page-number-citation(-last).
private CommonAccessibility commonAccessibility;
@@ -56,7 +57,7 @@ public abstract class AbstractPageNumberCitation extends FObj
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;
@@ -151,13 +152,13 @@ public abstract class AbstractPageNumberCitation extends FObj
}
@Override
- public void setPtr(String ptr) {
- this.ptr = ptr;
+ 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 7bff2d521..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;
@@ -143,13 +144,13 @@ public class BasicLink extends InlineLevel implements StructurePointerPropertySe
}
@Override
- public void setPtr(String ptr) {
- this.ptr = ptr;
+ 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 b1705288a..4e5b6f15f 100644
--- a/src/java/org/apache/fop/fo/flow/Block.java
+++ b/src/java/org/apache/fop/fo/flow/Block.java
@@ -42,13 +42,12 @@ 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
@@ -77,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;
@@ -183,16 +181,6 @@ public class Block extends FObjMixed implements BreakPropertySet, StructurePoint
return breakAfter;
}
- @Override
- public void setPtr(String ptr) {
- this.ptr = ptr;
- }
-
- /** {@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 a33bea53d..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;
@@ -210,13 +211,13 @@ public class Character extends FObj implements StructurePointerPropertySet {
}
@Override
- public void setPtr(String ptr) {
- this.ptr = ptr;
+ 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/Inline.java b/src/java/org/apache/fop/fo/flow/Inline.java
index e458184f4..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;
@@ -147,16 +145,6 @@ public class Inline extends InlineLevel implements StructurePointerPropertySet {
return dominantBaseline;
}
- @Override
- public void setPtr(String ptr) {
- this.ptr = ptr;
- }
-
- /** {@inheritDoc} */
- public String getPtr() {
- return ptr;
- }
-
/** {@inheritDoc} */
public String getLocalName() {
return "inline";
diff --git a/src/java/org/apache/fop/fo/flow/PageNumber.java b/src/java/org/apache/fop/fo/flow/PageNumber.java
index c0373aa7f..0e5ce5071 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;
@@ -36,14 +37,14 @@ 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, CommonAccessibilityHolder {
+ implements StructureTreeElementHolder, CommonAccessibilityHolder {
// The value of properties relevant for fo:page-number.
private CommonAccessibility commonAccessibility;
private CommonBorderPaddingBackground commonBorderPaddingBackground;
@@ -52,7 +53,7 @@ public class PageNumber extends FObj
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 */
@@ -176,13 +177,13 @@ public class PageNumber extends FObj
}
@Override
- public void setPtr(String ptr) {
- this.ptr = ptr;
+ 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/table/TableFObj.java b/src/java/org/apache/fop/fo/flow/table/TableFObj.java
index 0da7b9458..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
@@ -240,16 +238,6 @@ public abstract class TableFObj extends FObj implements StructurePointerProperty
}
}
- @Override
- public void setPtr(String ptr) {
- this.ptr = ptr;
- }
-
- /** {@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/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..da548c23c 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,14 @@ 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/PDFStructElem.java b/src/java/org/apache/fop/pdf/PDFStructElem.java
index 6dfb0dc95..44622638d 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.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");
}
/**
@@ -154,6 +141,63 @@ 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, Writer writer) throws IOException {
+ attachKids();
+ super.writeDictionary(out, writer);
+ }
+
+ /**
+ * 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;
}
+
+ public static class Placeholder extends PDFStructElem {
+
+ @Override
+ public void outputInline(OutputStream out, Writer writer) throws IOException {
+ if (kids != null) {
+ assert kids.size() > 0;
+ for (int i = 0; i < kids.size(); i++) {
+ if (i > 0) {
+ writer.write(' ');
+ }
+ Object obj = kids.get(i);
+ formatObject(obj, out, writer);
+ }
+ }
+ }
+
+ public Placeholder(PDFObject parent, String name) {
+ super(parent, new PDFName(name));
+ }
+ }
+
}
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/IFParser.java b/src/java/org/apache/fop/render/intermediate/IFParser.java
index 8f0bb88ec..1a384c6e9 100644
--- a/src/java/org/apache/fop/render/intermediate/IFParser.java
+++ b/src/java/org/apache/fop/render/intermediate/IFParser.java
@@ -49,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.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;
@@ -158,6 +160,9 @@ public class IFParser implements IFConstants {
private Attributes pageSequenceAttributes;
+ private Map<String, StructureTreeElement> structureTreeElements =
+ new HashMap<String, StructureTreeElement>();
+
private final class StructureTreeHandler extends DefaultHandler {
private final StructureTreeEventHandler structureTreeEventHandler;
@@ -177,7 +182,23 @@ public class IFParser implements IFConstants {
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if (!"structure-tree".equals(localName)) {
- structureTreeEventHandler.startNode(localName, attributes);
+ 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);
+ }
}
}
@@ -225,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 {
@@ -276,7 +289,7 @@ 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++;
@@ -604,9 +617,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() {
@@ -701,7 +714,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));
@@ -715,7 +728,7 @@ public class IFParser implements IFConstants {
painter.drawImage(uri, new Rectangle(x, y, width, height));
}
resetForeignAttributes();
- resetStructurePointer();
+ resetStructureTreeElement();
inForeignObject = false;
}
@@ -769,13 +782,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 d217646f6..a2d8a0bea 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;
@@ -629,12 +630,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} */
@@ -851,8 +852,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);
@@ -912,7 +914,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();
@@ -956,7 +957,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);
}
@@ -1009,8 +1012,8 @@ 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 a4431b972..c6bf9af9e 100644
--- a/src/java/org/apache/fop/render/intermediate/IFSerializer.java
+++ b/src/java/org/apache/fop/render/intermediate/IFSerializer.java
@@ -38,9 +38,11 @@ import org.apache.xmlgraphics.util.QName;
import org.apache.xmlgraphics.util.XMLizable;
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;
@@ -163,6 +165,7 @@ 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);
@@ -439,7 +442,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);
@@ -467,7 +470,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);
@@ -582,7 +585,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);
@@ -682,13 +685,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.id);
}
}
+ 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)) {
@@ -773,7 +785,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()).id);
}
try {
handler.startElement(DocumentNavigationExtensionConstants.LINK, atts);
diff --git a/src/java/org/apache/fop/render/intermediate/IFStructureTreeBuilder.java b/src/java/org/apache/fop/render/intermediate/IFStructureTreeBuilder.java
index 66457681f..b78ae35bc 100644
--- a/src/java/org/apache/fop/render/intermediate/IFStructureTreeBuilder.java
+++ b/src/java/org/apache/fop/render/intermediate/IFStructureTreeBuilder.java
@@ -26,10 +26,14 @@ 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
@@ -37,42 +41,17 @@ import org.apache.fop.accessibility.StructureTreeEventHandler;
*/
final class IFStructureTreeBuilder implements StructureTreeEventHandler {
- private StructureTreeEventHandler delegate;
-
- private final List<SAXEventRecorder> pageSequenceEventRecorders = new ArrayList<SAXEventRecorder>();
-
- /**
- * 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);
- }
-
- /** {@inheritDoc} */
- public void startPageSequence(Locale locale) {
- SAXEventRecorder eventRecorder = new SAXEventRecorder();
- pageSequenceEventRecorders.add(eventRecorder);
- delegate = StructureTree2SAXEventAdapter.newInstance(eventRecorder);
- delegate.startPageSequence(locale);
- }
+ static final class IFStructureTreeElement implements StructureTreeElement {
- /** {@inheritDoc} */
- public void endPageSequence() {
- delegate.endPageSequence();
- }
+ final String id;
- /** {@inheritDoc} */
- public void startNode(String name, Attributes attributes) {
- delegate.startNode(name, attributes);
- }
+ IFStructureTreeElement() {
+ this.id = null;
+ }
- /** {@inheritDoc} */
- public void endNode(String name) {
- delegate.endNode(name);
+ IFStructureTreeElement(String id) {
+ this.id = id;
+ }
}
/** A SAX handler that records events to replay them later. */
@@ -159,22 +138,22 @@ final class IFStructureTreeBuilder implements StructureTreeEventHandler {
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.
@@ -187,4 +166,69 @@ final class IFStructureTreeBuilder implements StructureTreeEventHandler {
}
}
}
+
+ 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..693497b73 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/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 d49ef4a3e..88a6e9c22 100644
--- a/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java
+++ b/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java
@@ -19,9 +19,7 @@
package org.apache.fop.render.pdf;
-import java.util.HashMap;
import java.util.Locale;
-import java.util.Map;
import org.apache.fop.pdf.PDFArray;
import org.apache.fop.pdf.PDFDictionary;
@@ -47,11 +45,6 @@ class PDFLogicalStructureHandler {
private final PDFDocument pdfDoc;
- /**
- * Map of references to the corresponding structure elements.
- */
- private final Map<String, PDFStructElem> structTreeMap = new HashMap<String, PDFStructElem>();
-
private final PDFParentTree parentTree = new PDFParentTree();
private int parentTreeKey;
@@ -151,100 +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);
- }
-
- void addStructurePointer(String ptr, PDFStructElem structElem) {
- structTreeMap.put(ptr, structElem);
+ 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
index 8ec10b209..3b5b00c33 100644
--- a/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java
+++ b/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java
@@ -24,10 +24,10 @@ 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.fo.extensions.InternalElementMapping;
import org.apache.fop.pdf.PDFFactory;
import org.apache.fop.pdf.PDFStructElem;
@@ -61,33 +61,64 @@ class PDFStructureTreeBuilder implements StructureTreeEventHandler {
public void endPageSequence() {
}
- public void startNode(String name, Attributes attributes) {
+ public StructureTreeElement startNode(String name, Attributes attributes) {
PDFStructElem parent = ancestors.getFirst();
String role = attributes.getValue("role");
- PDFStructElem created = pdfFactory.makeStructureElement(
- FOToPDFRoleMap.mapFormattingObject(name, role, parent,
- eventBroadcaster), parent);
- if (ancestors.size() <= 2) { // TODO remove
- parent.addKid(created);
- }
- String ptr = attributes.getValue(InternalElementMapping.URI, "ptr");
- if (ptr != null) {
- logicalStructureHandler.addStructurePointer(ptr, created);
+ 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 void endImageNode(String name) {
+ removeFirstAncestor();
+ }
- if (name.equals("external-graphic") || name.equals("instream-foreign-object")) {
- String altTextNode = attributes.getValue(ExtensionElementMapping.URI, "alt-text");
- if (altTextNode != null) {
- created.put("Alt", altTextNode);
- } else {
- created.put("Alt", "No alternate text specified");
- }
+ 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;
}
- public void endNode(String name) {
- ancestors.removeFirst();
+ public void endReferencedNode(String name) {
+ removeFirstAncestor();
}
}
diff --git a/src/java/org/apache/fop/render/rtf/RTFHandler.java b/src/java/org/apache/fop/render/rtf/RTFHandler.java
index 8878b5d24..a3e3db461 100644
--- a/src/java/org/apache/fop/render/rtf/RTFHandler.java
+++ b/src/java/org/apache/fop/render/rtf/RTFHandler.java
@@ -117,13 +117,13 @@ import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfFootnote;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfHyperLink;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfList;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfListItem;
+import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfListItem.RtfListItemLabel;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfPage;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfSection;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTable;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTableCell;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTableRow;
import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTextrun;
-import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfListItem.RtfListItemLabel;
import org.apache.fop.render.rtf.rtflib.tools.BuilderContext;
import org.apache.fop.render.rtf.rtflib.tools.PercentContext;
import org.apache.fop.render.rtf.rtflib.tools.TableContext;
@@ -1362,11 +1362,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 +1379,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);
@@ -1558,7 +1556,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) {
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/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.pdf b/test/accessibility/pdf/background-image_jpg_repeat.pdf
index 97b304c53..221761757 100644
--- a/test/accessibility/pdf/background-image_jpg_repeat.pdf
+++ b/test/accessibility/pdf/background-image_jpg_repeat.pdf
Binary files differ
diff --git a/test/accessibility/pdf/background-image_jpg_single.pdf b/test/accessibility/pdf/background-image_jpg_single.pdf
index e1d7f9340..232afdd05 100644
--- a/test/accessibility/pdf/background-image_jpg_single.pdf
+++ b/test/accessibility/pdf/background-image_jpg_single.pdf
Binary files differ
diff --git a/test/accessibility/pdf/background-image_png_repeat.pdf b/test/accessibility/pdf/background-image_png_repeat.pdf
index 9f5e7ff12..52da4020a 100644
--- a/test/accessibility/pdf/background-image_png_repeat.pdf
+++ b/test/accessibility/pdf/background-image_png_repeat.pdf
Binary files differ
diff --git a/test/accessibility/pdf/background-image_png_single.pdf b/test/accessibility/pdf/background-image_png_single.pdf
index 81156e18d..356e4885c 100644
--- a/test/accessibility/pdf/background-image_png_single.pdf
+++ b/test/accessibility/pdf/background-image_png_single.pdf
Binary files differ
diff --git a/test/accessibility/pdf/background-image_svg_repeat.pdf b/test/accessibility/pdf/background-image_svg_repeat.pdf
index 0e438958d..0bce2404d 100644
--- a/test/accessibility/pdf/background-image_svg_repeat.pdf
+++ b/test/accessibility/pdf/background-image_svg_repeat.pdf
Binary files differ
diff --git a/test/accessibility/pdf/background-image_svg_single.pdf b/test/accessibility/pdf/background-image_svg_single.pdf
index a46b6df38..3e4afcdcf 100644
--- a/test/accessibility/pdf/background-image_svg_single.pdf
+++ b/test/accessibility/pdf/background-image_svg_single.pdf
Binary files differ
diff --git a/test/accessibility/pdf/complete.pdf b/test/accessibility/pdf/complete.pdf
index a42bb2a97..cffb9e2cb 100644
--- a/test/accessibility/pdf/complete.pdf
+++ b/test/accessibility/pdf/complete.pdf
Binary files differ
diff --git a/test/accessibility/pdf/image_jpg.pdf b/test/accessibility/pdf/image_jpg.pdf
index 6b70c268d..cb004bbd2 100644
--- a/test/accessibility/pdf/image_jpg.pdf
+++ b/test/accessibility/pdf/image_jpg.pdf
Binary files differ
diff --git a/test/accessibility/pdf/image_png.pdf b/test/accessibility/pdf/image_png.pdf
index d63db6708..c3289374f 100644
--- a/test/accessibility/pdf/image_png.pdf
+++ b/test/accessibility/pdf/image_png.pdf
Binary files differ
diff --git a/test/accessibility/pdf/image_svg.pdf b/test/accessibility/pdf/image_svg.pdf
index 94720f564..c3fce5b0e 100644
--- a/test/accessibility/pdf/image_svg.pdf
+++ b/test/accessibility/pdf/image_svg.pdf
Binary files differ
diff --git a/test/accessibility/pdf/image_wmf.pdf b/test/accessibility/pdf/image_wmf.pdf
index 4b6eb0827..b9ec8c55a 100644
--- a/test/accessibility/pdf/image_wmf.pdf
+++ b/test/accessibility/pdf/image_wmf.pdf
Binary files differ
diff --git a/test/accessibility/pdf/leader.pdf b/test/accessibility/pdf/leader.pdf
index 4a6c25253..c7432e751 100644
--- a/test/accessibility/pdf/leader.pdf
+++ b/test/accessibility/pdf/leader.pdf
Binary files differ
diff --git a/test/accessibility/pdf/links.pdf b/test/accessibility/pdf/links.pdf
index b8d4e3be3..91d7c2592 100644
--- a/test/accessibility/pdf/links.pdf
+++ b/test/accessibility/pdf/links.pdf
Binary files differ
diff --git a/test/accessibility/pdf/role.pdf b/test/accessibility/pdf/role.pdf
index ec5d5f536..acb435027 100644
--- a/test/accessibility/pdf/role.pdf
+++ b/test/accessibility/pdf/role.pdf
Binary files differ
diff --git a/test/accessibility/pdf/role_non-standard.pdf b/test/accessibility/pdf/role_non-standard.pdf
index d90693066..fcf614ed1 100644
--- a/test/accessibility/pdf/role_non-standard.pdf
+++ b/test/accessibility/pdf/role_non-standard.pdf
Binary files differ
diff --git a/test/accessibility/pdf/text_1.pdf b/test/accessibility/pdf/text_1.pdf
index 0b1e1ee9f..596419c9d 100644
--- a/test/accessibility/pdf/text_1.pdf
+++ b/test/accessibility/pdf/text_1.pdf
Binary files differ
diff --git a/test/accessibility/pdf/text_2.pdf b/test/accessibility/pdf/text_2.pdf
index 3330cc902..19fff21a4 100644
--- a/test/accessibility/pdf/text_2.pdf
+++ b/test/accessibility/pdf/text_2.pdf
Binary files differ
diff --git a/test/accessibility/pdf/text_font-embedding.pdf b/test/accessibility/pdf/text_font-embedding.pdf
index a268dbb63..0288449d5 100644
--- a/test/accessibility/pdf/text_font-embedding.pdf
+++ b/test/accessibility/pdf/text_font-embedding.pdf
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/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/FO2StructureTreeConverterTestCase.java b/test/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverterTestCase.java
index f8719edd6..9c53bdde3 100644
--- a/test/java/org/apache/fop/accessibility/FO2StructureTreeConverterTestCase.java
+++ b/test/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverterTestCase.java
@@ -17,10 +17,12 @@
/* $Id$ */
-package org.apache.fop.accessibility;
+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;
@@ -34,18 +36,17 @@ 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.custommonkey.xmlunit.Difference;
-import org.custommonkey.xmlunit.DifferenceConstants;
-import org.custommonkey.xmlunit.DifferenceListener;
import org.junit.Test;
import org.w3c.dom.Document;
-import org.w3c.dom.Node;
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;
@@ -56,54 +57,75 @@ import org.apache.fop.fotreetest.DummyFOEventHandler;
public class FO2StructureTreeConverterTestCase {
- private static class IgnoringPtrDifferenceListener implements DifferenceListener {
-
- public int differenceFound(Difference difference) {
- switch (difference.getId()) {
- case DifferenceConstants.ELEMENT_NUM_ATTRIBUTES_ID:
- return RETURN_IGNORE_DIFFERENCE_NODES_SIMILAR;
- case DifferenceConstants.ATTR_NAME_NOT_FOUND_ID:
- String additionalAttribute = difference.getTestNodeDetail().getValue();
- if (additionalAttribute.equals("ptr")) {
- return RETURN_IGNORE_DIFFERENCE_NODES_SIMILAR;
- } else {
- return RETURN_ACCEPT_DIFFERENCE;
- }
- default:
- return RETURN_ACCEPT_DIFFERENCE;
- }
- }
+ private interface FOLoader {
- public void skippedComparison(Node control, Node test) {
- throw new UnsupportedOperationException("Not implemented");
- }
+ 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 testConverter() throws Exception {
+ 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.similar());
+ assertTrue(diff.toString(), diff.identical());
}
- private static DOMResult loadExpectedStructureTree() {
+ private DOMResult loadExpectedStructureTree() {
DOMResult expectedStructureTree = new DOMResult();
- runXSLT(getXsltInputStream(), getFoInputStream(), expectedStructureTree);
+ InputStream xslt = getResource("fo2StructureTree.xsl");
+ runXSLT(xslt, foLoader.getFoInputStream(), expectedStructureTree);
return expectedStructureTree;
}
- private static InputStream getXsltInputStream() {
- return FO2StructureTreeConverterTestCase.class.getResourceAsStream("foToIfStructureTree.xsl");
- }
-
- private static InputStream getFoInputStream() {
- return FO2StructureTreeConverterTestCase.class.getResourceAsStream(
- "/org/apache/fop/fo/complete_document.fo");
- }
-
private static void runXSLT(InputStream xslt, InputStream doc, Result result) {
Source fo = new StreamSource(doc);
try {
@@ -128,15 +150,15 @@ public class FO2StructureTreeConverterTestCase {
}
}
- private static DOMResult buildActualStructureTree() throws Exception {
+ private DOMResult buildActualStructureTree() throws Exception {
DOMResult actualStructureTree = new DOMResult();
- createStructureTreeFromDocument(getFoInputStream(), actualStructureTree);
+ createStructureTreeFromDocument(foLoader.getFoInputStream(), actualStructureTree);
return actualStructureTree;
}
private static void createStructureTreeFromDocument(InputStream foInputStream,
- DOMResult domResult) throws Exception {
- TransformerHandler tHandler = createTransformerHandler(domResult);
+ Result result) throws Exception {
+ TransformerHandler tHandler = createTransformerHandler(result);
startStructureTreeSequence(tHandler);
StructureTreeEventHandler structureTreeEventHandler
= StructureTree2SAXEventAdapter.newInstance(tHandler);
@@ -146,7 +168,7 @@ public class FO2StructureTreeConverterTestCase {
endStructureTreeSequence(tHandler);
}
- private static TransformerHandler createTransformerHandler(DOMResult domResult)
+ private static TransformerHandler createTransformerHandler(Result domResult)
throws TransformerConfigurationException, TransformerFactoryConfigurationError {
SAXTransformerFactory factory = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
TransformerHandler transformerHandler = factory.newTransformerHandler();
@@ -192,7 +214,6 @@ public class FO2StructureTreeConverterTestCase {
private static Diff createDiff(DOMResult expected, DOMResult actual) {
Diff diff = new Diff(getDocument(expected), getDocument(actual));
- diff.overrideDifferenceListener(new IgnoringPtrDifferenceListener());
return diff;
}
diff --git a/test/java/org/apache/fop/accessibility/fo2StructureTree.xsl b/test/java/org/apache/fop/accessibility/fo/fo2StructureTree.xsl
index 5c9c5615c..ce326f3b1 100644
--- a/test/java/org/apache/fop/accessibility/fo2StructureTree.xsl
+++ b/test/java/org/apache/fop/accessibility/fo/fo2StructureTree.xsl
@@ -69,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>
@@ -110,7 +118,18 @@
<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/render/intermediate/IFStructureTreeBuilderTestCase.java b/test/java/org/apache/fop/render/intermediate/IFStructureTreeBuilderTestCase.java
index d7db7db7f..65c6b25a6 100644
--- a/test/java/org/apache/fop/render/intermediate/IFStructureTreeBuilderTestCase.java
+++ b/test/java/org/apache/fop/render/intermediate/IFStructureTreeBuilderTestCase.java
@@ -85,7 +85,7 @@ public class IFStructureTreeBuilderTestCase {
@Test
public void startNode() throws Exception {
- final String[] attributes = {"ptr", "1"};
+ final String[] attributes = {"struct-id", "1"};
final String nodeName = "block";
final ContentHandler handler = mock(ContentHandler.class);