diff options
author | Vincent Hennebert <vhennebert@apache.org> | 2009-09-22 11:49:06 +0000 |
---|---|---|
committer | Vincent Hennebert <vhennebert@apache.org> | 2009-09-22 11:49:06 +0000 |
commit | dbaf63a64da3aaa4ecc1dc6de510cca85617a51a (patch) | |
tree | 178577f0e28833e2d4469f92b073ee2633227c01 /src/java | |
parent | 0e5a789b6b0604bb9c6cc9b782c22f490917e9f9 (diff) | |
download | xmlgraphics-fop-dbaf63a64da3aaa4ecc1dc6de510cca85617a51a.tar.gz xmlgraphics-fop-dbaf63a64da3aaa4ecc1dc6de510cca85617a51a.zip |
Factorized into a new class the parsing of the reduced FO tree, that was duplicated in IFSerializer and PDFDocumentHandler.
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_Accessibility@817617 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java')
5 files changed, 157 insertions, 198 deletions
diff --git a/src/java/org/apache/fop/accessibility/StructureTree.java b/src/java/org/apache/fop/accessibility/StructureTree.java new file mode 100644 index 000000000..0be785eb2 --- /dev/null +++ b/src/java/org/apache/fop/accessibility/StructureTree.java @@ -0,0 +1,98 @@ +/* + * 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.Iterator; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +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 Node reducedFOTree; + + private static class NamespaceContextImpl implements NamespaceContext { + + private String uri; + private String prefix; + + public NamespaceContextImpl() { + } + + public NamespaceContextImpl(String prefix, String uri) { + this.uri = uri; + this.prefix = prefix; + } + + public String getNamespaceURI(String prefix) { + return uri; + } + + public void setNamespaceURI(String uri) { + this.uri = uri; + } + + public String getPrefix(String uri) { + return prefix; + } + + public void setPrefix(String prefix) { + this.prefix = prefix; + } + + public Iterator getPrefixes(String uri) { + return null; + } + } + + StructureTree(Node reducedFOTree) { + this.reducedFOTree = reducedFOTree; + } + + /** + * Returns the list of nodes that are the children of the given page sequence. + * + * @param number number of the page sequence, 1-based + * @return its children nodes + */ + public NodeList getPageSequence(int number) { + XPath xpath = XPathFactory.newInstance().newXPath(); + NamespaceContext namespaceContext = new NamespaceContextImpl("fo", + "http://www.w3.org/1999/XSL/Format"); + xpath.setNamespaceContext(namespaceContext); + String xpathExpr = "/fo:root/fo:page-sequence[" + Integer.toString(number) + "]/*"; + + try { + return (NodeList) xpath.evaluate(xpathExpr, reducedFOTree, XPathConstants.NODESET); + } catch (XPathExpressionException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/java/org/apache/fop/accessibility/TransformerNodeEndProcessing.java b/src/java/org/apache/fop/accessibility/TransformerNodeEndProcessing.java index 34974233a..c89f72623 100644 --- a/src/java/org/apache/fop/accessibility/TransformerNodeEndProcessing.java +++ b/src/java/org/apache/fop/accessibility/TransformerNodeEndProcessing.java @@ -28,14 +28,14 @@ import javax.xml.transform.Result; import javax.xml.transform.Source; import javax.xml.transform.Templates; import javax.xml.transform.Transformer; +import javax.xml.transform.dom.DOMResult; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; +import org.apache.commons.io.output.ByteArrayOutputStream; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; -import org.apache.commons.io.output.ByteArrayOutputStream; - import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; @@ -76,10 +76,9 @@ class TransformerNodeEndProcessing extends TransformerNode { byte[] enrichedFO = enrichedFOBuffer.toByteArray(); Transformer transformer = AccessibilityUtil.getReduceFOTreeTemplates().newTransformer(); Source src = new StreamSource(new ByteArrayInputStream(enrichedFO)); - ByteArrayOutputStream out = new ByteArrayOutputStream(); - Result res = new StreamResult(out); + DOMResult res = new DOMResult(); transformer.transform(src, res); - userAgent.setReducedFOTree(out.toByteArray()); + userAgent.setStructureTree(new StructureTree(res.getNode())); SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); saxParserFactory.setNamespaceAware(true); diff --git a/src/java/org/apache/fop/apps/FOUserAgent.java b/src/java/org/apache/fop/apps/FOUserAgent.java index 13db8d5ef..0ed5151e0 100644 --- a/src/java/org/apache/fop/apps/FOUserAgent.java +++ b/src/java/org/apache/fop/apps/FOUserAgent.java @@ -38,6 +38,7 @@ import org.apache.xmlgraphics.image.loader.impl.AbstractImageSessionContext; import org.apache.fop.Version; import org.apache.fop.accessibility.AccessibilityUtil; +import org.apache.fop.accessibility.StructureTree; import org.apache.fop.events.DefaultEventBroadcaster; import org.apache.fop.events.Event; import org.apache.fop.events.EventBroadcaster; @@ -100,8 +101,7 @@ public class FOUserAgent { private boolean conserveMemoryPolicy = false; private EventBroadcaster eventBroadcaster = new FOPEventBroadcaster(); - //TODO Verify that a byte array is the best solution here - private byte[] reducedFOTree; // accessibility: reduced FO + private StructureTree structureTree; /** Producer: Metadata element for the system/software that produces * the document. (Some renderers can store this in the document.) @@ -664,20 +664,24 @@ public class FOUserAgent { } /** - * Used for accessibility. Stores the reduced FO tree (the result from the second transform) - * for later use. - * @param reducedFOTree the result from 2nd transform + * Sets the document's structure tree, for use by accessible output formats. + * + * @param structureTree a simplified version of the FO tree, retaining only + * its logical structure */ - public void setReducedFOTree(byte[] reducedFOTree) { - this.reducedFOTree = reducedFOTree; + public void setStructureTree(StructureTree structureTree) { + this.structureTree = structureTree; } /** - * Used for accessibility. Returns the reduced FO tree. - * @return result from 2nd transform as byte array + * Returns the document's structure tree, for use by accessible output + * formats. + * + * @return a simplified version of the FO tree, retaining only its logical + * structure */ - public byte[] getReducedFOTree() { - return this.reducedFOTree; + public StructureTree getStructureTree() { + return this.structureTree; } } diff --git a/src/java/org/apache/fop/render/intermediate/IFSerializer.java b/src/java/org/apache/fop/render/intermediate/IFSerializer.java index 2d009d58d..281301fbe 100644 --- a/src/java/org/apache/fop/render/intermediate/IFSerializer.java +++ b/src/java/org/apache/fop/render/intermediate/IFSerializer.java @@ -25,33 +25,22 @@ import java.awt.Paint; import java.awt.Point; import java.awt.Rectangle; import java.awt.geom.AffineTransform; -import java.io.ByteArrayInputStream; -import java.io.IOException; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Stack; -import javax.xml.namespace.NamespaceContext; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.xpath.XPath; -import javax.xml.xpath.XPathConstants; -import javax.xml.xpath.XPathExpressionException; -import javax.xml.xpath.XPathFactory; - 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.fonts.FontInfo; import org.apache.fop.render.PrintRendererConfigurator; import org.apache.fop.render.RenderingContext; @@ -76,45 +65,10 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler private IFDocumentHandler mimicHandler; private int pageSequenceCounter; // used for accessibility - private DocumentBuilder parser = null; // used for accessibility - private Document doc = null; // used for accessibility /** Holds the intermediate format state */ private IFState state; - private static class NamespaceContextImpl implements NamespaceContext { - - public String uri; - public String prefix; - - public NamespaceContextImpl() { - } - - public NamespaceContextImpl(String prefix, String uri) { - this.uri = uri; - this.prefix = prefix; - } - - public String getNamespaceURI(String prefix) { - return uri; - } - public void setNamespaceURI(String uri) { - this.uri = uri; - } - - public String getPrefix(String uri) { - return prefix; - } - - public void setPrefix(String prefix) { - this.prefix = prefix; - } - public Iterator getPrefixes(String uri) { - return null; - } - - } - /** * Default constructor. */ @@ -202,16 +156,8 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler handler.startPrefixMapping(DocumentNavigationExtensionConstants.PREFIX, DocumentNavigationExtensionConstants.NAMESPACE); handler.startElement(EL_DOCUMENT); - if (this.getUserAgent().isAccessibilityEnabled()) { - pageSequenceCounter = 0; - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - parser = factory.newDocumentBuilder(); - } } catch (SAXException e) { throw new IFException("SAX error in startDocument()", e); - } catch (ParserConfigurationException pce) { - throw new IFException("Error creating new DocumentBuilder", pce); } } @@ -273,18 +219,9 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler addForeignAttributes(atts); handler.startElement(EL_PAGE_SEQUENCE, atts); if (this.getUserAgent().isAccessibilityEnabled()) { - if (doc == null) { - doc = parser.parse( - new ByteArrayInputStream(this.getUserAgent().getReducedFOTree())); - } + StructureTree structureTree = getUserAgent().getStructureTree(); handler.startElement(EL_STRUCTURE_TREE); // add structure tree - String xpathExpr - = "/fo:root/fo:page-sequence[" + Integer.toString(++pageSequenceCounter) + "]/*"; - XPath xpath = XPathFactory.newInstance().newXPath(); - NamespaceContext namespaceContext - = new NamespaceContextImpl("fo", "http://www.w3.org/1999/XSL/Format"); - xpath.setNamespaceContext(namespaceContext); - NodeList nodes = (NodeList)xpath.evaluate(xpathExpr, doc, XPathConstants.NODESET); + NodeList nodes = structureTree.getPageSequence(++pageSequenceCounter); for (int i = 0, n = nodes.getLength(); i < n; i++) { Node node = nodes.item(i); new DOM2SAX(handler).writeFragment(node); @@ -293,10 +230,6 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler } } catch (SAXException e) { throw new IFException("SAX error in startPageSequence()", e); - } catch (XPathExpressionException e) { - throw new IFException("Error while evaluating XPath expression", e); - } catch (IOException ioe) { - throw new IFException("I/O error while parsing structure tree", ioe); } } diff --git a/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java b/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java index 9e2b2cdb3..064682a3c 100644 --- a/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java +++ b/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java @@ -25,31 +25,19 @@ import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D.Double; -import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; -import javax.xml.namespace.NamespaceContext; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.xpath.XPath; -import javax.xml.xpath.XPathConstants; -import javax.xml.xpath.XPathExpressionException; -import javax.xml.xpath.XPathFactory; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; import org.apache.xmlgraphics.xmp.Metadata; +import org.apache.fop.accessibility.StructureTree; import org.apache.fop.apps.MimeConstants; import org.apache.fop.fo.extensions.xmp.XMPMetadata; import org.apache.fop.pdf.PDFAnnotList; @@ -86,8 +74,6 @@ public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler { /** the following variables are used for accessibility */ private int pageSequenceCounter; - private DocumentBuilder parser = null; - private Document reducedFOTree = null; private Map structElemType = new HashMap(); private boolean accessEnabled = false; private int parentTreeKey = -1; @@ -97,41 +83,6 @@ public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler { private Map structTreeMap = new HashMap(); private List parentTreeList = new java.util.ArrayList(); - private static class NamespaceContextImpl implements NamespaceContext { - - private String uri; - private String prefix; - - public NamespaceContextImpl() { - } - - public NamespaceContextImpl(String prefix, String uri) { - this.uri = uri; - this.prefix = prefix; - } - - public String getNamespaceURI(String prefix) { - return uri; - } - - public void setNamespaceURI(String uri) { - this.uri = uri; - } - - public String getPrefix(String uri) { - return prefix; - } - - public void setPrefix(String prefix) { - this.prefix = prefix; - } - - public Iterator getPrefixes(String uri) { - return null; - } - - } - private static final class ParentTreeEntry { private final int position; private final PDFObject object; @@ -233,14 +184,9 @@ public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler { parentTree = new PDFParentTree(); pageSequenceCounter = 0; - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - parser = factory.newDocumentBuilder(); } } catch (IOException e) { throw new IFException("I/O error in startDocument()", e); - } catch (ParserConfigurationException pce) { - throw new IFException("Error creating new DocumentBuilder", pce); } } @@ -271,8 +217,6 @@ public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler { parentTree.setNums(nums); getStructTreeRoot().addParentTree(parentTree); pdfDoc.outputTrailer(this.outputStream); - parser = null; - reducedFOTree = null; structElemType = null; parentTree = null; structTreeMap = null; @@ -308,65 +252,46 @@ public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler { } if (getUserAgent().isAccessibilityEnabled()) { - try { - if (this.pdfDoc.getRoot().getLanguage() == null) { - String fallbackLanguage; - if (this.pdfDoc.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"; - } - this.pdfDoc.getRoot().setLanguage(fallbackLanguage); + if (this.pdfDoc.getRoot().getLanguage() == null) { + String fallbackLanguage; + if (this.pdfDoc.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"; } + this.pdfDoc.getRoot().setLanguage(fallbackLanguage); + } - if (reducedFOTree == null) { - reducedFOTree = parser.parse( - new ByteArrayInputStream(this.getUserAgent().getReducedFOTree())); - } - PDFStructElem parent = (PDFStructElem)getStructTreeRoot().getFirstChild(); - PDFStructElem structElemPart = new PDFStructElem(parent, - FOToPDFRoleMap.mapFormattingObject("page-sequence", parent)); - if (getContext().getLanguage() != null) { - structElemPart.setLanguage(getContext().getLanguage()); - } - this.pdfDoc.assignObjectNumber(structElemPart); - this.pdfDoc.addTrailerObject(structElemPart); - parent.addKid(structElemPart); - - String xpathExpr = "/fo:root/fo:page-sequence[" - + Integer.toString(++pageSequenceCounter) + "]/*"; - XPath xpath = XPathFactory.newInstance().newXPath(); - NamespaceContext namespaceContext = new NamespaceContextImpl("fo", - "http://www.w3.org/1999/XSL/Format"); - xpath.setNamespaceContext(namespaceContext); - - NodeList nodes = (NodeList) xpath.evaluate(xpathExpr, reducedFOTree, - XPathConstants.NODESET); - - for (int i = 0, n = nodes.getLength(); i < n; i++) { - Node node = nodes.item(i); - if (node.getNodeName().equals("fo:flow") - || node.getNodeName().equals("fo:static-content")) { - PDFStructElem structElemSect = new PDFStructElem(structElemPart, - FOToPDFRoleMap.mapFormattingObject(node.getLocalName(), - structElemPart)); - this.pdfDoc.assignObjectNumber(structElemSect); - this.pdfDoc.addTrailerObject(structElemSect); - structElemPart.addKid(structElemSect); - NodeList iNodes = node.getChildNodes(); - for (int j = 0, m = iNodes.getLength(); j < m; j++) { - processContent(iNodes.item(j), structElemSect, 1); - } + StructureTree structureTree = getUserAgent().getStructureTree(); + PDFStructElem parent = (PDFStructElem)getStructTreeRoot().getFirstChild(); + PDFStructElem structElemPart = new PDFStructElem(parent, + FOToPDFRoleMap.mapFormattingObject("page-sequence", parent)); + if (getContext().getLanguage() != null) { + structElemPart.setLanguage(getContext().getLanguage()); + } + this.pdfDoc.assignObjectNumber(structElemPart); + this.pdfDoc.addTrailerObject(structElemPart); + parent.addKid(structElemPart); + + NodeList nodes = structureTree.getPageSequence(++pageSequenceCounter); + + for (int i = 0, n = nodes.getLength(); i < n; i++) { + Node node = nodes.item(i); + if (node.getNodeName().equals("fo:flow") + || node.getNodeName().equals("fo:static-content")) { + PDFStructElem structElemSect = new PDFStructElem(structElemPart, + FOToPDFRoleMap.mapFormattingObject(node.getLocalName(), + structElemPart)); + this.pdfDoc.assignObjectNumber(structElemSect); + this.pdfDoc.addTrailerObject(structElemSect); + structElemPart.addKid(structElemSect); + NodeList iNodes = node.getChildNodes(); + for (int j = 0, m = iNodes.getLength(); j < m; j++) { + processContent(iNodes.item(j), structElemSect, 1); } } - } catch (SAXException e) { - throw new IFException("SAX error in startPageSequence()", e); - } catch (XPathExpressionException e) { - throw new IFException("Error while evaluating XPath expression", e); - } catch (IOException ioe) { - throw new IFException("I/O error while parsing structure tree", ioe); } } } |