aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache/fop
diff options
context:
space:
mode:
authorVincent Hennebert <vhennebert@apache.org>2011-11-24 17:15:28 +0000
committerVincent Hennebert <vhennebert@apache.org>2011-11-24 17:15:28 +0000
commitc6fb066a02573904f7ca404605f14c800adf80c5 (patch)
treed73a722e23ae74124b1bcb691d0e6f0b2f0af32f /src/java/org/apache/fop
parentb073a605e44760bcb7add72968a3a2f78cf06d97 (diff)
downloadxmlgraphics-fop-c6fb066a02573904f7ca404605f14c800adf80c5.tar.gz
xmlgraphics-fop-c6fb066a02573904f7ca404605f14c800adf80c5.zip
Removed the DOM representation of the structure tree.
The structure tree is now directly converted into corresponding PDF objects. When going the IF route, the structure tree is stored in the form of SAX events that will be re-played when it's time to stream them into the output. This may still change. * Extracted RFC3066 methods from XMLUtil into new LanguageTags class that can be re-used in a non-XML context. * Dropped support for accessibility in the old Area Tree XML. * Added support for the xml:lang property on fo:root, so that the global language can be set for the document without retrieving the language from the first page-sequence. * Renamed StructureTreeBuilder into more appropriate StructureTreeEventHandler (same for applicable sub-classes) * Renamed StructureTreeBuildingFOEventHandler into FO2StructureTreeConverter and added test case * Added test cases for classes in the StructureTreeEventHandler hierarchy git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_ImproveAccessibility@1205935 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java/org/apache/fop')
-rw-r--r--src/java/org/apache/fop/accessibility/DummyStructureTreeEventHandler.java52
-rw-r--r--src/java/org/apache/fop/accessibility/FO2StructureTreeConverter.java (renamed from src/java/org/apache/fop/accessibility/StructureTreeBuildingFOEventHandler.java)227
-rw-r--r--src/java/org/apache/fop/accessibility/StructureTree.java102
-rw-r--r--src/java/org/apache/fop/accessibility/StructureTree2SAXEventAdapter.java104
-rw-r--r--src/java/org/apache/fop/accessibility/StructureTreeBuilder.java95
-rw-r--r--src/java/org/apache/fop/accessibility/StructureTreeEventHandler.java56
-rw-r--r--src/java/org/apache/fop/apps/FOUserAgent.java30
-rw-r--r--src/java/org/apache/fop/area/AreaTreeHandler.java9
-rw-r--r--src/java/org/apache/fop/area/AreaTreeModel.java8
-rw-r--r--src/java/org/apache/fop/area/AreaTreeParser.java56
-rw-r--r--src/java/org/apache/fop/area/RenderPagesModel.java6
-rw-r--r--src/java/org/apache/fop/fo/DelegatingFOEventHandler.java11
-rw-r--r--src/java/org/apache/fop/fo/FOElementMapping.java5
-rw-r--r--src/java/org/apache/fop/fo/FOEventHandler.java7
-rw-r--r--src/java/org/apache/fop/fo/FOTreeBuilder.java8
-rw-r--r--src/java/org/apache/fop/fo/pagination/Root.java26
-rw-r--r--src/java/org/apache/fop/pdf/PDFDocument.java19
-rw-r--r--src/java/org/apache/fop/pdf/PDFProfile.java6
-rw-r--r--src/java/org/apache/fop/pdf/PDFRoot.java14
-rw-r--r--src/java/org/apache/fop/pdf/PDFStructElem.java4
-rw-r--r--src/java/org/apache/fop/render/AbstractRenderer.java7
-rw-r--r--src/java/org/apache/fop/render/Renderer.java7
-rw-r--r--src/java/org/apache/fop/render/intermediate/AbstractIFDocumentHandler.java17
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFConstants.java1
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFDocumentHandler.java16
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFParser.java68
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFRenderer.java14
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFSerializer.java48
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFSerializerMaker.java3
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFStructureTreeBuilder.java190
-rw-r--r--src/java/org/apache/fop/render/intermediate/util/IFDocumentHandlerProxy.java16
-rw-r--r--src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java35
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java59
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFDocumentHandlerMaker.java3
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java72
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java93
-rw-r--r--src/java/org/apache/fop/render/xml/XMLRenderer.java31
-rw-r--r--src/java/org/apache/fop/util/LanguageTags.java66
-rw-r--r--src/java/org/apache/fop/util/XMLUtil.java36
39 files changed, 994 insertions, 633 deletions
diff --git a/src/java/org/apache/fop/accessibility/DummyStructureTreeEventHandler.java b/src/java/org/apache/fop/accessibility/DummyStructureTreeEventHandler.java
new file mode 100644
index 000000000..80a011bab
--- /dev/null
+++ b/src/java/org/apache/fop/accessibility/DummyStructureTreeEventHandler.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.accessibility;
+
+import java.util.Locale;
+
+import org.xml.sax.Attributes;
+
+/**
+ * This implementation ignores all structure tree events.
+ */
+public final class DummyStructureTreeEventHandler implements StructureTreeEventHandler {
+
+ /** The singleton instance of this class. */
+ public static final StructureTreeEventHandler INSTANCE = new DummyStructureTreeEventHandler();
+
+ private DummyStructureTreeEventHandler() { }
+
+ /** {@inheritDoc} */
+ public void startPageSequence(Locale locale) {
+ }
+
+ /** {@inheritDoc} */
+ public void startNode(String name, Attributes attributes) {
+ }
+
+ /** {@inheritDoc} */
+ public void endNode(String name) {
+ }
+
+ /** {@inheritDoc} */
+ public void endPageSequence() {
+ }
+
+}
diff --git a/src/java/org/apache/fop/accessibility/StructureTreeBuildingFOEventHandler.java b/src/java/org/apache/fop/accessibility/FO2StructureTreeConverter.java
index e3f946810..e6d0193b9 100644
--- a/src/java/org/apache/fop/accessibility/StructureTreeBuildingFOEventHandler.java
+++ b/src/java/org/apache/fop/accessibility/FO2StructureTreeConverter.java
@@ -19,11 +19,7 @@
package org.apache.fop.accessibility;
-import javax.xml.transform.TransformerConfigurationException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMResult;
-import javax.xml.transform.sax.SAXTransformerFactory;
-import javax.xml.transform.sax.TransformerHandler;
+import java.util.Locale;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
@@ -63,34 +59,32 @@ import org.apache.fop.fo.flow.table.TableHeader;
import org.apache.fop.fo.flow.table.TableRow;
import org.apache.fop.fo.pagination.Flow;
import org.apache.fop.fo.pagination.PageSequence;
+import org.apache.fop.fo.pagination.Root;
import org.apache.fop.fo.pagination.StaticContent;
import org.apache.fop.fo.properties.CommonAccessibilityHolder;
import org.apache.fop.util.XMLUtil;
/**
- * A class that builds the document's structure tree.
+ * Allows to create the structure tree of an FO document, by converting FO
+ * events into appropriate structure tree events.
*/
-public class StructureTreeBuildingFOEventHandler extends DelegatingFOEventHandler {
+public class FO2StructureTreeConverter extends DelegatingFOEventHandler {
private int idCounter;
- private final StructureTree structureTree;
+ /** Delegates to either {@link #foToStructureTreeEventAdapter} or {@link #eventSwallower}. */
+ private FOEventHandler converter;
- private TransformerHandler structureTreeDOMBuilder;
-
- private DOMResult result;
-
- /** Delegates to either {@link #actualStructureTreeBuilder} or {@link #eventSwallower}. */
- private FOEventHandler structureTreeBuilder;
-
- private FOEventHandler actualStructureTreeBuilder;
+ private final FOEventHandler foToStructureTreeEventAdapter;
/** The descendants of some elements like fo:leader must be ignored. */
private final FOEventHandler eventSwallower;
- private final class StructureTreeBuilder extends FOEventHandler {
+ private final StructureTreeEventHandler structureTreeEventHandler;
+
+ private final class FOToStructureTreeEventAdapter extends FOEventHandler {
- public StructureTreeBuilder(FOUserAgent foUserAgent) {
+ public FOToStructureTreeEventAdapter(FOUserAgent foUserAgent) {
super(foUserAgent);
}
@@ -104,33 +98,20 @@ public class StructureTreeBuildingFOEventHandler extends DelegatingFOEventHandle
@Override
public void startPageSequence(PageSequence pageSeq) {
- SAXTransformerFactory transformerFactory =
- (SAXTransformerFactory) TransformerFactory.newInstance();
- try {
- structureTreeDOMBuilder = transformerFactory.newTransformerHandler();
- } catch (TransformerConfigurationException e) {
- throw new RuntimeException(e);
+ Locale locale = null;
+ if (pageSeq.getLanguage() != null) {
+ if (pageSeq.getCountry() != null) {
+ locale = new Locale(pageSeq.getLanguage(), pageSeq.getCountry());
+ } else {
+ locale = new Locale(pageSeq.getLanguage());
+ }
}
- result = new DOMResult();
- structureTreeDOMBuilder.setResult(result);
- try {
- structureTreeDOMBuilder.startDocument();
- } catch (SAXException e) {
- throw new RuntimeException(e);
- }
- startElement(pageSeq);
+ structureTreeEventHandler.startPageSequence(locale);
}
@Override
public void endPageSequence(PageSequence pageSeq) {
- endElement(pageSeq);
- try {
- structureTreeDOMBuilder.endDocument();
- } catch (SAXException e) {
- throw new RuntimeException(e);
- }
- structureTree.addPageSequenceStructure(
- result.getNode().getFirstChild().getChildNodes());
+ structureTreeEventHandler.endPageSequence();
}
@Override
@@ -381,6 +362,7 @@ public class StructureTreeBuildingFOEventHandler extends DelegatingFOEventHandle
endElement(c);
}
+
private void startElement(FONode node) {
startElement(node, new AttributesImpl());
}
@@ -409,13 +391,7 @@ public class StructureTreeBuildingFOEventHandler extends DelegatingFOEventHandle
if (node instanceof CommonAccessibilityHolder) {
addRole((CommonAccessibilityHolder) node, attributes);
}
- try {
- structureTreeDOMBuilder.startElement(node.getNamespaceURI(), localName,
- node.getNormalNamespacePrefix() + ":" + localName,
- attributes);
- } catch (SAXException e) {
- throw new RuntimeException(e);
- }
+ structureTreeEventHandler.startNode(localName, attributes);
}
private void addNoNamespaceAttribute(AttributesImpl attributes, String name, String value) {
@@ -438,12 +414,7 @@ public class StructureTreeBuildingFOEventHandler extends DelegatingFOEventHandle
private void endElement(FONode node) {
String localName = node.getLocalName();
- try {
- structureTreeDOMBuilder.endElement(node.getNamespaceURI(), localName,
- node.getNormalNamespacePrefix() + ":" + localName);
- } catch (SAXException e) {
- throw new RuntimeException(e);
- }
+ structureTreeEventHandler.endNode(localName);
}
}
@@ -451,389 +422,401 @@ public class StructureTreeBuildingFOEventHandler extends DelegatingFOEventHandle
/**
* Creates a new instance.
*
- * @param structureTree the object that will hold the structure tree
+ * @param structureTreeEventHandler the object that will hold the structure tree
* @param delegate the FO event handler that must be wrapped by this instance
*/
- public StructureTreeBuildingFOEventHandler(StructureTree structureTree,
+ public FO2StructureTreeConverter(StructureTreeEventHandler structureTreeEventHandler,
FOEventHandler delegate) {
super(delegate);
- this.structureTree = structureTree;
- this.actualStructureTreeBuilder = new StructureTreeBuilder(foUserAgent);
- this.structureTreeBuilder = actualStructureTreeBuilder;
+ this.structureTreeEventHandler = structureTreeEventHandler;
+ this.foToStructureTreeEventAdapter = new FOToStructureTreeEventAdapter(foUserAgent);
+ this.converter = foToStructureTreeEventAdapter;
this.eventSwallower = new FOEventHandler(foUserAgent) { };
}
@Override
public void startDocument() throws SAXException {
- structureTreeBuilder.startDocument();
+ converter.startDocument();
super.startDocument();
}
@Override
public void endDocument() throws SAXException {
- structureTreeBuilder.endDocument();
+ converter.endDocument();
super.endDocument();
}
@Override
+ public void startRoot(Root root) {
+ converter.startRoot(root);
+ super.startRoot(root);
+ }
+
+ @Override
+ public void endRoot(Root root) {
+ converter.endRoot(root);
+ super.endRoot(root);
+ }
+
+ @Override
public void startPageSequence(PageSequence pageSeq) {
- structureTreeBuilder.startPageSequence(pageSeq);
+ converter.startPageSequence(pageSeq);
super.startPageSequence(pageSeq);
}
@Override
public void endPageSequence(PageSequence pageSeq) {
- structureTreeBuilder.endPageSequence(pageSeq);
+ converter.endPageSequence(pageSeq);
super.endPageSequence(pageSeq);
}
@Override
public void startPageNumber(PageNumber pagenum) {
- structureTreeBuilder.startPageNumber(pagenum);
+ converter.startPageNumber(pagenum);
super.startPageNumber(pagenum);
}
@Override
public void endPageNumber(PageNumber pagenum) {
- structureTreeBuilder.endPageNumber(pagenum);
+ converter.endPageNumber(pagenum);
super.endPageNumber(pagenum);
}
@Override
public void startPageNumberCitation(PageNumberCitation pageCite) {
- structureTreeBuilder.startPageNumberCitation(pageCite);
+ converter.startPageNumberCitation(pageCite);
super.startPageNumberCitation(pageCite);
}
@Override
public void endPageNumberCitation(PageNumberCitation pageCite) {
- structureTreeBuilder.endPageNumberCitation(pageCite);
+ converter.endPageNumberCitation(pageCite);
super.endPageNumberCitation(pageCite);
}
@Override
public void startPageNumberCitationLast(PageNumberCitationLast pageLast) {
- structureTreeBuilder.startPageNumberCitationLast(pageLast);
+ converter.startPageNumberCitationLast(pageLast);
super.startPageNumberCitationLast(pageLast);
}
@Override
public void endPageNumberCitationLast(PageNumberCitationLast pageLast) {
- structureTreeBuilder.endPageNumberCitationLast(pageLast);
+ converter.endPageNumberCitationLast(pageLast);
super.endPageNumberCitationLast(pageLast);
}
@Override
public void startFlow(Flow fl) {
- structureTreeBuilder.startFlow(fl);
+ converter.startFlow(fl);
super.startFlow(fl);
}
@Override
public void endFlow(Flow fl) {
- structureTreeBuilder.endFlow(fl);
+ converter.endFlow(fl);
super.endFlow(fl);
}
@Override
public void startBlock(Block bl) {
- structureTreeBuilder.startBlock(bl);
+ converter.startBlock(bl);
super.startBlock(bl);
}
@Override
public void endBlock(Block bl) {
- structureTreeBuilder.endBlock(bl);
+ converter.endBlock(bl);
super.endBlock(bl);
}
@Override
public void startBlockContainer(BlockContainer blc) {
- structureTreeBuilder.startBlockContainer(blc);
+ converter.startBlockContainer(blc);
super.startBlockContainer(blc);
}
@Override
public void endBlockContainer(BlockContainer blc) {
- structureTreeBuilder.endBlockContainer(blc);
+ converter.endBlockContainer(blc);
super.endBlockContainer(blc);
}
@Override
public void startInline(Inline inl) {
- structureTreeBuilder.startInline(inl);
+ converter.startInline(inl);
super.startInline(inl);
}
@Override
public void endInline(Inline inl) {
- structureTreeBuilder.endInline(inl);
+ converter.endInline(inl);
super.endInline(inl);
}
@Override
public void startTable(Table tbl) {
- structureTreeBuilder.startTable(tbl);
+ converter.startTable(tbl);
super.startTable(tbl);
}
@Override
public void endTable(Table tbl) {
- structureTreeBuilder.endTable(tbl);
+ converter.endTable(tbl);
super.endTable(tbl);
}
@Override
public void startColumn(TableColumn tc) {
- structureTreeBuilder.startColumn(tc);
+ converter.startColumn(tc);
super.startColumn(tc);
}
@Override
public void endColumn(TableColumn tc) {
- structureTreeBuilder.endColumn(tc);
+ converter.endColumn(tc);
super.endColumn(tc);
}
@Override
public void startHeader(TableHeader header) {
- structureTreeBuilder.startHeader(header);
+ converter.startHeader(header);
super.startHeader(header);
}
@Override
public void endHeader(TableHeader header) {
- structureTreeBuilder.endHeader(header);
+ converter.endHeader(header);
super.endHeader(header);
}
@Override
public void startFooter(TableFooter footer) {
- structureTreeBuilder.startFooter(footer);
+ converter.startFooter(footer);
super.startFooter(footer);
}
@Override
public void endFooter(TableFooter footer) {
- structureTreeBuilder.endFooter(footer);
+ converter.endFooter(footer);
super.endFooter(footer);
}
@Override
public void startBody(TableBody body) {
- structureTreeBuilder.startBody(body);
+ converter.startBody(body);
super.startBody(body);
}
@Override
public void endBody(TableBody body) {
- structureTreeBuilder.endBody(body);
+ converter.endBody(body);
super.endBody(body);
}
@Override
public void startRow(TableRow tr) {
- structureTreeBuilder.startRow(tr);
+ converter.startRow(tr);
super.startRow(tr);
}
@Override
public void endRow(TableRow tr) {
- structureTreeBuilder.endRow(tr);
+ converter.endRow(tr);
super.endRow(tr);
}
@Override
public void startCell(TableCell tc) {
- structureTreeBuilder.startCell(tc);
+ converter.startCell(tc);
super.startCell(tc);
}
@Override
public void endCell(TableCell tc) {
- structureTreeBuilder.endCell(tc);
+ converter.endCell(tc);
super.endCell(tc);
}
@Override
public void startList(ListBlock lb) {
- structureTreeBuilder.startList(lb);
+ converter.startList(lb);
super.startList(lb);
}
@Override
public void endList(ListBlock lb) {
- structureTreeBuilder.endList(lb);
+ converter.endList(lb);
super.endList(lb);
}
@Override
public void startListItem(ListItem li) {
- structureTreeBuilder.startListItem(li);
+ converter.startListItem(li);
super.startListItem(li);
}
@Override
public void endListItem(ListItem li) {
- structureTreeBuilder.endListItem(li);
+ converter.endListItem(li);
super.endListItem(li);
}
@Override
public void startListLabel(ListItemLabel listItemLabel) {
- structureTreeBuilder.startListLabel(listItemLabel);
+ converter.startListLabel(listItemLabel);
super.startListLabel(listItemLabel);
}
@Override
public void endListLabel(ListItemLabel listItemLabel) {
- structureTreeBuilder.endListLabel(listItemLabel);
+ converter.endListLabel(listItemLabel);
super.endListLabel(listItemLabel);
}
@Override
public void startListBody(ListItemBody listItemBody) {
- structureTreeBuilder.startListBody(listItemBody);
+ converter.startListBody(listItemBody);
super.startListBody(listItemBody);
}
@Override
public void endListBody(ListItemBody listItemBody) {
- structureTreeBuilder.endListBody(listItemBody);
+ converter.endListBody(listItemBody);
super.endListBody(listItemBody);
}
@Override
public void startStatic(StaticContent staticContent) {
- structureTreeBuilder.startStatic(staticContent);
+ converter.startStatic(staticContent);
super.startStatic(staticContent);
}
@Override
public void endStatic(StaticContent statisContent) {
- structureTreeBuilder.endStatic(statisContent);
+ converter.endStatic(statisContent);
super.endStatic(statisContent);
}
@Override
public void startMarkup() {
- structureTreeBuilder.startMarkup();
+ converter.startMarkup();
super.startMarkup();
}
@Override
public void endMarkup() {
- structureTreeBuilder.endMarkup();
+ converter.endMarkup();
super.endMarkup();
}
@Override
public void startLink(BasicLink basicLink) {
- structureTreeBuilder.startLink(basicLink);
+ converter.startLink(basicLink);
super.startLink(basicLink);
}
@Override
public void endLink(BasicLink basicLink) {
- structureTreeBuilder.endLink(basicLink);
+ converter.endLink(basicLink);
super.endLink(basicLink);
}
@Override
public void image(ExternalGraphic eg) {
- structureTreeBuilder.image(eg);
+ converter.image(eg);
super.image(eg);
}
@Override
public void pageRef() {
- structureTreeBuilder.pageRef();
+ converter.pageRef();
super.pageRef();
}
@Override
public void startInstreamForeignObject(InstreamForeignObject ifo) {
- structureTreeBuilder.startInstreamForeignObject(ifo);
+ converter.startInstreamForeignObject(ifo);
super.startInstreamForeignObject(ifo);
}
@Override
public void endInstreamForeignObject(InstreamForeignObject ifo) {
- structureTreeBuilder.endInstreamForeignObject(ifo);
+ converter.endInstreamForeignObject(ifo);
super.endInstreamForeignObject(ifo);
}
@Override
public void startFootnote(Footnote footnote) {
- structureTreeBuilder.startFootnote(footnote);
+ converter.startFootnote(footnote);
super.startFootnote(footnote);
}
@Override
public void endFootnote(Footnote footnote) {
- structureTreeBuilder.endFootnote(footnote);
+ converter.endFootnote(footnote);
super.endFootnote(footnote);
}
@Override
public void startFootnoteBody(FootnoteBody body) {
- structureTreeBuilder.startFootnoteBody(body);
+ converter.startFootnoteBody(body);
super.startFootnoteBody(body);
}
@Override
public void endFootnoteBody(FootnoteBody body) {
- structureTreeBuilder.endFootnoteBody(body);
+ converter.endFootnoteBody(body);
super.endFootnoteBody(body);
}
@Override
public void startLeader(Leader l) {
- structureTreeBuilder = eventSwallower;
- structureTreeBuilder.startLeader(l);
+ converter = eventSwallower;
+ converter.startLeader(l);
super.startLeader(l);
}
@Override
public void endLeader(Leader l) {
- structureTreeBuilder.endLeader(l);
- structureTreeBuilder = actualStructureTreeBuilder;
+ converter.endLeader(l);
+ converter = foToStructureTreeEventAdapter;
super.endLeader(l);
}
@Override
public void startWrapper(Wrapper wrapper) {
- structureTreeBuilder.startWrapper(wrapper);
+ converter.startWrapper(wrapper);
super.startWrapper(wrapper);
}
@Override
public void endWrapper(Wrapper wrapper) {
- structureTreeBuilder.endWrapper(wrapper);
+ converter.endWrapper(wrapper);
super.endWrapper(wrapper);
}
@Override
public void character(Character c) {
- structureTreeBuilder.character(c);
+ converter.character(c);
super.character(c);
}
@Override
public void characters(char[] data, int start, int length) {
- structureTreeBuilder.characters(data, start, length);
+ converter.characters(data, start, length);
super.characters(data, start, length);
}
@Override
public void startExternalDocument(ExternalDocument document) {
- structureTreeBuilder.startExternalDocument(document);
+ converter.startExternalDocument(document);
super.startExternalDocument(document);
}
@Override
public void endExternalDocument(ExternalDocument document) {
- structureTreeBuilder.endExternalDocument(document);
+ converter.endExternalDocument(document);
super.endExternalDocument(document);
}
diff --git a/src/java/org/apache/fop/accessibility/StructureTree.java b/src/java/org/apache/fop/accessibility/StructureTree.java
deleted file mode 100644
index a8afd4ef5..000000000
--- a/src/java/org/apache/fop/accessibility/StructureTree.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* $Id$ */
-
-package org.apache.fop.accessibility;
-
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-/**
- * A reduced version of the document's FO tree, containing only its logical
- * structure. Used by accessible output formats.
- */
-public final class StructureTree {
-
- private final List pageSequenceStructures = new ArrayList();
-
- /**
- * Package-private default constructor.
- */
- public StructureTree() { }
-
- private static boolean flowOrStaticContentNodes(NodeList nodes) {
- for (int i = 0; i < nodes.getLength(); i++) {
- Node node = nodes.item(i);
- if (node.getNodeType() != Node.ELEMENT_NODE) {
- return false;
- }
- String name = node.getLocalName();
- if (!(name.equals("flow") || name.equals("static-content"))) {
- return false;
- }
- }
- return true;
- }
-
- void addPageSequenceStructure(NodeList structureTree) {
- assert flowOrStaticContentNodes(structureTree);
- pageSequenceStructures.add(structureTree);
- }
-
- /**
- * Returns the list of nodes that are the children of the given page sequence.
- *
- * @param index index of the page sequence, 0-based
- * @return its children nodes
- */
- public NodeList getPageSequence(int index) {
- return (NodeList) pageSequenceStructures.get(index);
- }
-
- /**
- * Returns an XML-like representation of the structure trees.
- * <p>
- * <strong>Note:</strong> use only for debugging purpose, as this method
- * performs non-trivial operations.
- * </p>
- * @return a string representation of this object
- */
- public String toString() {
- try {
- Transformer t = TransformerFactory.newInstance().newTransformer();
- Writer str = new StringWriter();
- for (Iterator iter = pageSequenceStructures.iterator(); iter.hasNext();) {
- NodeList nodes = (NodeList) iter.next();
- for (int i = 0, c = nodes.getLength(); i < c; i++) {
- t.transform(new DOMSource(nodes.item(i)), new StreamResult(str));
- }
- }
- return str.toString();
- } catch (Exception e) {
- return e.toString();
- }
- }
-
-}
diff --git a/src/java/org/apache/fop/accessibility/StructureTree2SAXEventAdapter.java b/src/java/org/apache/fop/accessibility/StructureTree2SAXEventAdapter.java
new file mode 100644
index 000000000..240c384d6
--- /dev/null
+++ b/src/java/org/apache/fop/accessibility/StructureTree2SAXEventAdapter.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.accessibility;
+
+import java.util.Locale;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import org.apache.fop.fo.FOElementMapping;
+import org.apache.fop.fo.extensions.ExtensionElementMapping;
+import org.apache.fop.fo.extensions.InternalElementMapping;
+import org.apache.fop.render.intermediate.IFConstants;
+
+/**
+ * Converts structure tree events to SAX events.
+ */
+public final class StructureTree2SAXEventAdapter implements StructureTreeEventHandler {
+
+ private final ContentHandler contentHandler;
+
+ private StructureTree2SAXEventAdapter(ContentHandler currentContentHandler) {
+ this.contentHandler = currentContentHandler;
+ }
+
+ /**
+ * Factory method that creates a new instance.
+ * @param contentHandler The handler that receives SAX events
+ */
+ public static StructureTreeEventHandler newInstance(ContentHandler contentHandler) {
+ return new StructureTree2SAXEventAdapter(contentHandler);
+ }
+
+ /** {@inheritDoc} */
+ public void startPageSequence(Locale locale) {
+ try {
+
+ contentHandler.startPrefixMapping(
+ InternalElementMapping.STANDARD_PREFIX, InternalElementMapping.URI);
+ contentHandler.startPrefixMapping(
+ ExtensionElementMapping.STANDARD_PREFIX, ExtensionElementMapping.URI);
+ contentHandler.startElement(IFConstants.NAMESPACE,
+ IFConstants.EL_STRUCTURE_TREE, IFConstants.EL_STRUCTURE_TREE,
+ new AttributesImpl());
+ } catch (SAXException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void endPageSequence() {
+ try {
+ contentHandler.endElement(IFConstants.NAMESPACE, IFConstants.EL_STRUCTURE_TREE,
+ IFConstants.EL_STRUCTURE_TREE);
+ contentHandler.endPrefixMapping(
+ ExtensionElementMapping.STANDARD_PREFIX);
+ contentHandler.endPrefixMapping(
+ InternalElementMapping.STANDARD_PREFIX);
+
+ } catch (SAXException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void startNode(String name, Attributes attributes) {
+ try {
+ contentHandler.startElement(FOElementMapping.URI, name,
+ FOElementMapping.STANDARD_PREFIX + ":" + name,
+ attributes);
+ } catch (SAXException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void endNode(String name) {
+ try {
+ contentHandler.endElement(FOElementMapping.URI, name,
+ FOElementMapping.STANDARD_PREFIX + ":" + name);
+ } catch (SAXException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/src/java/org/apache/fop/accessibility/StructureTreeBuilder.java b/src/java/org/apache/fop/accessibility/StructureTreeBuilder.java
deleted file mode 100644
index 036502e99..000000000
--- a/src/java/org/apache/fop/accessibility/StructureTreeBuilder.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* $Id$ */
-
-package org.apache.fop.accessibility;
-
-import javax.xml.transform.TransformerConfigurationException;
-import javax.xml.transform.dom.DOMResult;
-import javax.xml.transform.sax.SAXTransformerFactory;
-import javax.xml.transform.sax.TransformerHandler;
-
-import org.xml.sax.ContentHandler;
-import org.xml.sax.SAXException;
-
-import org.apache.fop.util.DelegatingContentHandler;
-
-/**
- * Helper class that re-builds a structure tree from what is stored in an
- * intermediate XML file (IF XML or Area Tree XML).
- */
-public final class StructureTreeBuilder {
-
- private final SAXTransformerFactory factory;
-
- private final StructureTree structureTree = new StructureTree();
-
- /**
- * Creates a new instance.
- *
- * @param factory a factory internally used to build the structures of page
- * sequences
- */
- public StructureTreeBuilder(SAXTransformerFactory factory) {
- this.factory = factory;
- }
-
- /**
- * Returns the structure tree that will result from the parsing.
- *
- * @return the structure tree built by this object
- */
- public StructureTree getStructureTree() {
- return structureTree;
- }
-
- /**
- * Returns a ContenHandler for parsing the structure of a new page sequence.
- * It is assumed that page sequences are being parsed in the document order.
- *
- * @return a handler for parsing the &lt;structure-tree&gt; or
- * &lt;structureTree&gt; element and its descendants
- * @throws SAXException if there is an error when creating the handler
- */
- public ContentHandler getHandlerForNextPageSequence() throws SAXException {
- TransformerHandler structureTreeBuilder;
- try {
- structureTreeBuilder = factory.newTransformerHandler();
- } catch (TransformerConfigurationException e) {
- throw new SAXException(e);
- }
- final DOMResult domResult = new DOMResult();
- structureTreeBuilder.setResult(domResult);
- return new DelegatingContentHandler(structureTreeBuilder) {
-
- public void characters(char[] ch, int start, int length) throws SAXException {
- /*
- * There's no text node in the structure tree. This is just
- * whitespace => ignore
- */
- }
-
- public void endDocument() throws SAXException {
- super.endDocument();
- structureTree.addPageSequenceStructure(domResult.getNode().getFirstChild()
- .getChildNodes());
- }
- };
- }
-
-}
diff --git a/src/java/org/apache/fop/accessibility/StructureTreeEventHandler.java b/src/java/org/apache/fop/accessibility/StructureTreeEventHandler.java
new file mode 100644
index 000000000..d84d07870
--- /dev/null
+++ b/src/java/org/apache/fop/accessibility/StructureTreeEventHandler.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.accessibility;
+
+import java.util.Locale;
+
+import org.xml.sax.Attributes;
+
+/**
+ * Receive notifications relating to the structure tree of an FO document.
+ * A structure tree is a reduced version of the document's FO tree, containing only the logical
+ * structure that is used by accessible output formats.
+ */
+public interface StructureTreeEventHandler {
+
+ /**
+ * Starts a page sequence structure tree node.
+ * @param locale The locale of the page sequence
+ */
+ void startPageSequence(Locale locale);
+
+ /**
+ * Starts a structure tree node.
+ * @param name The name of the structure tree node
+ * @param attributes Map of node properties
+ */
+ void startNode(String name, Attributes attributes);
+
+ /**
+ * Ends a structure tree node.
+ * @param name The name of the structure tree node
+ */
+ void endNode(String name);
+
+ /**
+ * Ends a page sequence structure tree node.
+ */
+ void endPageSequence();
+}
diff --git a/src/java/org/apache/fop/apps/FOUserAgent.java b/src/java/org/apache/fop/apps/FOUserAgent.java
index 071066e04..d5cc695c8 100644
--- a/src/java/org/apache/fop/apps/FOUserAgent.java
+++ b/src/java/org/apache/fop/apps/FOUserAgent.java
@@ -39,7 +39,8 @@ import org.apache.xmlgraphics.util.UnitConv;
import org.apache.fop.Version;
import org.apache.fop.accessibility.Accessibility;
-import org.apache.fop.accessibility.StructureTree;
+import org.apache.fop.accessibility.DummyStructureTreeEventHandler;
+import org.apache.fop.accessibility.StructureTreeEventHandler;
import org.apache.fop.events.DefaultEventBroadcaster;
import org.apache.fop.events.Event;
import org.apache.fop.events.EventBroadcaster;
@@ -101,8 +102,7 @@ public class FOUserAgent {
private boolean locatorEnabled = true; // true by default (for error messages).
private boolean conserveMemoryPolicy = false;
private EventBroadcaster eventBroadcaster = new FOPEventBroadcaster();
-
- private StructureTree structureTree;
+ private StructureTreeEventHandler structureTreeEventHandler = DummyStructureTreeEventHandler.INSTANCE;
/** Producer: Metadata element for the system/software that produces
* the document. (Some renderers can store this in the document.)
@@ -173,6 +173,9 @@ public class FOUserAgent {
* @param documentHandler the document handler instance to use
*/
public void setDocumentHandlerOverride(IFDocumentHandler documentHandler) {
+ if (isAccessibilityEnabled()) {
+ setStructureTreeEventHandler(documentHandler.getStructureTreeEventHandler());
+ }
this.documentHandlerOverride = documentHandler;
}
@@ -674,24 +677,23 @@ public class FOUserAgent {
}
/**
- * Sets the document's structure tree, for use by accessible output formats.
+ * Sets the document's structure tree event handler, for use by accessible
+ * output formats.
*
- * @param structureTree a simplified version of the FO tree, retaining only
- * its logical structure
+ * @param structureTreeEventHandler The structure tree event handler to set
*/
- public void setStructureTree(StructureTree structureTree) {
- this.structureTree = structureTree;
+ public void setStructureTreeEventHandler(StructureTreeEventHandler structureTreeEventHandler) {
+ this.structureTreeEventHandler = structureTreeEventHandler;
}
/**
- * Returns the document's structure tree, for use by accessible output
- * formats.
+ * Returns the document's structure tree event handler, for use by
+ * accessible output formats.
*
- * @return a simplified version of the FO tree, retaining only its logical
- * structure
+ * @return The structure tree event handler
*/
- public StructureTree getStructureTree() {
- return this.structureTree;
+ public StructureTreeEventHandler getStructureTreeEventHandler() {
+ return this.structureTreeEventHandler;
}
}
diff --git a/src/java/org/apache/fop/area/AreaTreeHandler.java b/src/java/org/apache/fop/area/AreaTreeHandler.java
index f45245bfe..6448e7c5d 100644
--- a/src/java/org/apache/fop/area/AreaTreeHandler.java
+++ b/src/java/org/apache/fop/area/AreaTreeHandler.java
@@ -22,6 +22,7 @@ package org.apache.fop.area;
// Java
import java.io.OutputStream;
import java.util.List;
+import java.util.Locale;
import org.xml.sax.SAXException;
@@ -182,6 +183,14 @@ public class AreaTreeHandler extends FOEventHandler {
}
}
+ @Override
+ public void startRoot(Root root) {
+ Locale locale = root.getLocale();
+ if (locale != null) {
+ model.setDocumentLocale(locale);
+ }
+ }
+
/**
* finish the previous pageSequence
*/
diff --git a/src/java/org/apache/fop/area/AreaTreeModel.java b/src/java/org/apache/fop/area/AreaTreeModel.java
index 2a1f14ab5..941f6cea2 100644
--- a/src/java/org/apache/fop/area/AreaTreeModel.java
+++ b/src/java/org/apache/fop/area/AreaTreeModel.java
@@ -21,6 +21,7 @@ package org.apache.fop.area;
// Java
import java.util.List;
+import java.util.Locale;
import org.xml.sax.SAXException;
@@ -123,4 +124,11 @@ public class AreaTreeModel {
public PageViewport getPage(int seq, int count) {
return pageSequenceList.get(seq - 1).getPage(count);
}
+
+ /**
+ *
+ * @param locale The locale of the document
+ */
+ public void setDocumentLocale(Locale locale) {
+ }
}
diff --git a/src/java/org/apache/fop/area/AreaTreeParser.java b/src/java/org/apache/fop/area/AreaTreeParser.java
index d2f52f991..545c9015d 100644
--- a/src/java/org/apache/fop/area/AreaTreeParser.java
+++ b/src/java/org/apache/fop/area/AreaTreeParser.java
@@ -58,8 +58,6 @@ import org.apache.xmlgraphics.image.loader.ImageSessionContext;
import org.apache.xmlgraphics.util.QName;
import org.apache.fop.ResourceEventProducer;
-import org.apache.fop.accessibility.AccessibilityEventProducer;
-import org.apache.fop.accessibility.StructureTreeBuilder;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.area.Trait.Background;
import org.apache.fop.area.Trait.InternalLink;
@@ -69,11 +67,11 @@ import org.apache.fop.area.inline.Image;
import org.apache.fop.area.inline.InlineArea;
import org.apache.fop.area.inline.InlineBlockParent;
import org.apache.fop.area.inline.InlineParent;
+import org.apache.fop.area.inline.InlineViewport;
import org.apache.fop.area.inline.Leader;
import org.apache.fop.area.inline.Space;
import org.apache.fop.area.inline.SpaceArea;
import org.apache.fop.area.inline.TextArea;
-import org.apache.fop.area.inline.InlineViewport;
import org.apache.fop.area.inline.WordArea;
import org.apache.fop.fo.ElementMappingRegistry;
import org.apache.fop.fo.expr.PropertyException;
@@ -86,7 +84,6 @@ import org.apache.fop.util.ContentHandlerFactory;
import org.apache.fop.util.ContentHandlerFactoryRegistry;
import org.apache.fop.util.ConversionUtils;
import org.apache.fop.util.DefaultErrorListener;
-import org.apache.fop.util.DelegatingContentHandler;
import org.apache.fop.util.XMLConstants;
import org.apache.fop.util.XMLUtil;
@@ -166,27 +163,8 @@ public class AreaTreeParser {
private DOMImplementation domImplementation;
private Locator locator;
-
- private StructureTreeBuilder structureTreeBuilder;
-
- private ContentHandler structureTreeBuilderWrapper;
-
private Attributes pageSequenceAttributes;
- private final class StructureTreeBuilderWrapper extends DelegatingContentHandler {
-
- private StructureTreeBuilderWrapper()
- throws SAXException {
- super(structureTreeBuilder.getHandlerForNextPageSequence());
- }
-
- public void endDocument() throws SAXException {
- super.endDocument();
- startAreaTreeElement("pageSequence", pageSequenceAttributes);
- pageSequenceAttributes = null;
- }
- }
-
public Handler(AreaTreeModel treeModel, FOUserAgent userAgent,
ElementMappingRegistry elementMappingRegistry) {
this.treeModel = treeModel;
@@ -223,11 +201,6 @@ public class AreaTreeParser {
makers.put("bookmarkTree", new BookmarkTreeMaker());
makers.put("bookmark", new BookmarkMaker());
makers.put("destination", new DestinationMaker());
-
- if (userAgent.isAccessibilityEnabled()) {
- structureTreeBuilder = new StructureTreeBuilder(tFactory);
- userAgent.setStructureTree(structureTreeBuilder.getStructureTree());
- }
}
private Area findAreaType(Class clazz) {
@@ -308,32 +281,15 @@ public class AreaTreeParser {
} else {
boolean handled = true;
if ("".equals(uri)) {
- if (localName.equals("pageSequence") && userAgent.isAccessibilityEnabled()) {
- structureTreeBuilderWrapper = new StructureTreeBuilderWrapper();
- pageSequenceAttributes = new AttributesImpl(attributes);
- } else if (localName.equals("structureTree")) {
- if (userAgent.isAccessibilityEnabled()) {
- delegate = structureTreeBuilderWrapper;
- } else {
- /* Delegate to a handler that does nothing */
- delegate = new DefaultHandler();
- }
+ if (localName.equals("structureTree")) {
+
+ /* The area tree parser no longer supports the structure tree. */
+ delegate = new DefaultHandler();
+
delegateStack.push(qName);
delegate.startDocument();
delegate.startElement(uri, localName, qName, attributes);
} else {
- if (pageSequenceAttributes != null) {
- /*
- * This means that no structure-element tag was
- * found in the XML, otherwise a
- * StructureTreeBuilderWrapper object would have
- * been created, which would have reset the
- * pageSequenceAttributes field.
- */
- AccessibilityEventProducer.Provider
- .get(userAgent.getEventBroadcaster())
- .noStructureTreeInXML(this);
- }
handled = startAreaTreeElement(localName, attributes);
}
} else {
diff --git a/src/java/org/apache/fop/area/RenderPagesModel.java b/src/java/org/apache/fop/area/RenderPagesModel.java
index afec850f8..cef2552c8 100644
--- a/src/java/org/apache/fop/area/RenderPagesModel.java
+++ b/src/java/org/apache/fop/area/RenderPagesModel.java
@@ -24,6 +24,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.List;
+import java.util.Locale;
import org.xml.sax.SAXException;
@@ -83,6 +84,11 @@ public class RenderPagesModel extends AreaTreeModel {
}
}
+ @Override
+ public void setDocumentLocale(Locale locale) {
+ renderer.setDocumentLocale(locale);
+ }
+
/** {@inheritDoc} */
@Override
public void startPageSequence(PageSequence pageSequence) {
diff --git a/src/java/org/apache/fop/fo/DelegatingFOEventHandler.java b/src/java/org/apache/fop/fo/DelegatingFOEventHandler.java
index cb4ded17f..ed85bd1c9 100644
--- a/src/java/org/apache/fop/fo/DelegatingFOEventHandler.java
+++ b/src/java/org/apache/fop/fo/DelegatingFOEventHandler.java
@@ -50,6 +50,7 @@ import org.apache.fop.fo.flow.table.TableHeader;
import org.apache.fop.fo.flow.table.TableRow;
import org.apache.fop.fo.pagination.Flow;
import org.apache.fop.fo.pagination.PageSequence;
+import org.apache.fop.fo.pagination.Root;
import org.apache.fop.fo.pagination.StaticContent;
import org.apache.fop.fonts.FontInfo;
@@ -91,6 +92,16 @@ public abstract class DelegatingFOEventHandler extends FOEventHandler {
}
@Override
+ public void startRoot(Root root) {
+ delegate.startRoot(root);
+ }
+
+ @Override
+ public void endRoot(Root root) {
+ delegate.endRoot(root);
+ }
+
+ @Override
public void startPageSequence(PageSequence pageSeq) {
delegate.startPageSequence(pageSeq);
}
diff --git a/src/java/org/apache/fop/fo/FOElementMapping.java b/src/java/org/apache/fop/fo/FOElementMapping.java
index 8069880c6..c96c3b933 100644
--- a/src/java/org/apache/fop/fo/FOElementMapping.java
+++ b/src/java/org/apache/fop/fo/FOElementMapping.java
@@ -32,6 +32,9 @@ public class FOElementMapping extends ElementMapping {
/** The XSL-FO namespace URI */
public static final String URI = "http://www.w3.org/1999/XSL/Format";
+ /** Standard prefix */
+ public static final String STANDARD_PREFIX = "fo";
+
/**
* Basic constructor; inititializes the namespace URI for the fo: namespace
*/
@@ -141,7 +144,7 @@ public class FOElementMapping extends ElementMapping {
/** {@inheritDoc} */
public String getStandardPrefix() {
- return "fo";
+ return STANDARD_PREFIX;
}
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/fo/FOEventHandler.java b/src/java/org/apache/fop/fo/FOEventHandler.java
index 453edec35..1f3514dea 100644
--- a/src/java/org/apache/fop/fo/FOEventHandler.java
+++ b/src/java/org/apache/fop/fo/FOEventHandler.java
@@ -50,6 +50,7 @@ import org.apache.fop.fo.flow.table.TableHeader;
import org.apache.fop.fo.flow.table.TableRow;
import org.apache.fop.fo.pagination.Flow;
import org.apache.fop.fo.pagination.PageSequence;
+import org.apache.fop.fo.pagination.Root;
import org.apache.fop.fo.pagination.StaticContent;
import org.apache.fop.fonts.FontEventAdapter;
import org.apache.fop.fonts.FontInfo;
@@ -117,6 +118,12 @@ public abstract class FOEventHandler {
public void endDocument() throws SAXException {
}
+ public void startRoot(Root root) {
+ }
+
+ public void endRoot(Root root) {
+ }
+
/**
*
* @param pageSeq PageSequence that is starting.
diff --git a/src/java/org/apache/fop/fo/FOTreeBuilder.java b/src/java/org/apache/fop/fo/FOTreeBuilder.java
index 890138e5c..b053692d6 100644
--- a/src/java/org/apache/fop/fo/FOTreeBuilder.java
+++ b/src/java/org/apache/fop/fo/FOTreeBuilder.java
@@ -33,8 +33,7 @@ import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.util.QName;
-import org.apache.fop.accessibility.StructureTree;
-import org.apache.fop.accessibility.StructureTreeBuildingFOEventHandler;
+import org.apache.fop.accessibility.FO2StructureTreeConverter;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.FormattingResults;
@@ -107,9 +106,8 @@ public class FOTreeBuilder extends DefaultHandler {
foEventHandler = foUserAgent.getRendererFactory().createFOEventHandler(
foUserAgent, outputFormat, stream);
if (userAgent.isAccessibilityEnabled()) {
- StructureTree structureTree = new StructureTree();
- foEventHandler = new StructureTreeBuildingFOEventHandler(structureTree, foEventHandler);
- userAgent.setStructureTree(structureTree);
+ foEventHandler = new FO2StructureTreeConverter(
+ foUserAgent.getStructureTreeEventHandler(), foEventHandler);
}
builderContext = new FOTreeBuilderContext();
builderContext.setPropertyListMaker(new PropertyListMaker() {
diff --git a/src/java/org/apache/fop/fo/pagination/Root.java b/src/java/org/apache/fop/fo/pagination/Root.java
index c670d6e42..6df6e9537 100644
--- a/src/java/org/apache/fop/fo/pagination/Root.java
+++ b/src/java/org/apache/fop/fo/pagination/Root.java
@@ -21,6 +21,7 @@ package org.apache.fop.fo.pagination;
// java
import java.util.List;
+import java.util.Locale;
import org.xml.sax.Locator;
@@ -52,6 +53,7 @@ public class Root extends FObj implements CommonAccessibilityHolder {
private BookmarkTree bookmarkTree = null;
private List<Destination> destinationList;
private List<PageSequence> pageSequences;
+ private Locale locale;
// temporary until above list populated
private boolean pageSequenceFound = false;
@@ -88,6 +90,24 @@ public class Root extends FObj implements CommonAccessibilityHolder {
super.bind(pList);
commonAccessibility = CommonAccessibility.getInstance(pList);
mediaUsage = pList.get(PR_MEDIA_USAGE).getEnum();
+ String language = pList.get(PR_LANGUAGE).getString();
+ String country = pList.get(PR_COUNTRY).getString();
+ if (isLocalePropertySet(language)) {
+ if (isLocalePropertySet(country)) {
+ locale = new Locale(language, country);
+ } else {
+ locale = new Locale(language);
+ }
+ }
+ }
+
+ private boolean isLocalePropertySet(String property) {
+ return property != null && !property.equals("none");
+ }
+
+ /** {@inheritDoc} */
+ protected void startOfNode() throws FOPException {
+ foEventHandler.startRoot(this);
}
/** {@inheritDoc} */
@@ -96,6 +116,7 @@ public class Root extends FObj implements CommonAccessibilityHolder {
missingChildElementError("(layout-master-set, declarations?, "
+ "bookmark-tree?, (page-sequence|fox:external-document)+)");
}
+ foEventHandler.endRoot(this);
}
/**
@@ -343,4 +364,9 @@ public class Root extends FObj implements CommonAccessibilityHolder {
return FO_ROOT;
}
+
+ public Locale getLocale() {
+ return locale;
+ }
+
}
diff --git a/src/java/org/apache/fop/pdf/PDFDocument.java b/src/java/org/apache/fop/pdf/PDFDocument.java
index cbca3ea8f..e9f42d4b2 100644
--- a/src/java/org/apache/fop/pdf/PDFDocument.java
+++ b/src/java/org/apache/fop/pdf/PDFDocument.java
@@ -354,25 +354,6 @@ public class PDFDocument {
}
/**
- * Makes sure a Lang entry has been set on the document catalog, setting it
- * to a default value if necessary. When accessibility is enabled the
- * language must be specified for any text element in the document.
- */
- public void enforceLanguageOnRoot() {
- if (root.getLanguage() == null) {
- String fallbackLanguage;
- if (getProfile().getPDFAMode().isPDFA1LevelA()) {
- //According to Annex B of ISO-19005-1:2005(E), section B.2
- fallbackLanguage = "x-unknown";
- } else {
- //No language has been set on the first page-sequence, so fall back to "en".
- fallbackLanguage = "en";
- }
- root.setLanguage(fallbackLanguage);
- }
- }
-
- /**
* Get the {@link PDFInfo} object for this document.
*
* @return the {@link PDFInfo} object
diff --git a/src/java/org/apache/fop/pdf/PDFProfile.java b/src/java/org/apache/fop/pdf/PDFProfile.java
index fb4575105..b4b43c422 100644
--- a/src/java/org/apache/fop/pdf/PDFProfile.java
+++ b/src/java/org/apache/fop/pdf/PDFProfile.java
@@ -133,8 +133,12 @@ public class PDFProfile {
//---------=== Info and validation methods ===---------
+ private String format(String pattern, Object[] args) {
+ return MessageFormat.format(pattern, args);
+ }
+
private String format(String pattern, Object arg) {
- return MessageFormat.format(pattern, new Object[] {arg});
+ return format(pattern, new Object[] {arg});
}
/** Checks if encryption is allowed. */
diff --git a/src/java/org/apache/fop/pdf/PDFRoot.java b/src/java/org/apache/fop/pdf/PDFRoot.java
index f71841005..177ca4b2d 100644
--- a/src/java/org/apache/fop/pdf/PDFRoot.java
+++ b/src/java/org/apache/fop/pdf/PDFRoot.java
@@ -21,6 +21,9 @@ package org.apache.fop.pdf;
import java.io.IOException;
import java.io.OutputStream;
+import java.util.Locale;
+
+import org.apache.fop.util.LanguageTags;
/**
* Class representing a Root (/Catalog) object.
@@ -69,6 +72,7 @@ public class PDFRoot extends PDFDictionary {
setObjectNumber(objnum);
put("Type", new PDFName("Catalog"));
setRootPages(pages);
+ setLanguage("x-unknown");
}
/** {@inheritDoc} */
@@ -254,10 +258,14 @@ public class PDFRoot extends PDFDictionary {
* Sets the language identifier of the document.
* @param lang the language identifier of the document.
*/
- public void setLanguage(String lang) {
- if (lang == null) {
- throw new NullPointerException("lang must not be null");
+ public void setLanguage(Locale locale) {
+ if (locale == null) {
+ throw new NullPointerException("locale must not be null");
}
+ setLanguage(LanguageTags.toLanguageTag(locale));
+ }
+
+ private void setLanguage(String lang) {
put("Lang", lang);
}
diff --git a/src/java/org/apache/fop/pdf/PDFStructElem.java b/src/java/org/apache/fop/pdf/PDFStructElem.java
index 4fb8cbcd5..6dfb0dc95 100644
--- a/src/java/org/apache/fop/pdf/PDFStructElem.java
+++ b/src/java/org/apache/fop/pdf/PDFStructElem.java
@@ -21,7 +21,7 @@ package org.apache.fop.pdf;
import java.util.Locale;
-import org.apache.fop.util.XMLUtil;
+import org.apache.fop.util.LanguageTags;
/**
* Class representing a PDF Structure Element.
@@ -145,7 +145,7 @@ public class PDFStructElem extends PDFDictionary {
* @param language a value for the Lang entry
*/
public void setLanguage(Locale language) {
- setLanguage(XMLUtil.toRFC3066(language));
+ setLanguage(LanguageTags.toLanguageTag(language));
}
/**
diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java
index 7ff236d16..ec14e597c 100644
--- a/src/java/org/apache/fop/render/AbstractRenderer.java
+++ b/src/java/org/apache/fop/render/AbstractRenderer.java
@@ -27,6 +27,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.List;
+import java.util.Locale;
import java.util.Set;
import org.w3c.dom.Document;
@@ -61,11 +62,11 @@ import org.apache.fop.area.inline.Image;
import org.apache.fop.area.inline.InlineArea;
import org.apache.fop.area.inline.InlineBlockParent;
import org.apache.fop.area.inline.InlineParent;
+import org.apache.fop.area.inline.InlineViewport;
import org.apache.fop.area.inline.Leader;
import org.apache.fop.area.inline.Space;
import org.apache.fop.area.inline.SpaceArea;
import org.apache.fop.area.inline.TextArea;
-import org.apache.fop.area.inline.InlineViewport;
import org.apache.fop.area.inline.WordArea;
import org.apache.fop.fo.Constants;
import org.apache.fop.fonts.FontInfo;
@@ -152,6 +153,10 @@ public abstract class AbstractRenderer
return false;
}
+ /** {@inheritDoc} */
+ public void setDocumentLocale(Locale locale) {
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/src/java/org/apache/fop/render/Renderer.java b/src/java/org/apache/fop/render/Renderer.java
index 76f245251..599b8e260 100644
--- a/src/java/org/apache/fop/render/Renderer.java
+++ b/src/java/org/apache/fop/render/Renderer.java
@@ -22,6 +22,7 @@ package org.apache.fop.render;
// Java
import java.io.IOException;
import java.io.OutputStream;
+import java.util.Locale;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
@@ -116,6 +117,12 @@ public interface Renderer {
boolean supportsOutOfOrder();
/**
+ *
+ * @param locale Locale of the language
+ */
+ void setDocumentLocale(Locale locale);
+
+ /**
* Tells the renderer to process an item not explicitly placed on the
* document (e.g., PDF bookmarks). Note - not all renderers will process
* all off-document items.
diff --git a/src/java/org/apache/fop/render/intermediate/AbstractIFDocumentHandler.java b/src/java/org/apache/fop/render/intermediate/AbstractIFDocumentHandler.java
index b156b6c3a..ad4e6ad0e 100644
--- a/src/java/org/apache/fop/render/intermediate/AbstractIFDocumentHandler.java
+++ b/src/java/org/apache/fop/render/intermediate/AbstractIFDocumentHandler.java
@@ -19,6 +19,13 @@
package org.apache.fop.render.intermediate;
+import java.util.Locale;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.fop.accessibility.DummyStructureTreeEventHandler;
+import org.apache.fop.accessibility.StructureTreeEventHandler;
import org.apache.fop.apps.FOUserAgent;
/**
@@ -53,6 +60,11 @@ public abstract class AbstractIFDocumentHandler implements IFDocumentHandler {
}
/** {@inheritDoc} */
+ public StructureTreeEventHandler getStructureTreeEventHandler() {
+ return DummyStructureTreeEventHandler.INSTANCE;
+ }
+
+ /** {@inheritDoc} */
public IFDocumentNavigationHandler getDocumentNavigationHandler() {
return null; //By default, this is not supported
}
@@ -66,6 +78,10 @@ public abstract class AbstractIFDocumentHandler implements IFDocumentHandler {
}
/** {@inheritDoc} */
+ public void setDocumentLocale(Locale locale) {
+ }
+
+ /** {@inheritDoc} */
public void startDocumentHeader() throws IFException {
//nop
}
@@ -104,5 +120,4 @@ public abstract class AbstractIFDocumentHandler implements IFDocumentHandler {
public void endPageTrailer() throws IFException {
//nop
}
-
}
diff --git a/src/java/org/apache/fop/render/intermediate/IFConstants.java b/src/java/org/apache/fop/render/intermediate/IFConstants.java
index 2b16b343d..dba39bec0 100644
--- a/src/java/org/apache/fop/render/intermediate/IFConstants.java
+++ b/src/java/org/apache/fop/render/intermediate/IFConstants.java
@@ -39,6 +39,7 @@ public interface IFConstants extends XMLConstants {
String EL_HEADER = "header";
/** element name trailer */
String EL_TRAILER = "trailer";
+ String EL_LOCALE = "locale";
/** element name page-sequence */
String EL_PAGE_SEQUENCE = "page-sequence";
/** element name page */
diff --git a/src/java/org/apache/fop/render/intermediate/IFDocumentHandler.java b/src/java/org/apache/fop/render/intermediate/IFDocumentHandler.java
index af1451fe3..6cb8f2795 100644
--- a/src/java/org/apache/fop/render/intermediate/IFDocumentHandler.java
+++ b/src/java/org/apache/fop/render/intermediate/IFDocumentHandler.java
@@ -20,9 +20,11 @@
package org.apache.fop.render.intermediate;
import java.awt.Dimension;
+import java.util.Locale;
import javax.xml.transform.Result;
+import org.apache.fop.accessibility.StructureTreeEventHandler;
import org.apache.fop.fonts.FontInfo;
/**
@@ -32,6 +34,7 @@ import org.apache.fop.fonts.FontInfo;
* <p>
* <pre>
* startDocument()
+ * [setDocumentLocale()]
* startDocumentHeader()
* [handleExtension()]*
* endDocumentHeader()
@@ -118,6 +121,11 @@ public interface IFDocumentHandler {
IFDocumentHandlerConfigurator getConfigurator();
/**
+ * @return the structure tree builder
+ */
+ StructureTreeEventHandler getStructureTreeEventHandler();
+
+ /**
* Returns a document navigation handler if this feature is supported.
* @return the document navigation handler or null if not supported
*/
@@ -152,6 +160,11 @@ public interface IFDocumentHandler {
void endDocument() throws IFException;
/**
+ * @param locale Locale of the document.
+ */
+ void setDocumentLocale(Locale locale);
+
+ /**
* Indicates the start of the document header. This method is called right after the
* {@link #startDocument()} method. Extensions sent to this painter between
* {@link #startDocumentHeader()} and {@link #endDocumentHeader()} apply to the document as
@@ -261,7 +274,4 @@ public interface IFDocumentHandler {
* @throws IFException if an error occurs while handling this event
*/
void handleExtensionObject(Object extension) throws IFException;
-
- //TODO Prototype the following:
- //ContentHandler handleExtension() throws Exception
}
diff --git a/src/java/org/apache/fop/render/intermediate/IFParser.java b/src/java/org/apache/fop/render/intermediate/IFParser.java
index 313cee685..8f0bb88ec 100644
--- a/src/java/org/apache/fop/render/intermediate/IFParser.java
+++ b/src/java/org/apache/fop/render/intermediate/IFParser.java
@@ -25,6 +25,7 @@ import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.util.HashMap;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
@@ -48,7 +49,7 @@ import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.util.QName;
import org.apache.fop.accessibility.AccessibilityEventProducer;
-import org.apache.fop.accessibility.StructureTreeBuilder;
+import org.apache.fop.accessibility.StructureTreeEventHandler;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.fo.ElementMapping;
import org.apache.fop.fo.ElementMappingRegistry;
@@ -62,7 +63,7 @@ import org.apache.fop.util.ContentHandlerFactory;
import org.apache.fop.util.ContentHandlerFactoryRegistry;
import org.apache.fop.util.DOMBuilderContentHandlerFactory;
import org.apache.fop.util.DefaultErrorListener;
-import org.apache.fop.util.DelegatingContentHandler;
+import org.apache.fop.util.LanguageTags;
import org.apache.fop.util.XMLUtil;
/**
@@ -153,24 +154,40 @@ public class IFParser implements IFConstants {
private ContentHandler navParser;
- private StructureTreeBuilder structureTreeBuilder;
-
- private ContentHandler structureTreeBuilderWrapper;
+ private ContentHandler structureTreeHandler;
private Attributes pageSequenceAttributes;
- private final class StructureTreeBuilderWrapper extends DelegatingContentHandler {
+ private final class StructureTreeHandler extends DefaultHandler {
- private StructureTreeBuilderWrapper()
- throws SAXException {
- super(structureTreeBuilder.getHandlerForNextPageSequence());
+ private final StructureTreeEventHandler structureTreeEventHandler;
+
+ private StructureTreeHandler(StructureTreeEventHandler structureTreeEventHandler,
+ Locale pageSequenceLanguage) throws SAXException {
+ this.structureTreeEventHandler = structureTreeEventHandler;
+ structureTreeEventHandler.startPageSequence(pageSequenceLanguage);
}
public void endDocument() throws SAXException {
- super.endDocument();
startIFElement(EL_PAGE_SEQUENCE, pageSequenceAttributes);
pageSequenceAttributes = null;
}
+
+ @Override
+ public void startElement(String uri, String localName, String qName,
+ Attributes attributes) throws SAXException {
+ if (!"structure-tree".equals(localName)) {
+ structureTreeEventHandler.startNode(localName, attributes);
+ }
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String arqNameg2)
+ throws SAXException {
+ if (!"structure-tree".equals(localName)) {
+ structureTreeEventHandler.endNode(localName);
+ }
+ }
}
public Handler(IFDocumentHandler documentHandler, FOUserAgent userAgent,
@@ -180,6 +197,7 @@ public class IFParser implements IFConstants {
this.elementMappingRegistry = elementMappingRegistry;
elementHandlers.put(EL_DOCUMENT, new DocumentHandler());
elementHandlers.put(EL_HEADER, new DocumentHeaderHandler());
+ elementHandlers.put(EL_LOCALE, new LocaleHandler());
elementHandlers.put(EL_TRAILER, new DocumentTrailerHandler());
elementHandlers.put(EL_PAGE_SEQUENCE, new PageSequenceHandler());
elementHandlers.put(EL_PAGE, new PageHandler());
@@ -197,11 +215,6 @@ public class IFParser implements IFConstants {
elementHandlers.put(EL_LINE, new LineHandler());
elementHandlers.put(EL_BORDER_RECT, new BorderRectHandler());
elementHandlers.put(EL_IMAGE, new ImageHandler());
-
- if (userAgent.isAccessibilityEnabled()) {
- structureTreeBuilder = new StructureTreeBuilder(tFactory);
- userAgent.setStructureTree(structureTreeBuilder.getStructureTree());
- }
}
private void establishForeignAttributes(Map<QName, String> foreignAttributes) {
@@ -231,10 +244,13 @@ public class IFParser implements IFConstants {
if (NAMESPACE.equals(uri)) {
if (localName.equals(EL_PAGE_SEQUENCE) && userAgent.isAccessibilityEnabled()) {
pageSequenceAttributes = new AttributesImpl(attributes);
- structureTreeBuilderWrapper = new StructureTreeBuilderWrapper();
+ Locale language = getLanguage(attributes);
+ structureTreeHandler = new StructureTreeHandler(
+ userAgent.getStructureTreeEventHandler(), language);
+
} else if (localName.equals(EL_STRUCTURE_TREE)) {
if (userAgent.isAccessibilityEnabled()) {
- delegate = structureTreeBuilderWrapper;
+ delegate = structureTreeHandler;
} else {
/* Delegate to a handler that does nothing */
delegate = new DefaultHandler();
@@ -299,6 +315,11 @@ public class IFParser implements IFConstants {
}
}
+ private static Locale getLanguage(Attributes attributes) {
+ String xmllang = attributes.getValue(XML_NAMESPACE, "lang");
+ return (xmllang == null) ? null : LanguageTags.toLocale(xmllang);
+ }
+
private boolean startIFElement(String localName, Attributes attributes)
throws SAXException {
lastAttributes = new AttributesImpl(attributes);
@@ -413,6 +434,12 @@ public class IFParser implements IFConstants {
}
+ private class LocaleHandler extends AbstractElementHandler {
+ public void startElement(Attributes attributes) throws IFException {
+ documentHandler.setDocumentLocale(getLanguage(attributes));
+ }
+ }
+
private class DocumentTrailerHandler extends AbstractElementHandler {
public void startElement(Attributes attributes) throws IFException {
@@ -429,10 +456,9 @@ public class IFParser implements IFConstants {
public void startElement(Attributes attributes) throws IFException {
String id = attributes.getValue("id");
- String xmllang = attributes.getValue(XML_NAMESPACE, "lang");
- if (xmllang != null) {
- documentHandler.getContext().setLanguage(
- XMLUtil.convertRFC3066ToLocale(xmllang));
+ Locale language = getLanguage(attributes);
+ if (language != null) {
+ documentHandler.getContext().setLanguage(language);
}
Map<QName, String> foreignAttributes = getForeignAttributes(lastAttributes);
establishForeignAttributes(foreignAttributes);
diff --git a/src/java/org/apache/fop/render/intermediate/IFRenderer.java b/src/java/org/apache/fop/render/intermediate/IFRenderer.java
index 24a2e8a75..d217646f6 100644
--- a/src/java/org/apache/fop/render/intermediate/IFRenderer.java
+++ b/src/java/org/apache/fop/render/intermediate/IFRenderer.java
@@ -51,6 +51,7 @@ import org.apache.xmlgraphics.xmp.schemas.XMPBasicSchema;
import org.apache.fop.Version;
import org.apache.fop.apps.FOPException;
+import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.area.Area;
import org.apache.fop.area.AreaTreeObject;
@@ -70,10 +71,10 @@ import org.apache.fop.area.inline.ForeignObject;
import org.apache.fop.area.inline.Image;
import org.apache.fop.area.inline.InlineArea;
import org.apache.fop.area.inline.InlineParent;
+import org.apache.fop.area.inline.InlineViewport;
import org.apache.fop.area.inline.Leader;
import org.apache.fop.area.inline.SpaceArea;
import org.apache.fop.area.inline.TextArea;
-import org.apache.fop.area.inline.InlineViewport;
import org.apache.fop.area.inline.WordArea;
import org.apache.fop.datatypes.URISpecification;
import org.apache.fop.fo.extensions.ExtensionAttachment;
@@ -227,7 +228,11 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
*/
protected IFDocumentHandler createDefaultDocumentHandler() {
IFSerializer serializer = new IFSerializer();
- serializer.setContext(new IFContext(getUserAgent()));
+ FOUserAgent userAgent = getUserAgent();
+ serializer.setContext(new IFContext(userAgent));
+ if (userAgent.isAccessibilityEnabled()) {
+ userAgent.setStructureTreeEventHandler(serializer.getStructureTreeEventHandler());
+ }
return serializer;
}
@@ -294,6 +299,11 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
log.debug("Rendering finished.");
}
+ @Override
+ public void setDocumentLocale(Locale locale) {
+ documentHandler.setDocumentLocale(locale);
+ }
+
/** {@inheritDoc} */
public void processOffDocumentItem(OffDocumentItem odi) {
if (odi instanceof DestinationData) {
diff --git a/src/java/org/apache/fop/render/intermediate/IFSerializer.java b/src/java/org/apache/fop/render/intermediate/IFSerializer.java
index 471a982ca..a4431b972 100644
--- a/src/java/org/apache/fop/render/intermediate/IFSerializer.java
+++ b/src/java/org/apache/fop/render/intermediate/IFSerializer.java
@@ -31,16 +31,13 @@ import java.util.Locale;
import java.util.Map;
import org.w3c.dom.Document;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import org.apache.xmlgraphics.util.QName;
import org.apache.xmlgraphics.util.XMLizable;
-import org.apache.fop.accessibility.StructureTree;
+import org.apache.fop.accessibility.StructureTreeEventHandler;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.render.PrintRendererConfigurator;
import org.apache.fop.render.RenderingContext;
@@ -54,9 +51,11 @@ import org.apache.fop.traits.BorderProps;
import org.apache.fop.traits.RuleStyle;
import org.apache.fop.util.ColorUtil;
import org.apache.fop.util.DOM2SAX;
+import org.apache.fop.util.LanguageTags;
import org.apache.fop.util.XMLConstants;
import org.apache.fop.util.XMLUtil;
+
/**
* IFPainter implementation that serializes the intermediate format to XML.
*/
@@ -71,11 +70,7 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
private String currentID = "";
- /**
- * Default constructor.
- */
- public IFSerializer() {
- }
+ private IFStructureTreeBuilder structureTreeBuilder;
/** {@inheritDoc} */
@Override
@@ -150,6 +145,14 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
}
}
+ @Override
+ public StructureTreeEventHandler getStructureTreeEventHandler() {
+ if (structureTreeBuilder == null) {
+ structureTreeBuilder = new IFStructureTreeBuilder();
+ }
+ return structureTreeBuilder;
+ }
+
/** {@inheritDoc} */
@Override
public void startDocument() throws IFException {
@@ -166,6 +169,19 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
}
}
+ @Override
+ public void setDocumentLocale(Locale locale) {
+ AttributesImpl atts = new AttributesImpl();
+ atts.addAttribute(XML_NAMESPACE, "lang", "xml:lang", XMLUtil.CDATA,
+ LanguageTags.toLanguageTag(locale));
+ try {
+ handler.startElement(EL_LOCALE, atts);
+ handler.endElement(EL_LOCALE);
+ } catch (SAXException e) {
+ throw new RuntimeException("Unable to create the " + EL_LOCALE + " element.", e);
+ }
+ }
+
/** {@inheritDoc} */
@Override
public void startDocumentHeader() throws IFException {
@@ -227,20 +243,14 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
Locale lang = getContext().getLanguage();
if (lang != null) {
atts.addAttribute(XML_NAMESPACE, "lang", "xml:lang", XMLUtil.CDATA,
- XMLUtil.toRFC3066(lang));
+ LanguageTags.toLanguageTag(lang));
}
XMLUtil.addAttribute(atts, XMLConstants.XML_SPACE, "preserve");
addForeignAttributes(atts);
handler.startElement(EL_PAGE_SEQUENCE, atts);
if (this.getUserAgent().isAccessibilityEnabled()) {
- StructureTree structureTree = getUserAgent().getStructureTree();
- handler.startElement(EL_STRUCTURE_TREE); // add structure tree
- NodeList nodes = structureTree.getPageSequence(pageSequenceIndex++);
- for (int i = 0, n = nodes.getLength(); i < n; i++) {
- Node node = nodes.item(i);
- new DOM2SAX(handler).writeFragment(node);
- }
- handler.endElement(EL_STRUCTURE_TREE);
+ assert (structureTreeBuilder != null);
+ structureTreeBuilder.replayEventsForPageSequence(handler, pageSequenceIndex++);
}
} catch (SAXException e) {
throw new IFException("SAX error in startPageSequence()", e);
@@ -250,6 +260,7 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
/** {@inheritDoc} */
public void endPageSequence() throws IFException {
try {
+
handler.endElement(EL_PAGE_SEQUENCE);
} catch (SAXException e) {
throw new IFException("SAX error in endPageSequence()", e);
@@ -806,5 +817,4 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
throw new IFException("SAX error serializing object", e);
}
}
-
}
diff --git a/src/java/org/apache/fop/render/intermediate/IFSerializerMaker.java b/src/java/org/apache/fop/render/intermediate/IFSerializerMaker.java
index 699fd0549..c0060ab8e 100644
--- a/src/java/org/apache/fop/render/intermediate/IFSerializerMaker.java
+++ b/src/java/org/apache/fop/render/intermediate/IFSerializerMaker.java
@@ -31,6 +31,9 @@ public class IFSerializerMaker extends AbstractIFDocumentHandlerMaker {
public IFDocumentHandler makeIFDocumentHandler(FOUserAgent ua) {
IFSerializer handler = new IFSerializer();
handler.setContext(new IFContext(ua));
+ if (ua.isAccessibilityEnabled()) {
+ ua.setStructureTreeEventHandler(handler.getStructureTreeEventHandler());
+ }
return handler;
}
diff --git a/src/java/org/apache/fop/render/intermediate/IFStructureTreeBuilder.java b/src/java/org/apache/fop/render/intermediate/IFStructureTreeBuilder.java
new file mode 100644
index 000000000..66457681f
--- /dev/null
+++ b/src/java/org/apache/fop/render/intermediate/IFStructureTreeBuilder.java
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.intermediate;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import org.apache.fop.accessibility.StructureTree2SAXEventAdapter;
+import org.apache.fop.accessibility.StructureTreeEventHandler;
+
+/**
+ * Saves structure tree events as SAX events in order to replay them when it's
+ * time to stream the structure tree to the output.
+ */
+final class IFStructureTreeBuilder implements StructureTreeEventHandler {
+
+ 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);
+ }
+
+ /** {@inheritDoc} */
+ public void endPageSequence() {
+ delegate.endPageSequence();
+ }
+
+ /** {@inheritDoc} */
+ public void startNode(String name, Attributes attributes) {
+ delegate.startNode(name, attributes);
+ }
+
+ /** {@inheritDoc} */
+ public void endNode(String name) {
+ delegate.endNode(name);
+ }
+
+ /** A SAX handler that records events to replay them later. */
+ static class SAXEventRecorder extends DefaultHandler {
+
+ private final List<SAXEventRecorder.Event> events = new ArrayList<SAXEventRecorder.Event>();
+
+ private abstract static class Event {
+ abstract void replay(ContentHandler handler) throws SAXException;
+ }
+
+ private abstract static class Element extends SAXEventRecorder.Event {
+
+ protected final String uri;
+ protected final String localName;
+ protected final String qName;
+
+ private Element(String uri, String localName, String qName) {
+ this.uri = uri;
+ this.localName = localName;
+ this.qName = qName;
+ }
+ }
+
+ private static final class StartElement extends SAXEventRecorder.Element {
+
+ private final Attributes attributes;
+
+ private StartElement(String uri, String localName, String qName,
+ Attributes attributes) {
+ super(uri, localName, qName);
+ this.attributes = attributes;
+ }
+
+ @Override
+ void replay(ContentHandler handler) throws SAXException {
+ handler.startElement(uri, localName, qName, attributes);
+ }
+ }
+
+ private static final class EndElement extends SAXEventRecorder.Element {
+
+ private EndElement(String uri, String localName, String qName) {
+ super(uri, localName, qName);
+ }
+
+ @Override
+ void replay(ContentHandler handler) throws SAXException {
+ handler.endElement(uri, localName, qName);
+ }
+ }
+
+ private static final class StartPrefixMapping extends SAXEventRecorder.Event {
+
+ protected final String prefix;
+ protected final String uri;
+
+ private StartPrefixMapping(String prefix, String uri) {
+ this.prefix = prefix;
+ this.uri = uri;
+ }
+
+ @Override
+ void replay(ContentHandler handler) throws SAXException {
+ handler.startPrefixMapping(prefix, uri);
+ }
+ }
+
+ private static final class EndPrefixMapping extends SAXEventRecorder.Event {
+
+ protected final String prefix;
+
+ private EndPrefixMapping(String prefix) {
+ this.prefix = prefix;
+ }
+
+ @Override
+ void replay(ContentHandler handler) throws SAXException {
+ handler.endPrefixMapping(prefix);
+ }
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName,
+ Attributes attributes) throws SAXException {
+ events.add(new StartElement(uri, localName, qName, attributes));
+ };
+
+ @Override
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ events.add(new EndElement(uri, localName, qName));
+ };
+
+ @Override
+ public void startPrefixMapping(String prefix, String uri) throws SAXException {
+ events.add(new StartPrefixMapping(prefix, uri));
+ };
+
+ @Override
+ public void endPrefixMapping(String prefix) throws SAXException {
+ events.add(new EndPrefixMapping(prefix));
+ };
+
+ /**
+ * Replays the recorded events.
+ *
+ * @param handler {@code ContentHandler} to replay events on
+ */
+ public void replay(ContentHandler handler) throws SAXException {
+ for (SAXEventRecorder.Event e : events) {
+ e.replay(handler);
+ }
+ }
+ }
+}
diff --git a/src/java/org/apache/fop/render/intermediate/util/IFDocumentHandlerProxy.java b/src/java/org/apache/fop/render/intermediate/util/IFDocumentHandlerProxy.java
index 3d89e812e..64c876fb1 100644
--- a/src/java/org/apache/fop/render/intermediate/util/IFDocumentHandlerProxy.java
+++ b/src/java/org/apache/fop/render/intermediate/util/IFDocumentHandlerProxy.java
@@ -20,9 +20,12 @@
package org.apache.fop.render.intermediate.util;
import java.awt.Dimension;
+import java.util.Locale;
import javax.xml.transform.Result;
+import org.apache.fop.accessibility.DummyStructureTreeEventHandler;
+import org.apache.fop.accessibility.StructureTreeEventHandler;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.render.intermediate.IFContext;
import org.apache.fop.render.intermediate.IFDocumentHandler;
@@ -94,6 +97,11 @@ public class IFDocumentHandlerProxy implements IFDocumentHandler {
}
/** {@inheritDoc} */
+ public StructureTreeEventHandler getStructureTreeEventHandler() {
+ return DummyStructureTreeEventHandler.INSTANCE;
+ }
+
+ /** {@inheritDoc} */
public void setResult(Result result) throws IFException {
this.delegate.setResult(result);
}
@@ -104,6 +112,12 @@ public class IFDocumentHandlerProxy implements IFDocumentHandler {
}
/** {@inheritDoc} */
+ public void setDocumentLocale(Locale locale) {
+ this.delegate.setDocumentLocale(locale);
+
+ }
+
+ /** {@inheritDoc} */
public void startDocumentHeader() throws IFException {
this.delegate.startDocumentHeader();
}
@@ -184,4 +198,4 @@ public class IFDocumentHandlerProxy implements IFDocumentHandler {
this.delegate.handleExtensionObject(extension);
}
-} \ No newline at end of file
+}
diff --git a/src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java b/src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java
index 26595bca1..c773b1339 100644
--- a/src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java
+++ b/src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java
@@ -22,8 +22,6 @@ package org.apache.fop.render.pdf;
import java.util.HashMap;
import java.util.Map;
-import org.w3c.dom.Node;
-
import org.apache.fop.events.EventBroadcaster;
import org.apache.fop.pdf.PDFName;
import org.apache.fop.pdf.PDFObject;
@@ -37,9 +35,9 @@ final class FOToPDFRoleMap {
/**
* Standard structure types defined by the PDF Reference, Fourth Edition (PDF 1.5).
*/
- private static final Map STANDARD_STRUCTURE_TYPES = new HashMap();
+ private static final Map<String, PDFName> STANDARD_STRUCTURE_TYPES = new HashMap<String, PDFName>();
- private static final Map DEFAULT_MAPPINGS = new java.util.HashMap();
+ private static final Map<String, Mapper> DEFAULT_MAPPINGS = new java.util.HashMap<String, Mapper>();
private static final PDFName THEAD;
private static final PDFName NON_STRUCT;
@@ -172,7 +170,7 @@ final class FOToPDFRoleMap {
* @return the structure type or null if no match could be found
*/
public static PDFName mapFormattingObject(String fo, PDFObject parent) {
- Mapper mapper = (Mapper)DEFAULT_MAPPINGS.get(fo);
+ Mapper mapper = (Mapper) DEFAULT_MAPPINGS.get(fo);
if (mapper != null) {
return mapper.getStructureType(parent);
} else {
@@ -180,27 +178,32 @@ final class FOToPDFRoleMap {
}
}
- public static PDFName mapFormattingObject(Node fo, PDFObject parent,
- EventBroadcaster eventBroadcaster) {
+ /**
+ * Maps a Formatting Object to a PDFName representing the associated structure type.
+ * @param fo the formatting object's local name
+ * @param role the value of the formatting object's role property
+ * @param parent the parent of the structure element to be mapped
+ * @param eventBroadcaster the event broadcaster
+ * @return the structure type or null if no match could be found
+ */
+ public static PDFName mapFormattingObject(String fo, String role,
+ PDFObject parent, EventBroadcaster eventBroadcaster) {
PDFName type = null;
- Node role = fo.getAttributes().getNamedItemNS(null, "role");
if (role == null) {
- type = mapFormattingObject(fo.getLocalName(), parent);
+ type = mapFormattingObject(fo, parent);
} else {
- String customType = role.getNodeValue();
- type = (PDFName) STANDARD_STRUCTURE_TYPES.get(customType);
+ type = (PDFName) STANDARD_STRUCTURE_TYPES.get(role);
if (type == null) {
- String foName = fo.getLocalName();
- type = mapFormattingObject(foName, parent);
+ type = mapFormattingObject(fo, parent);
PDFEventProducer.Provider.get(eventBroadcaster).nonStandardStructureType(fo,
- foName, customType, type.toString().substring(1));
+ fo, role, type.toString().substring(1));
}
}
assert type != null;
return type;
}
- private static interface Mapper {
+ private interface Mapper {
PDFName getStructureType(PDFObject parent);
}
@@ -222,7 +225,7 @@ final class FOToPDFRoleMap {
public PDFName getStructureType(PDFObject parent) {
PDFStructElem grandParent = (PDFStructElem)
- ((PDFStructElem)parent).getParentStructElem();
+ ((PDFStructElem) parent).getParentStructElem();
//TODO What to do with cells from table-footer? Currently they are mapped on TD.
PDFName type;
if (THEAD.equals(grandParent.getStructureType())) {
diff --git a/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java b/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java
index c1d959dd1..5be8c3001 100644
--- a/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java
+++ b/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java
@@ -25,15 +25,16 @@ import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
+import java.util.HashMap;
+import java.util.Locale;
import java.util.Map;
-import org.w3c.dom.NodeList;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.xmp.Metadata;
+import org.apache.fop.accessibility.StructureTreeEventHandler;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.fo.extensions.xmp.XMPMetadata;
import org.apache.fop.pdf.PDFAnnotList;
@@ -45,28 +46,26 @@ import org.apache.fop.render.extensions.prepress.PageBoundaries;
import org.apache.fop.render.extensions.prepress.PageScale;
import org.apache.fop.render.intermediate.AbstractBinaryWritingIFDocumentHandler;
import org.apache.fop.render.intermediate.IFContext;
-import org.apache.fop.render.intermediate.IFDocumentHandler;
import org.apache.fop.render.intermediate.IFDocumentHandlerConfigurator;
import org.apache.fop.render.intermediate.IFDocumentNavigationHandler;
import org.apache.fop.render.intermediate.IFException;
import org.apache.fop.render.intermediate.IFPainter;
import org.apache.fop.render.pdf.extensions.PDFEmbeddedFileExtensionAttachment;
-import org.apache.fop.util.XMLUtil;
/**
- * {@link IFDocumentHandler} implementation that produces PDF.
+ * {@link org.apache.fop.render.intermediate.IFDocumentHandler} implementation that produces PDF.
*/
public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler {
/** logging instance */
private static Log log = LogFactory.getLog(PDFDocumentHandler.class);
- private int pageSequenceIndex;
-
private boolean accessEnabled;
private PDFLogicalStructureHandler logicalStructureHandler;
+ private PDFStructureTreeBuilder structureTreeBuilder;
+
/** the PDF Document being created */
protected PDFDocument pdfDoc;
@@ -92,8 +91,7 @@ public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler {
protected PageReference currentPageRef;
/** Used for bookmarks/outlines. */
- protected Map<Integer, PageReference> pageReferences
- = new java.util.HashMap<Integer, PageReference>();
+ protected Map<Integer, PageReference> pageReferences = new HashMap<Integer, PageReference>();
private final PDFDocumentNavigationHandler documentNavigationHandler
= new PDFDocumentNavigationHandler(this);
@@ -145,15 +143,23 @@ public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler {
this.pdfDoc = pdfUtil.setupPDFDocument(this.outputStream);
this.accessEnabled = getUserAgent().isAccessibilityEnabled();
if (accessEnabled) {
- pdfDoc.getRoot().makeTagged();
- logicalStructureHandler = new PDFLogicalStructureHandler(pdfDoc,
- getUserAgent().getEventBroadcaster());
+ setupAccessibility();
}
} catch (IOException e) {
throw new IFException("I/O error in startDocument()", e);
}
}
+ private void setupAccessibility() {
+ pdfDoc.getRoot().makeTagged();
+ logicalStructureHandler = new PDFLogicalStructureHandler(pdfDoc);
+ // TODO this is ugly. All the necessary information should be available
+ // at creation time in order to enforce immutability
+ structureTreeBuilder.setPdfFactory(pdfDoc.getFactory());
+ structureTreeBuilder.setLogicalStructureHandler(logicalStructureHandler);
+ structureTreeBuilder.setEventBroadcaster(getUserAgent().getEventBroadcaster());
+ }
+
/** {@inheritDoc} */
public void endDocumentHeader() throws IFException {
pdfUtil.generateDefaultXMPMetadata();
@@ -178,18 +184,7 @@ public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler {
/** {@inheritDoc} */
public void startPageSequence(String id) throws IFException {
- //TODO page sequence title
-
- if (this.pdfDoc.getRoot().getLanguage() == null
- && getContext().getLanguage() != null) {
- //No document-level language set, so we use the first page-sequence's language
- this.pdfDoc.getRoot().setLanguage(XMLUtil.toRFC3066(getContext().getLanguage()));
- }
-
- if (accessEnabled) {
- NodeList nodes = getUserAgent().getStructureTree().getPageSequence(pageSequenceIndex++);
- logicalStructureHandler.processStructureTree(nodes, getContext().getLanguage());
- }
+ //nop
}
/** {@inheritDoc} */
@@ -289,9 +284,9 @@ public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler {
/** {@inheritDoc} */
public void handleExtensionObject(Object extension) throws IFException {
if (extension instanceof XMPMetadata) {
- pdfUtil.renderXMPMetadata((XMPMetadata)extension);
+ pdfUtil.renderXMPMetadata((XMPMetadata) extension);
} else if (extension instanceof Metadata) {
- XMPMetadata wrapper = new XMPMetadata(((Metadata)extension));
+ XMPMetadata wrapper = new XMPMetadata(((Metadata) extension));
pdfUtil.renderXMPMetadata(wrapper);
} else if (extension instanceof PDFEmbeddedFileExtensionAttachment) {
PDFEmbeddedFileExtensionAttachment embeddedFile
@@ -307,6 +302,11 @@ public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler {
}
}
+ /** {@inheritDoc} */
+ public void setDocumentLocale(Locale locale) {
+ pdfDoc.getRoot().setLanguage(locale);
+ }
+
PageReference getPageReference(int pageIndex) {
return this.pageReferences.get(Integer.valueOf(pageIndex));
}
@@ -332,4 +332,11 @@ public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler {
}
}
+ @Override
+ public StructureTreeEventHandler getStructureTreeEventHandler() {
+ if (structureTreeBuilder == null) {
+ structureTreeBuilder = new PDFStructureTreeBuilder();
+ }
+ return structureTreeBuilder;
+ }
}
diff --git a/src/java/org/apache/fop/render/pdf/PDFDocumentHandlerMaker.java b/src/java/org/apache/fop/render/pdf/PDFDocumentHandlerMaker.java
index f4ba03d5b..1186db3ae 100644
--- a/src/java/org/apache/fop/render/pdf/PDFDocumentHandlerMaker.java
+++ b/src/java/org/apache/fop/render/pdf/PDFDocumentHandlerMaker.java
@@ -36,6 +36,9 @@ public class PDFDocumentHandlerMaker extends AbstractIFDocumentHandlerMaker {
public IFDocumentHandler makeIFDocumentHandler(FOUserAgent ua) {
PDFDocumentHandler handler = new PDFDocumentHandler();
handler.setContext(new IFContext(ua));
+ if (ua.isAccessibilityEnabled()) {
+ ua.setStructureTreeEventHandler(handler.getStructureTreeEventHandler());
+ }
return handler;
}
diff --git a/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java b/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java
index ce86f4849..d49ef4a3e 100644
--- a/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java
+++ b/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java
@@ -23,12 +23,6 @@ import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-import org.apache.fop.events.EventBroadcaster;
-import org.apache.fop.fo.extensions.ExtensionElementMapping;
-import org.apache.fop.fo.extensions.InternalElementMapping;
import org.apache.fop.pdf.PDFArray;
import org.apache.fop.pdf.PDFDictionary;
import org.apache.fop.pdf.PDFDocument;
@@ -53,12 +47,10 @@ class PDFLogicalStructureHandler {
private final PDFDocument pdfDoc;
- private final EventBroadcaster eventBroadcaster;
-
/**
* Map of references to the corresponding structure elements.
*/
- private final Map structTreeMap = new HashMap();
+ private final Map<String, PDFStructElem> structTreeMap = new HashMap<String, PDFStructElem>();
private final PDFParentTree parentTree = new PDFParentTree();
@@ -108,23 +100,16 @@ class PDFLogicalStructureHandler {
*
* @param pdfDoc a document
*/
- PDFLogicalStructureHandler(PDFDocument pdfDoc, EventBroadcaster eventBroadcaster) {
+ PDFLogicalStructureHandler(PDFDocument pdfDoc) {
this.pdfDoc = pdfDoc;
- this.eventBroadcaster = eventBroadcaster;
PDFStructTreeRoot structTreeRoot = pdfDoc.getFactory().makeStructTreeRoot(parentTree);
rootStructureElement = pdfDoc.getFactory().makeStructureElement(
FOToPDFRoleMap.mapFormattingObject("root", structTreeRoot), structTreeRoot);
structTreeRoot.addKid(rootStructureElement);
}
- /**
- * Converts the given structure tree into PDF.
- *
- * @param structureTree the structure tree of the current page sequence
- * @param language language set on the page sequence
- */
- void processStructureTree(NodeList structureTree, Locale language) {
- pdfDoc.enforceLanguageOnRoot();
+
+ PDFStructElem createPageSequence(Locale language) {
PDFStructElem structElemPart = pdfDoc.getFactory().makeStructureElement(
FOToPDFRoleMap.mapFormattingObject("page-sequence", rootStructureElement),
rootStructureElement);
@@ -132,50 +117,7 @@ class PDFLogicalStructureHandler {
if (language != null) {
structElemPart.setLanguage(language);
}
-
- for (int i = 0, n = structureTree.getLength(); i < n; i++) {
- Node node = structureTree.item(i);
- assert node.getLocalName().equals("flow")
- || node.getLocalName().equals("static-content");
- PDFStructElem structElemSect = pdfDoc.getFactory().makeStructureElement(
- FOToPDFRoleMap.mapFormattingObject(node.getLocalName(), structElemPart),
- structElemPart);
- structElemPart.addKid(structElemSect);
- NodeList childNodes = node.getChildNodes();
- for (int j = 0, m = childNodes.getLength(); j < m; j++) {
- processNode(childNodes.item(j), structElemSect, true);
- }
- }
- }
-
- private void processNode(Node node, PDFStructElem parent, boolean addKid) {
- PDFStructElem structElem = pdfDoc.getFactory().makeStructureElement(
- FOToPDFRoleMap.mapFormattingObject(node, parent, eventBroadcaster), parent);
- // TODO necessary? If a page-sequence is empty (e.g., contains a single
- // empty fo:block), should the block still be added to the structure
- // tree? This is not being done for descendant empty elements...
- if (addKid) {
- parent.addKid(structElem);
- }
- String nodeName = node.getLocalName();
- if (nodeName.equals("external-graphic") || nodeName.equals("instream-foreign-object")) {
- Node altTextNode = node.getAttributes().getNamedItemNS(
- ExtensionElementMapping.URI, "alt-text");
- if (altTextNode != null) {
- structElem.put("Alt", altTextNode.getNodeValue());
- } else {
- structElem.put("Alt", "No alternate text specified");
- }
- }
- Node attr = node.getAttributes().getNamedItemNS(InternalElementMapping.URI, "ptr");
- if (attr != null) {
- String ptr = attr.getNodeValue();
- structTreeMap.put(ptr, structElem);
- }
- NodeList nodes = node.getChildNodes();
- for (int i = 0, n = nodes.getLength(); i < n; i++) {
- processNode(nodes.item(i), structElem, false);
- }
+ return structElemPart;
}
private int getNextParentTreeKey() {
@@ -301,4 +243,8 @@ class PDFLogicalStructureHandler {
parent.addKid(contentItem);
}
+ void addStructurePointer(String ptr, PDFStructElem structElem) {
+ structTreeMap.put(ptr, structElem);
+ }
+
}
diff --git a/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java b/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java
new file mode 100644
index 000000000..8ec10b209
--- /dev/null
+++ b/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.pdf;
+
+import java.util.LinkedList;
+import java.util.Locale;
+
+import org.xml.sax.Attributes;
+
+import org.apache.fop.accessibility.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;
+
+class PDFStructureTreeBuilder implements StructureTreeEventHandler {
+
+ private PDFFactory pdfFactory;
+
+ private PDFLogicalStructureHandler logicalStructureHandler;
+
+ private EventBroadcaster eventBroadcaster;
+
+ private LinkedList<PDFStructElem> ancestors = new LinkedList<PDFStructElem>();
+
+ void setPdfFactory(PDFFactory pdfFactory) {
+ this.pdfFactory = pdfFactory;
+ }
+
+ void setLogicalStructureHandler(PDFLogicalStructureHandler logicalStructureHandler) {
+ this.logicalStructureHandler = logicalStructureHandler;
+ }
+
+ void setEventBroadcaster(EventBroadcaster eventBroadcaster) {
+ this.eventBroadcaster = eventBroadcaster;
+ }
+
+ public void startPageSequence(Locale locale) {
+ ancestors = new LinkedList<PDFStructElem>();
+ ancestors.add(logicalStructureHandler.createPageSequence(locale));
+ }
+
+ public void endPageSequence() {
+ }
+
+ public void 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);
+ }
+
+ 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");
+ }
+ }
+ ancestors.addFirst(created);
+ }
+
+ public void endNode(String name) {
+ ancestors.removeFirst();
+ }
+
+}
diff --git a/src/java/org/apache/fop/render/xml/XMLRenderer.java b/src/java/org/apache/fop/render/xml/XMLRenderer.java
index 21d28042d..2a62d2cea 100644
--- a/src/java/org/apache/fop/render/xml/XMLRenderer.java
+++ b/src/java/org/apache/fop/render/xml/XMLRenderer.java
@@ -35,9 +35,6 @@ import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
import org.xml.sax.SAXException;
import org.apache.xmlgraphics.util.QName;
@@ -75,23 +72,20 @@ import org.apache.fop.area.inline.Image;
import org.apache.fop.area.inline.InlineArea;
import org.apache.fop.area.inline.InlineBlockParent;
import org.apache.fop.area.inline.InlineParent;
+import org.apache.fop.area.inline.InlineViewport;
import org.apache.fop.area.inline.Leader;
import org.apache.fop.area.inline.Space;
import org.apache.fop.area.inline.SpaceArea;
import org.apache.fop.area.inline.TextArea;
-import org.apache.fop.area.inline.InlineViewport;
import org.apache.fop.area.inline.WordArea;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.extensions.ExtensionAttachment;
-import org.apache.fop.fo.extensions.ExtensionElementMapping;
-import org.apache.fop.fo.extensions.InternalElementMapping;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.render.Renderer;
import org.apache.fop.render.RendererContext;
import org.apache.fop.render.XMLHandler;
import org.apache.fop.util.ColorUtil;
-import org.apache.fop.util.DOM2SAX;
/**
* Renderer that renders areas to XML for debugging purposes.
@@ -461,29 +455,6 @@ public class XMLRenderer extends AbstractXMLRenderer {
}
transferForeignObjects(pageSequence);
startElement("pageSequence", atts);
- if (this.getUserAgent().isAccessibilityEnabled()) {
- String structureTreeElement = "structureTree";
- startElement(structureTreeElement);
- try {
- this.handler.startPrefixMapping("foi", InternalElementMapping.URI);
- this.handler.startPrefixMapping("fox", ExtensionElementMapping.URI);
- NodeList nodes = getUserAgent().getStructureTree().getPageSequence(
- pageSequenceIndex++);
- for (int i = 0, n = nodes.getLength(); i < n; i++) {
- Node node = nodes.item(i);
- try {
- new DOM2SAX(handler).writeFragment(node);
- } catch (SAXException e) {
- handleSAXException(e);
- }
- }
- this.handler.endPrefixMapping("fox");
- this.handler.endPrefixMapping("foi");
- } catch (SAXException se) {
- handleSAXException(se);
- }
- endElement(structureTreeElement);
- }
handleExtensionAttachments(pageSequence.getExtensionAttachments());
LineArea seqTitle = pageSequence.getTitle();
if (seqTitle != null) {
diff --git a/src/java/org/apache/fop/util/LanguageTags.java b/src/java/org/apache/fop/util/LanguageTags.java
new file mode 100644
index 000000000..070fa15db
--- /dev/null
+++ b/src/java/org/apache/fop/util/LanguageTags.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.util;
+
+import java.util.Locale;
+
+/**
+ * Provides utility methods for manipulating language tags compliant with the
+ * RFC 3066 specification available at http://www.ietf.org/rfc/rfc3066.txt. A
+ * typical language tag is a 2-letter language code sometimes followed by a country
+ * code. For example: en, en-US.
+ */
+public final class LanguageTags {
+
+ private LanguageTags() {
+ }
+
+ /**
+ * Converts the given locale to an RFC 3066 compliant language tag.
+ *
+ * @param locale a locale
+ * @return the corresponding language tag
+ * @throws NullPointerException if the specified locale is null
+ */
+ public static String toLanguageTag(Locale locale) {
+ StringBuffer sb = new StringBuffer(5);
+ sb.append(locale.getLanguage());
+ String country = locale.getCountry();
+ if (country.length() > 0) {
+ sb.append('-');
+ sb.append(country);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Converts an RFC 3066 compliant language tag to a locale.
+ *
+ * @throws NullPointerException if the specified language tag is null
+ */
+ public static Locale toLocale(String languageTag) {
+ String[] parts = languageTag.split("-");
+ if (parts.length == 1) {
+ return new Locale(parts[0]);
+ } else {
+ return new Locale(parts[0], parts[1]);
+ }
+ }
+}
diff --git a/src/java/org/apache/fop/util/XMLUtil.java b/src/java/org/apache/fop/util/XMLUtil.java
index 0a55ce573..d4397c2c7 100644
--- a/src/java/org/apache/fop/util/XMLUtil.java
+++ b/src/java/org/apache/fop/util/XMLUtil.java
@@ -21,7 +21,6 @@ package org.apache.fop.util;
import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;
-import java.util.Locale;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
@@ -174,39 +173,4 @@ public final class XMLUtil implements XMLConstants {
atts.addAttribute("", localName, localName, XMLUtil.CDATA, value);
}
- /**
- * Converts a {@link Locale} instance to an RFC 3066 compliant language identifier.
- * @param language the language
- * @return the formatted language identifier
- */
- public static String toRFC3066(Locale language) {
- if (language == null || language.getLanguage().length() == 0) {
- return null;
- }
- StringBuffer sb = new StringBuffer();
- sb.append(language.getLanguage());
- if (language.getCountry().length() > 0) {
- sb.append('-');
- sb.append(language.getCountry());
- }
- return sb.toString();
- }
-
- /**
- * Converts an RFC 3066 compliant language identifier to a {@link Locale} instance.
- * @param lang the language string
- * @return the converted locale instance
- */
- public static Locale convertRFC3066ToLocale(String lang) {
- if (lang == null || lang.length() == 0) {
- return null;
- }
- String[] parts = lang.split("-");
- if (parts.length == 1) {
- return new Locale(parts[0]);
- } else {
- return new Locale(parts[0], parts[1]);
- }
- }
-
}