View | Details | Raw Unified | Return to bug 50852
Collapse All | Expand All

(-)a/src/java/org/apache/fop/accessibility/StructureTreeBuilder.java (-30 / +28 lines)
Lines 19-43 Link Here
19
19
20
package org.apache.fop.accessibility;
20
package org.apache.fop.accessibility;
21
21
22
import javax.xml.transform.TransformerConfigurationException;
22
import java.util.Stack;
23
import javax.xml.transform.dom.DOMResult;
24
import javax.xml.transform.sax.SAXTransformerFactory;
25
import javax.xml.transform.sax.TransformerHandler;
26
23
24
import org.xml.sax.Attributes;
27
import org.xml.sax.ContentHandler;
25
import org.xml.sax.ContentHandler;
28
import org.xml.sax.SAXException;
26
import org.xml.sax.SAXException;
29
27
import org.xml.sax.helpers.DefaultHandler;
30
import org.apache.fop.util.DelegatingContentHandler;
31
28
32
/**
29
/**
33
 * Helper class that re-builds a structure tree from what is stored in an
30
 * Helper class that re-builds a structure tree from what is stored in an
34
 * intermediate XML file (IF XML or Area Tree XML).
31
 * intermediate XML file (IF XML or Area Tree XML).
35
 */
32
 */
