From d3551e5d341ef9ef2ba2091dd9aa91c279bd9515 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Tue, 13 Oct 2009 16:14:12 +0000 Subject: [PATCH] Implemented rendering of structure tree to Area Tree XML and parsing back from it git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_Accessibility@824827 13f79535-47bb-0310-9956-ffa450edef68 --- .../accessibility/ParsedStructureTree.java | 31 +++++++ .../org/apache/fop/area/AreaTreeParser.java | 82 ++++++++++++++++--- .../apache/fop/render/xml/XMLRenderer.java | 22 ++++- 3 files changed, 122 insertions(+), 13 deletions(-) diff --git a/src/java/org/apache/fop/accessibility/ParsedStructureTree.java b/src/java/org/apache/fop/accessibility/ParsedStructureTree.java index 69b26c21c..3aa95b627 100644 --- a/src/java/org/apache/fop/accessibility/ParsedStructureTree.java +++ b/src/java/org/apache/fop/accessibility/ParsedStructureTree.java @@ -19,13 +19,20 @@ 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.TransformerConfigurationException; +import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.dom.DOMSource; import javax.xml.transform.sax.SAXTransformerFactory; import javax.xml.transform.sax.TransformerHandler; +import javax.xml.transform.stream.StreamResult; import org.w3c.dom.NodeList; import org.xml.sax.ContentHandler; @@ -92,4 +99,28 @@ public class ParsedStructureTree implements StructureTree { return (NodeList) pageSequenceStructures.get(number - 1); } + /** + * Returns an XML-like representation of the structure trees. + *

+ * Note: use only for debugging purpose, as this method + * performs non-trivial operations. + *

+ * @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/area/AreaTreeParser.java b/src/java/org/apache/fop/area/AreaTreeParser.java index 25d110086..12e31530d 100644 --- a/src/java/org/apache/fop/area/AreaTreeParser.java +++ b/src/java/org/apache/fop/area/AreaTreeParser.java @@ -39,8 +39,6 @@ import javax.xml.transform.sax.SAXResult; import javax.xml.transform.sax.SAXTransformerFactory; import javax.xml.transform.sax.TransformerHandler; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.w3c.dom.DOMImplementation; import org.w3c.dom.Document; import org.xml.sax.Attributes; @@ -50,12 +48,16 @@ import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; import org.xml.sax.helpers.DefaultHandler; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import org.apache.xmlgraphics.image.loader.ImageException; import org.apache.xmlgraphics.image.loader.ImageInfo; import org.apache.xmlgraphics.image.loader.ImageManager; import org.apache.xmlgraphics.image.loader.ImageSessionContext; import org.apache.xmlgraphics.util.QName; +import org.apache.fop.accessibility.ParsedStructureTree; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.area.Trait.Background; import org.apache.fop.area.Trait.InternalLink; @@ -84,6 +86,7 @@ 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; @@ -157,6 +160,26 @@ public class AreaTreeParser { private Locator locator; + private ParsedStructureTree structureTree; + + private ContentHandler structureTreeBuilder; + + private final class StructureTreeBuilder extends DelegatingContentHandler { + + private Attributes pageSequenceAttributes; + + private StructureTreeBuilder(Attributes pageSequenceAttributes, + ParsedStructureTree structureTree) throws SAXException { + super(structureTree.getHandlerForNextPageSequence()); + this.pageSequenceAttributes = new AttributesImpl(pageSequenceAttributes); + } + + public void endDocument() throws SAXException { + super.endDocument(); + startAreaTreeElement("pageSequence", pageSequenceAttributes); + } + } + public Handler(AreaTreeModel treeModel, FOUserAgent userAgent, ElementMappingRegistry elementMappingRegistry) { this.treeModel = treeModel; @@ -193,6 +216,10 @@ public class AreaTreeParser { makers.put("bookmarkTree", new BookmarkTreeMaker()); makers.put("bookmark", new BookmarkMaker()); makers.put("destination", new DestinationMaker()); + if (userAgent.isAccessibilityEnabled()) { + structureTree = new ParsedStructureTree(tFactory); + userAgent.setStructureTree(structureTree); + } } private Area findAreaType(Class clazz) { @@ -266,19 +293,22 @@ public class AreaTreeParser { delegate.startDocument(); delegate.startElement(uri, localName, qName, attributes); } else { - lastAttributes = new AttributesImpl(attributes); boolean handled = true; if ("".equals(uri)) { - Maker maker = (Maker)makers.get(localName); - content.clear(); - ignoreCharacters = true; - if (maker != null) { - ignoreCharacters = maker.ignoreCharacters(); - maker.startElement(attributes); - } else if ("extension-attachments".equals(localName)) { - //TODO implement me + if (localName.equals("pageSequence") && userAgent.isAccessibilityEnabled()) { + structureTreeBuilder = new StructureTreeBuilder(attributes, structureTree); + } else if (localName.equals("structureTree")) { + if (userAgent.isAccessibilityEnabled()) { + delegate = structureTreeBuilder; + } else { + /* Delegate to a handler that does nothing */ + delegate = new DefaultHandler(); + } + delegateStack.push(qName); + delegate.startDocument(); + delegate.startElement(uri, localName, qName, attributes); } else { - handled = false; + handled = startAreaTreeElement(localName, attributes); } } else { ContentHandlerFactoryRegistry registry @@ -305,6 +335,23 @@ public class AreaTreeParser { } } + private boolean startAreaTreeElement(String localName, Attributes attributes) + throws SAXException { + lastAttributes = new AttributesImpl(attributes); + Maker maker = (Maker)makers.get(localName); + content.clear(); + ignoreCharacters = true; + if (maker != null) { + ignoreCharacters = maker.ignoreCharacters(); + maker.startElement(attributes); + } else if ("extension-attachments".equals(localName)) { + //TODO implement me + } else { + return false; + } + return true; + } + /** {@inheritDoc} */ public void endElement(String uri, String localName, String qName) throws SAXException { if (delegate != null) { @@ -701,6 +748,7 @@ public class AreaTreeParser { setTraits(attributes, ip, SUBSET_BOX); setTraits(attributes, ip, SUBSET_COLOR); setTraits(attributes, ip, SUBSET_LINK); + setPtr(ip, attributes); Area parent = (Area)areaStack.peek(); parent.addChildArea(ip); areaStack.push(ip); @@ -749,6 +797,7 @@ public class AreaTreeParser { "tlsadjust", 0)); text.setTextWordSpaceAdjust(XMLUtil.getAttributeAsInt(attributes, "twsadjust", 0)); + setPtr(text, attributes); Area parent = (Area)areaStack.peek(); parent.addChildArea(text); areaStack.push(text); @@ -841,6 +890,7 @@ public class AreaTreeParser { viewport.setContentPosition(XMLUtil.getAttributeAsRectangle2D(attributes, "pos")); viewport.setClip(XMLUtil.getAttributeAsBoolean(attributes, "clip", false)); viewport.setOffset(XMLUtil.getAttributeAsInt(attributes, "offset", 0)); + setPtr(viewport, attributes); Area parent = (Area)areaStack.peek(); parent.addChildArea(viewport); areaStack.push(viewport); @@ -859,6 +909,7 @@ public class AreaTreeParser { transferForeignObjects(attributes, image); setAreaAttributes(attributes, image); setTraits(attributes, image, SUBSET_COMMON); + setPtr(image, attributes); getCurrentViewport().setContent(image); } } @@ -1143,6 +1194,13 @@ public class AreaTreeParser { } } + private void setPtr(Area area, Attributes attributes) { + String ptr = attributes.getValue("ptr"); + if (ptr != null) { + area.addTrait(Trait.PTR, ptr); + } + } + /** {@inheritDoc} */ public void characters(char[] ch, int start, int length) throws SAXException { if (delegate != null) { diff --git a/src/java/org/apache/fop/render/xml/XMLRenderer.java b/src/java/org/apache/fop/render/xml/XMLRenderer.java index 8e8ae3f1d..d86814d25 100644 --- a/src/java/org/apache/fop/render/xml/XMLRenderer.java +++ b/src/java/org/apache/fop/render/xml/XMLRenderer.java @@ -34,12 +34,14 @@ 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; import org.apache.xmlgraphics.util.XMLizable; +import org.apache.fop.accessibility.StructureTree; import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.MimeConstants; @@ -86,6 +88,7 @@ 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. @@ -105,6 +108,8 @@ public class XMLRenderer extends AbstractXMLRenderer { /** If not null, the XMLRenderer will mimic another renderer by using its font setup. */ protected Renderer mimic; + private int pageSequenceNumber; + /** * Creates a new XML renderer. */ @@ -440,6 +445,21 @@ public class XMLRenderer extends AbstractXMLRenderer { } transferForeignObjects(pageSequence); startElement("pageSequence", atts); + if (this.getUserAgent().isAccessibilityEnabled()) { + StructureTree structureTree = getUserAgent().getStructureTree(); + String structureTreeElement = "structureTree"; + startElement(structureTreeElement); + NodeList nodes = structureTree.getPageSequence(++pageSequenceNumber); + 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); + } + } + endElement(structureTreeElement); + } handleExtensionAttachments(pageSequence.getExtensionAttachments()); LineArea seqTitle = pageSequence.getTitle(); if (seqTitle != null) { -- 2.39.5