36
public final class StructureTreeBuilder {
33
public final class StructureTreeBuilder {
37
34
38
    private final SAXTransformerFactory factory;
35
    private StructureElement structureTree;
39
40
    private final StructureTree structureTree = new StructureTree();
41
36
42
    /**
37
    /**
43
     * Creates a new instance.
38
     * Creates a new instance.
Lines 45-52 public final class StructureTreeBuilder { Link Here
45
     * @param factory a factory internally used to build the structures of page
40
     * @param factory a factory internally used to build the structures of page
46
     * sequences
41
     * sequences
47
     */
42
     */
48
    public StructureTreeBuilder(SAXTransformerFactory factory) {
43
    public StructureTreeBuilder() {
49
        this.factory = factory;
50
    }
44
    }
51
45
52
    /**
46
    /**
Lines 54-60 public final class StructureTreeBuilder { Link Here
54
     *
48
     *
55
     * @return the structure tree built by this object
49
     * @return the structure tree built by this object
56
     */
50
     */
57
    public StructureTree getStructureTree() {
51
    public StructureElement getStructureTree() {
58
        return structureTree;
52
        return structureTree;
59
    }
53
    }
60
54
Lines 67-95 public final class StructureTreeBuilder { Link Here
67
     * @throws SAXException if there is an error when creating the handler
61
     * @throws SAXException if there is an error when creating the handler
68
     */
62
     */
69
    public ContentHandler getHandlerForNextPageSequence() throws SAXException {
63
    public ContentHandler getHandlerForNextPageSequence() throws SAXException {
70
        TransformerHandler structureTreeBuilder;
64
        final Stack stack = new Stack();
71
        try {
65
        stack.push (new StructureElement("root"));
72
            structureTreeBuilder = factory.newTransformerHandler();
66
        return new DefaultHandler() {
73
        } catch (TransformerConfigurationException e) {
67
74
            throw new SAXException(e);
68
            /** {@inheritDoc} */
75
        }
69
            public void startElement(String namespaceURI, String localName, String rawName,
76
        final DOMResult domResult = new DOMResult();
70
                                     Attributes attlist) throws SAXException {
77
        structureTreeBuilder.setResult(domResult);
71
                StructureElement e = new StructureElement(localName);
78
        return new DelegatingContentHandler(structureTreeBuilder) {
72
                StructureElement parent = (StructureElement)stack.peek();
73
                parent.addChild(e);
74
                stack.push(e);
75
                e.setPtr(attlist.getValue("foi:ptr"));
76
                e.setRole(attlist.getValue("fo:role"));
77
                e.setAltText(attlist.getValue("fox:alt-text"));
78
            }
79
79
80
            public void characters(char[] ch, int start, int length) throws SAXException {
80
            /** {@inheritDoc} */
81
                /*
81
            public void endElement(String uri, String localName, String rawName)
82
                 * There's no text node in the structure tree. This is just
82
                throws SAXException {
83
                 * whitespace => ignore
83
                stack.pop();
84
                 */
85
            }
84
            }
86
85
86
87
            public void endDocument() throws SAXException {
87
            public void endDocument() throws SAXException {
88
                super.endDocument();
88
                super.endDocument();
89
                structureTree.addPageSequenceStructure(domResult.getNode().getFirstChild()
89
                structureTree = ((StructureElement)stack.pop()).getChild(0).getChild(0);
90
                        .getChildNodes());
91
            }
90
            }
92
        };
91
        };
93
    }
92
    }
94
95
}
93
}
(-)a/src/java/org/apache/fop/apps/Fop.java (-6 / +1 lines)
Lines 24-30 import java.io.OutputStream; Link Here
24
24
25
import org.xml.sax.helpers.DefaultHandler;
25
import org.xml.sax.helpers.DefaultHandler;
26
26
27
import org.apache.fop.accessibility.Accessibility;
28
import org.apache.fop.fo.FOTreeBuilder;
27
import org.apache.fop.fo.FOTreeBuilder;
29
28
30
/**
29
/**
Lines 111-121 public class Fop { Link Here
111
        if (foTreeBuilder == null) {
110
        if (foTreeBuilder == null) {
112
            createDefaultHandler();
111
            createDefaultHandler();
113
        }
112
        }
114
        if (this.foUserAgent.isAccessibilityEnabled()) {
113
        return this.foTreeBuilder;
115
            return Accessibility.decorateDefaultHandler(this.foTreeBuilder, foUserAgent);
116
        } else {
117
            return this.foTreeBuilder;
118
        }
119
    }
114
    }
120
115
121
    /**
116
    /**
(-)a/src/java/org/apache/fop/area/AreaTreeParser.java (-2 / +2 lines)
Lines 184-189 public class AreaTreeParser { Link Here
184
                super.endDocument();
184
                super.endDocument();
185
                startAreaTreeElement("pageSequence", pageSequenceAttributes);
185
                startAreaTreeElement("pageSequence", pageSequenceAttributes);
186
                pageSequenceAttributes = null;
186
                pageSequenceAttributes = null;
187
                ((PageSequence)areaStack.peek()).setStructureTree(structureTreeBuilder.getStructureTree());
187
            }
188
            }
188
        }
189
        }
189
190
Lines 225-232 public class AreaTreeParser { Link Here
225
            makers.put("destination", new DestinationMaker());
226
            makers.put("destination", new DestinationMaker());
226
227
227
            if (userAgent.isAccessibilityEnabled()) {
228
            if (userAgent.isAccessibilityEnabled()) {
228
                structureTreeBuilder = new StructureTreeBuilder(tFactory);
229
                structureTreeBuilder = new StructureTreeBuilder();
229
                userAgent.setStructureTree(structureTreeBuilder.getStructureTree());
230
            }
230
            }
231
        }
231
        }
232
232
(-)a/src/java/org/apache/fop/fo/flow/AbstractGraphics.java (-1 / +1 lines)
Lines 100-107 public abstract class AbstractGraphics extends FObj Link Here
100
        dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum();
100
        dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum();
101
        height = pList.get(PR_HEIGHT).getLength();
101
        height = pList.get(PR_HEIGHT).getLength();
102
        id = pList.get(PR_ID).getString();
102
        id = pList.get(PR_ID).getString();
103
        ptr = pList.get(PR_X_PTR).getString();   // used for accessibility
104
        role = pList.get(PR_ROLE).getString(); // used for accessibility
103
        role = pList.get(PR_ROLE).getString(); // used for accessibility
104
        ptr = newPtrId();
105
        inlineProgressionDimension = pList.get(PR_INLINE_PROGRESSION_DIMENSION).getLengthRange();
105
        inlineProgressionDimension = pList.get(PR_INLINE_PROGRESSION_DIMENSION).getLengthRange();
106
        keepWithNext = pList.get(PR_KEEP_WITH_NEXT).getKeep();
106
        keepWithNext = pList.get(PR_KEEP_WITH_NEXT).getKeep();
107
        keepWithPrevious = pList.get(PR_KEEP_WITH_PREVIOUS).getKeep();
107
        keepWithPrevious = pList.get(PR_KEEP_WITH_PREVIOUS).getKeep();
(-)a/src/java/org/apache/fop/fo/flow/AbstractPageNumberCitation.java (-1 / +1 lines)
Lines 101-108 public abstract class AbstractPageNumberCitation extends FObj Link Here
101
        dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum();
101
        dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum();
102
        // letterSpacing = pList.get(PR_LETTER_SPACING);
102
        // letterSpacing = pList.get(PR_LETTER_SPACING);
103
        lineHeight = pList.get(PR_LINE_HEIGHT).getSpace();
103
        lineHeight = pList.get(PR_LINE_HEIGHT).getSpace();
104
        ptr = pList.get(PR_X_PTR).getString();   // used for accessibility
105
        role = pList.get(PR_ROLE).getString(); // used for accessibility
104
        role = pList.get(PR_ROLE).getString(); // used for accessibility
105
        ptr = newPtrId();
106
        refId = pList.get(PR_REF_ID).getString();
106
        refId = pList.get(PR_REF_ID).getString();
107
        textDecoration = pList.getTextDecorationProps();
107
        textDecoration = pList.getTextDecorationProps();
108
        // textShadow = pList.get(PR_TEXT_SHADOW);
108
        // textShadow = pList.get(PR_TEXT_SHADOW);
(-)a/src/java/org/apache/fop/fo/flow/Block.java (-1 / +1 lines)
Lines 127-134 public class Block extends FObjMixed implements BreakPropertySet, StructurePoint Link Here
127
        lineHeightShiftAdjustment = pList.get(PR_LINE_HEIGHT_SHIFT_ADJUSTMENT).getEnum();
127
        lineHeightShiftAdjustment = pList.get(PR_LINE_HEIGHT_SHIFT_ADJUSTMENT).getEnum();
128
        lineStackingStrategy = pList.get(PR_LINE_STACKING_STRATEGY).getEnum();
128
        lineStackingStrategy = pList.get(PR_LINE_STACKING_STRATEGY).getEnum();
129
        orphans = pList.get(PR_ORPHANS).getNumeric();
129
        orphans = pList.get(PR_ORPHANS).getNumeric();
130
        ptr = pList.get(PR_X_PTR).getString();  //used for accessibility
131
        role = pList.get(PR_ROLE).getString(); // used for accessibility
130
        role = pList.get(PR_ROLE).getString(); // used for accessibility
131
        ptr = newPtrId();
132
        whiteSpaceTreatment = pList.get(PR_WHITE_SPACE_TREATMENT).getEnum();
132
        whiteSpaceTreatment = pList.get(PR_WHITE_SPACE_TREATMENT).getEnum();
133
        span = pList.get(PR_SPAN).getEnum();
133
        span = pList.get(PR_SPAN).getEnum();
134
        textAlign = pList.get(PR_TEXT_ALIGN).getEnum();
134
        textAlign = pList.get(PR_TEXT_ALIGN).getEnum();
(-)a/src/java/org/apache/fop/fo/flow/Character.java (-1 / +1 lines)
Lines 112-119 public class Character extends FObj implements StructurePointerPropertySet { Link Here
112
        lineHeight = pList.get(PR_LINE_HEIGHT).getSpace();
112
        lineHeight = pList.get(PR_LINE_HEIGHT).getSpace();
113
        textDecoration = pList.getTextDecorationProps();
113
        textDecoration = pList.getTextDecorationProps();
114
        wordSpacing = pList.get(PR_WORD_SPACING);
114
        wordSpacing = pList.get(PR_WORD_SPACING);
115
        ptr = pList.get(PR_X_PTR).getString();  // used for accessibility
116
        role = pList.get(PR_ROLE).getString(); // used for accessibility
115
        role = pList.get(PR_ROLE).getString(); // used for accessibility
116
        ptr = newPtrId();
117
    }
117
    }
118
118
119
    /** {@inheritDoc} */
119
    /** {@inheritDoc} */
(-)a/src/java/org/apache/fop/fo/flow/Inline.java (-1 / +1 lines)
Lines 70-77 public class Inline extends InlineLevel implements StructurePointerPropertySet { Link Here
70
        alignmentBaseline = pList.get(PR_ALIGNMENT_BASELINE).getEnum();
70
        alignmentBaseline = pList.get(PR_ALIGNMENT_BASELINE).getEnum();
71
        baselineShift = pList.get(PR_BASELINE_SHIFT).getLength();
71
        baselineShift = pList.get(PR_BASELINE_SHIFT).getLength();
72
        dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum();
72
        dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum();
73
        ptr = pList.get(PR_X_PTR).getString(); // used for accessibility
74
        role = pList.get(PR_ROLE).getString(); // used for accessibility
73
        role = pList.get(PR_ROLE).getString(); // used for accessibility
74
        ptr = newPtrId();
75
    }
75
    }
76
76
77
    /** {@inheritDoc} */
77
    /** {@inheritDoc} */
(-)a/src/java/org/apache/fop/fo/flow/PageNumber.java (-1 / +1 lines)
Lines 96-103 public class PageNumber extends FObj implements StructurePointerPropertySet { Link Here
96
        // letterSpacing = pList.get(PR_LETTER_SPACING);
96
        // letterSpacing = pList.get(PR_LETTER_SPACING);
97
        lineHeight = pList.get(PR_LINE_HEIGHT).getSpace();
97
        lineHeight = pList.get(PR_LINE_HEIGHT).getSpace();
98
        textDecoration = pList.getTextDecorationProps();
98
        textDecoration = pList.getTextDecorationProps();
99
        ptr = pList.get(PR_X_PTR).getString(); // used for accessibility
100
        role = pList.get(PR_ROLE).getString(); // used for accessibility
99
        role = pList.get(PR_ROLE).getString(); // used for accessibility
100
        ptr = newPtrId();
101
        // textShadow = pList.get(PR_TEXT_SHADOW);
101
        // textShadow = pList.get(PR_TEXT_SHADOW);
102
102
103
        // implicit properties
103
        // implicit properties
(-)a/src/java/org/apache/fop/fo/flow/table/TableFObj.java (-1 / +1 lines)
Lines 76-83 public abstract class TableFObj extends FObj implements StructurePointerProperty Link Here
76
        borderBeforePrecedence = pList.get(PR_BORDER_BEFORE_PRECEDENCE).getNumeric();
76
        borderBeforePrecedence = pList.get(PR_BORDER_BEFORE_PRECEDENCE).getNumeric();
77
        borderEndPrecedence = pList.get(PR_BORDER_END_PRECEDENCE).getNumeric();
77
        borderEndPrecedence = pList.get(PR_BORDER_END_PRECEDENCE).getNumeric();
78
        borderStartPrecedence = pList.get(PR_BORDER_START_PRECEDENCE).getNumeric();
78
        borderStartPrecedence = pList.get(PR_BORDER_START_PRECEDENCE).getNumeric();
79
        ptr = pList.get(PR_X_PTR).getString();
80
        role = pList.get(PR_ROLE).getString(); // used for accessibility
79
        role = pList.get(PR_ROLE).getString(); // used for accessibility
80
        ptr = newPtrId();
81
        if (getNameId() != FO_TABLE //Separate check for fo:table in Table.java
81
        if (getNameId() != FO_TABLE //Separate check for fo:table in Table.java
82
                && getNameId() != FO_TABLE_CELL
82
                && getNameId() != FO_TABLE_CELL
83
                && getCommonBorderPaddingBackground().hasPadding(
83
                && getCommonBorderPaddingBackground().hasPadding(
(-)a/src/java/org/apache/fop/render/intermediate/IFParser.java (-2 / +6 lines)
Lines 169-174 public class IFParser implements IFConstants { Link Here
169
                super.endDocument();
169
                super.endDocument();
170
                startIFElement(EL_PAGE_SEQUENCE, pageSequenceAttributes);
170
                startIFElement(EL_PAGE_SEQUENCE, pageSequenceAttributes);
171
                pageSequenceAttributes = null;
171
                pageSequenceAttributes = null;
172
                try {
173
                    documentHandler.handleExtensionObject(structureTreeBuilder.getStructureTree());
174
                } catch (IFException ife) {
175
                    handleIFException(ife);
176
                }
172
            }
177
            }
173
        }
178
        }
174
179
Lines 197-204 public class IFParser implements IFConstants { Link Here
197
            elementHandlers.put(EL_IMAGE, new ImageHandler());
202
            elementHandlers.put(EL_IMAGE, new ImageHandler());
198
203
199
            if (userAgent.isAccessibilityEnabled()) {
204
            if (userAgent.isAccessibilityEnabled()) {
200
                structureTreeBuilder = new StructureTreeBuilder(tFactory);
205
                structureTreeBuilder = new StructureTreeBuilder();
201
                userAgent.setStructureTree(structureTreeBuilder.getStructureTree());
202
            }
206
            }
203
        }
207
        }
204
208
(-)a/src/java/org/apache/fop/render/intermediate/IFRenderer.java (+2 lines)
Lines 506-511 public class IFRenderer extends AbstractPathOrientedRenderer { Link Here
506
            establishForeignAttributes(pageSequence.getForeignAttributes());
506
            establishForeignAttributes(pageSequence.getForeignAttributes());
507
            documentHandler.getContext().setLanguage(toLocale(pageSequence));
507
            documentHandler.getContext().setLanguage(toLocale(pageSequence));
508
            documentHandler.startPageSequence(null);
508
            documentHandler.startPageSequence(null);
509
            if (pageSequence.getStructureTree() != null)
510
                documentHandler.handleExtensionObject(pageSequence.getStructureTree());
509
            resetForeignAttributes();
511
            resetForeignAttributes();
510
            processExtensionAttachments(pageSequence);
512
            processExtensionAttachments(pageSequence);
511
        } catch (IFException e) {
513
        } catch (IFException e) {
(-)a/src/java/org/apache/fop/render/intermediate/IFSerializer.java (-14 / +17 lines)
Lines 31-38 import java.util.Locale; Link Here
31
import java.util.Map;
31
import java.util.Map;
32
32
33
import org.w3c.dom.Document;
33
import org.w3c.dom.Document;
34
import org.w3c.dom.Node;
35
import org.w3c.dom.NodeList;
36
34
37
import org.xml.sax.SAXException;
35
import org.xml.sax.SAXException;
38
import org.xml.sax.helpers.AttributesImpl;
36
import org.xml.sax.helpers.AttributesImpl;
Lines 40-46 import org.xml.sax.helpers.AttributesImpl; Link Here
40
import org.apache.xmlgraphics.util.QName;
38
import org.apache.xmlgraphics.util.QName;
41
import org.apache.xmlgraphics.util.XMLizable;
39
import org.apache.xmlgraphics.util.XMLizable;
42
40
43
import org.apache.fop.accessibility.StructureTree;
41
import org.apache.fop.accessibility.StructureElement;
42
import org.apache.fop.fo.extensions.ExtensionElementMapping;
43
import org.apache.fop.fo.extensions.InternalElementMapping;
44
import org.apache.fop.fonts.FontInfo;
44
import org.apache.fop.fonts.FontInfo;
45
import org.apache.fop.render.PrintRendererConfigurator;
45
import org.apache.fop.render.PrintRendererConfigurator;
46
import org.apache.fop.render.RenderingContext;
46
import org.apache.fop.render.RenderingContext;
Lines 230-245 public class IFSerializer extends AbstractXMLWritingIFDocumentHandler Link Here
230
            XMLUtil.addAttribute(atts, XMLConstants.XML_SPACE, "preserve");
230
            XMLUtil.addAttribute(atts, XMLConstants.XML_SPACE, "preserve");
231
            addForeignAttributes(atts);
231
            addForeignAttributes(atts);
232
            handler.startElement(EL_PAGE_SEQUENCE, atts);
232
            handler.startElement(EL_PAGE_SEQUENCE, atts);
233
            if (this.getUserAgent().isAccessibilityEnabled()) {
234
                StructureTree structureTree = getUserAgent().getStructureTree();
235
                handler.startElement(EL_STRUCTURE_TREE); // add structure tree
236
                NodeList nodes = structureTree.getPageSequence(pageSequenceIndex++);
237
                for (int i = 0, n = nodes.getLength(); i < n; i++) {
238
                    Node node = nodes.item(i);
239
                    new DOM2SAX(handler).writeFragment(node);
240
                }
241
                handler.endElement(EL_STRUCTURE_TREE);
242
            }
243
        } catch (SAXException e) {
233
        } catch (SAXException e) {
244
            throw new IFException("SAX error in startPageSequence()", e);
234
            throw new IFException("SAX error in startPageSequence()", e);
245
        }
235
        }
Lines 633-639 public class IFSerializer extends AbstractXMLWritingIFDocumentHandler Link Here
633
623
634
    /** {@inheritDoc} */
624
    /** {@inheritDoc} */
635
    public void handleExtensionObject(Object extension) throws IFException {
625
    public void handleExtensionObject(Object extension) throws IFException {
636
        if (extension instanceof XMLizable) {
626
        if (extension instanceof StructureElement) {
627
            try {
628
                StructureElement node = (StructureElement)extension;
629
                handler.startElement(EL_STRUCTURE_TREE); // add structure tree
630
                handler.startPrefixMapping("foi", InternalElementMapping.URI);
631
                handler.startPrefixMapping("fox", ExtensionElementMapping.URI);
632
                node.toXML(handler);
633
                handler.endPrefixMapping("fox");
634
                handler.endPrefixMapping("foi");
635
                handler.endElement(EL_STRUCTURE_TREE);
636
            } catch (SAXException e) {
637
                throw new IFException("SAX error in setFont()", e);
638
            }
639
        } else if (extension instanceof XMLizable) {
637
            try {
640
            try {
638
                ((XMLizable)extension).toSAX(this.handler);
641
                ((XMLizable)extension).toSAX(this.handler);
639
            } catch (SAXException e) {
642
            } catch (SAXException e) {
(-)a/src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java (-9 / +7 lines)
Lines 22-29 package org.apache.fop.render.pdf; Link Here
22
import java.util.HashMap;
22
import java.util.HashMap;
23
import java.util.Map;
23
import java.util.Map;
24
24
25
import org.w3c.dom.Node;
25
import org.apache.fop.accessibility.StructureElement;
26
27
import org.apache.fop.events.EventBroadcaster;
26
import org.apache.fop.events.EventBroadcaster;
28
import org.apache.fop.pdf.PDFName;
27
import org.apache.fop.pdf.PDFName;
29
import org.apache.fop.pdf.PDFObject;
28
import org.apache.fop.pdf.PDFObject;
Lines 180-199 final class FOToPDFRoleMap { Link Here
180
        }
179
        }
181
    }
180
    }
182
181
183
    public static PDFName mapFormattingObject(Node fo, PDFObject parent,
182
    public static PDFName mapFormattingObject(StructureElement fo, PDFObject parent,
184
            EventBroadcaster eventBroadcaster) {
183
            EventBroadcaster eventBroadcaster) {
185
        PDFName type = null;
184
        PDFName type = null;
186
        Node role = fo.getAttributes().getNamedItemNS(null, "role");
185
        String role = fo.getRole();
187
        if (role == null) {
186
        if (role == null) {
188
            type = mapFormattingObject(fo.getLocalName(), parent);
187
            type = mapFormattingObject(fo.getName(), parent);
189
        } else {
188
        } else {
190
            String customType = role.getNodeValue();
189
            type = (PDFName) STANDARD_STRUCTURE_TYPES.get(role);
191
            type = (PDFName) STANDARD_STRUCTURE_TYPES.get(customType);
192
            if (type == null) {
190
            if (type == null) {
193
                String foName = fo.getLocalName();
191
                String foName = fo.getName();
194
                type = mapFormattingObject(foName, parent);
192
                type = mapFormattingObject(foName, parent);
195
                PDFEventProducer.Provider.get(eventBroadcaster).nonStandardStructureType(fo,
193
                PDFEventProducer.Provider.get(eventBroadcaster).nonStandardStructureType(fo,
196
                        foName, customType, type.toString().substring(1));
194
                        foName, fo.getRole(), type.toString().substring(1));
197
            }
195
            }
198
        }
196
        }
199
        assert type != null;
197
        assert type != null;
(-)a/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java (-10 / +4 lines)
Lines 27-39 import java.awt.geom.Rectangle2D; Link Here
27
import java.io.IOException;
27
import java.io.IOException;
28
import java.util.Map;
28
import java.util.Map;
29
29
30
import org.w3c.dom.NodeList;
31
32
import org.apache.commons.logging.Log;
30
import org.apache.commons.logging.Log;
33
import org.apache.commons.logging.LogFactory;
31
import org.apache.commons.logging.LogFactory;
34
32
35
import org.apache.xmlgraphics.xmp.Metadata;
33
import org.apache.xmlgraphics.xmp.Metadata;
36
34
35
import org.apache.fop.accessibility.StructureElement;
37
import org.apache.fop.apps.MimeConstants;
36
import org.apache.fop.apps.MimeConstants;
38
import org.apache.fop.fo.extensions.xmp.XMPMetadata;
37
import org.apache.fop.fo.extensions.xmp.XMPMetadata;
39
import org.apache.fop.pdf.PDFAnnotList;
38
import org.apache.fop.pdf.PDFAnnotList;
Lines 61-68 public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler { Link Here
61
    /** logging instance */
60
    /** logging instance */
62
    private static Log log = LogFactory.getLog(PDFDocumentHandler.class);
61
    private static Log log = LogFactory.getLog(PDFDocumentHandler.class);
63
62
64
    private int pageSequenceIndex;
65
66
    private boolean accessEnabled;
63
    private boolean accessEnabled;
67
64
68
    private PDFLogicalStructureHandler logicalStructureHandler;
65
    private PDFLogicalStructureHandler logicalStructureHandler;
Lines 185-195 public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler { Link Here
185
            //No document-level language set, so we use the first page-sequence's language
182
            //No document-level language set, so we use the first page-sequence's language
186
            this.pdfDoc.getRoot().setLanguage(XMLUtil.toRFC3066(getContext().getLanguage()));
183
            this.pdfDoc.getRoot().setLanguage(XMLUtil.toRFC3066(getContext().getLanguage()));
187
        }
184
        }
188
189
        if (accessEnabled) {
190
            NodeList nodes = getUserAgent().getStructureTree().getPageSequence(pageSequenceIndex++);
191
            logicalStructureHandler.processStructureTree(nodes, getContext().getLanguage());
192
        }
193
    }
185
    }
194
186
195
    /** {@inheritDoc} */
187
    /** {@inheritDoc} */
Lines 288-294 public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler { Link Here
288
280
289
    /** {@inheritDoc} */
281
    /** {@inheritDoc} */
290
    public void handleExtensionObject(Object extension) throws IFException {
282
    public void handleExtensionObject(Object extension) throws IFException {
291
        if (extension instanceof XMPMetadata) {
283
        if (extension instanceof StructureElement) {
284
            logicalStructureHandler.processStructureTree((StructureElement)extension, getContext().getLanguage());
285
        } else if (extension instanceof XMPMetadata) {
292
            pdfUtil.renderXMPMetadata((XMPMetadata)extension);
286
            pdfUtil.renderXMPMetadata((XMPMetadata)extension);
293
        } else if (extension instanceof Metadata) {
287
        } else if (extension instanceof Metadata) {
294
            XMPMetadata wrapper = new XMPMetadata(((Metadata)extension));
288
            XMPMetadata wrapper = new XMPMetadata(((Metadata)extension));
(-)a/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java (-22 / +16 lines)
Lines 23-31 import java.util.HashMap; Link Here
23
import java.util.Locale;
23
import java.util.Locale;
24
import java.util.Map;
24
import java.util.Map;
25
25
26
import org.w3c.dom.Node;
26
import org.apache.fop.accessibility.StructureElement;
27
import org.w3c.dom.NodeList;
28
29
import org.apache.fop.events.EventBroadcaster;
27
import org.apache.fop.events.EventBroadcaster;
30
import org.apache.fop.fo.extensions.ExtensionElementMapping;
28
import org.apache.fop.fo.extensions.ExtensionElementMapping;
31
import org.apache.fop.fo.extensions.InternalElementMapping;
29
import org.apache.fop.fo.extensions.InternalElementMapping;
Lines 123-129 class PDFLogicalStructureHandler { Link Here
123
     * @param structureTree the structure tree of the current page sequence
121
     * @param structureTree the structure tree of the current page sequence
124
     * @param language language set on the page sequence
122
     * @param language language set on the page sequence
125
     */
123
     */
126
    void processStructureTree(NodeList structureTree, Locale language) {
124
    void processStructureTree(StructureElement structureTree, Locale language) {
127
        pdfDoc.enforceLanguageOnRoot();
125
        pdfDoc.enforceLanguageOnRoot();
128
        PDFStructElem structElemPart = pdfDoc.getFactory().makeStructureElement(
126
        PDFStructElem structElemPart = pdfDoc.getFactory().makeStructureElement(
129
                FOToPDFRoleMap.mapFormattingObject("page-sequence", rootStructureElement),
127
                FOToPDFRoleMap.mapFormattingObject("page-sequence", rootStructureElement),
Lines 134-157 class PDFLogicalStructureHandler { Link Here
134
        }
132
        }
135
133
136
        for (int i = 0, n = structureTree.getLength(); i < n; i++) {
134
        for (int i = 0, n = structureTree.getLength(); i < n; i++) {
137
            Node node = structureTree.item(i);
135
            StructureElement node = structureTree.getChild(i);
138
            assert node.getLocalName().equals("flow")
136
            assert node.getName().equals("flow")
139
                    || node.getLocalName().equals("static-content");
137
                    || node.getName().equals("static-content");
140
            PDFStructElem structElemSect = pdfDoc.getFactory().makeStructureElement(
138
            PDFStructElem structElemSect = pdfDoc.getFactory().makeStructureElement(
141
                    FOToPDFRoleMap.mapFormattingObject(node.getLocalName(), structElemPart),
139
                    FOToPDFRoleMap.mapFormattingObject(node.getName(), structElemPart),
142
                    structElemPart);
140
                    structElemPart);
143
            structElemPart.addKid(structElemSect);
141
            structElemPart.addKid(structElemSect);
144
            NodeList childNodes = node.getChildNodes();
142
            for (int j = 0, m = node.getLength(); j < m; j++) {
145
            for (int j = 0, m = childNodes.getLength(); j < m; j++) {
143
                processNode(node.getChild(j), structElemSect, true);
146
                processNode(childNodes.item(j), structElemSect, true);
147
            }
144
            }
148
        }
145
        }
149
    }
146
    }
150
147
151
    private void processNode(Node node, PDFStructElem parent, boolean addKid) {
148
    private void processNode(StructureElement node, PDFStructElem parent, boolean addKid) {
152
        Node attr = node.getAttributes().getNamedItemNS(InternalElementMapping.URI, "ptr");
149
        String ptr = node.getPtr();
153
        assert attr != null;
150
        assert ptr != null;
154
        String ptr = attr.getNodeValue();
155
        PDFStructElem structElem = pdfDoc.getFactory().makeStructureElement(
151
        PDFStructElem structElem = pdfDoc.getFactory().makeStructureElement(
156
                FOToPDFRoleMap.mapFormattingObject(node, parent, eventBroadcaster), parent);
152
                FOToPDFRoleMap.mapFormattingObject(node, parent, eventBroadcaster), parent);
157
        // TODO necessary? If a page-sequence is empty (e.g., contains a single
153
        // TODO necessary? If a page-sequence is empty (e.g., contains a single
Lines 160-179 class PDFLogicalStructureHandler { Link Here
160
        if (addKid) {
156
        if (addKid) {
161
            parent.addKid(structElem);
157
            parent.addKid(structElem);
162
        }
158
        }
163
        String nodeName = node.getLocalName();
159
        String nodeName = node.getName();
164
        if (nodeName.equals("external-graphic") || nodeName.equals("instream-foreign-object")) {
160
        if (nodeName.equals("external-graphic") || nodeName.equals("instream-foreign-object")) {
165
            Node altTextNode = node.getAttributes().getNamedItemNS(
161
            String altTextNode = node.getAltText();
166
                    ExtensionElementMapping.URI, "alt-text");
167
            if (altTextNode != null) {
162
            if (altTextNode != null) {
168
                structElem.put("Alt", altTextNode.getNodeValue());
163
                structElem.put("Alt", altTextNode);
169
            } else {
164
            } else {
170
                structElem.put("Alt", "No alternate text specified");
165
                structElem.put("Alt", "No alternate text specified");
171
            }
166
            }
172
        }
167
        }
173
        structTreeMap.put(ptr, structElem);
168
        structTreeMap.put(ptr, structElem);
174
        NodeList nodes = node.getChildNodes();
169
        for (int i = 0, n = node.getLength(); i < n; i++) {
175
        for (int i = 0, n = nodes.getLength(); i < n; i++) {
170
            processNode(node.getChild(i), structElem, false);
176
            processNode(nodes.item(i), structElem, false);
177
        }
171
        }
178
    }
172
    }
179
173
(-)a/src/java/org/apache/fop/render/xml/XMLRenderer.java (-14 / +7 lines)
Lines 35-47 import javax.xml.transform.stream.StreamResult; Link Here
35
35
36
import org.w3c.dom.Document;
36
import org.w3c.dom.Document;
37
import org.w3c.dom.Node;
37
import org.w3c.dom.Node;
38
import org.w3c.dom.NodeList;
39
38
40
import org.xml.sax.SAXException;
39
import org.xml.sax.SAXException;
41
40
42
import org.apache.xmlgraphics.util.QName;
41
import org.apache.xmlgraphics.util.QName;
43
import org.apache.xmlgraphics.util.XMLizable;
42
import org.apache.xmlgraphics.util.XMLizable;
44
43
44
import org.apache.fop.accessibility.StructureElement;
45
import org.apache.fop.apps.FOPException;
45
import org.apache.fop.apps.FOPException;
46
import org.apache.fop.apps.FOUserAgent;
46
import org.apache.fop.apps.FOUserAgent;
47
import org.apache.fop.apps.MimeConstants;
47
import org.apache.fop.apps.MimeConstants;
Lines 110-117 public class XMLRenderer extends AbstractXMLRenderer { Link Here
110
    /** If not null, the XMLRenderer will mimic another renderer by using its font setup. */
110
    /** If not null, the XMLRenderer will mimic another renderer by using its font setup. */
111
    protected Renderer mimic;
111
    protected Renderer mimic;
112
112
113
    private int pageSequenceIndex;
114
115
    /**
113
    /**
116
     * Creates a new XML renderer.
114
     * Creates a new XML renderer.
117
     */
115
     */
Lines 460-480 public class XMLRenderer extends AbstractXMLRenderer { Link Here
460
        }
458
        }
461
        transferForeignObjects(pageSequence);
459
        transferForeignObjects(pageSequence);
462
        startElement("pageSequence", atts);
460
        startElement("pageSequence", atts);
463
        if (this.getUserAgent().isAccessibilityEnabled()) {
461
        StructureElement node = pageSequence.getStructureTree();
462
        if (node != null) {
464
            String structureTreeElement = "structureTree";
463
            String structureTreeElement = "structureTree";
465
            startElement(structureTreeElement);
464
            startElement(structureTreeElement);
466
            try {
465
            try {
467
                this.handler.startPrefixMapping("foi", InternalElementMapping.URI);
466
                this.handler.startPrefixMapping("foi", InternalElementMapping.URI);
468
                this.handler.startPrefixMapping("fox", ExtensionElementMapping.URI);
467
                this.handler.startPrefixMapping("fox", ExtensionElementMapping.URI);
469
                NodeList nodes = getUserAgent().getStructureTree().getPageSequence(
468
                try {
470
                        pageSequenceIndex++);
469
                    node.toXML(handler);
471
                for (int i = 0, n = nodes.getLength(); i < n; i++) {
470
                } catch (SAXException e) {
472
                    Node node = nodes.item(i);
471
                    handleSAXException(e);
473
                    try {
474
                        new DOM2SAX(handler).writeFragment(node);
475
                    } catch (SAXException e) {
476
                        handleSAXException(e);
477
                    }
478
                }
472
                }
479
                this.handler.endPrefixMapping("fox");
473
                this.handler.endPrefixMapping("fox");
480
                this.handler.endPrefixMapping("foi");
474
                this.handler.endPrefixMapping("foi");
481
- 

Return to bug 50852