]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Added possibility to customize PDF tagging via the role property
authorVincent Hennebert <vhennebert@apache.org>
Wed, 13 Jan 2010 17:05:59 +0000 (17:05 +0000)
committerVincent Hennebert <vhennebert@apache.org>
Wed, 13 Jan 2010 17:05:59 +0000 (17:05 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@898840 13f79535-47bb-0310-9956-ffa450edef68

19 files changed:
src/documentation/content/xdocs/trunk/accessibility.xml
src/java/org/apache/fop/accessibility/reduceFOTree.xsl
src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java
src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java
src/java/org/apache/fop/render/pdf/PDFEventProducer.java
src/java/org/apache/fop/render/pdf/PDFEventProducer.xml
src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java
src/java/org/apache/fop/render/pdf/PDFRenderer.java
status.xml
test/accessibility/README
test/accessibility/complete.fo
test/accessibility/pdf/complete_painter_orig.pdf
test/accessibility/pdf/complete_renderer_orig.pdf
test/accessibility/pdf/role_non-standard_painter_orig.pdf [new file with mode: 0644]
test/accessibility/pdf/role_non-standard_renderer_orig.pdf [new file with mode: 0644]
test/accessibility/pdf/role_painter_orig.pdf [new file with mode: 0644]
test/accessibility/pdf/role_renderer_orig.pdf [new file with mode: 0644]
test/accessibility/role.fo [new file with mode: 0644]
test/accessibility/role_non-standard.fo [new file with mode: 0644]

index 1eb78264b6a713cc805c99e48d11373a604a2324..f3c66e06aa88e9ecdf6ff619e2769c146441f381 100644 (file)
         </li>
       </ul>
     </section>
+    <section id="customTags">
+      <title>Customized Tagging</title>
+      <p>The <a href="#PDFReference">PDF Reference</a> defines a set of standard Structure Types to 
+        tag content. For example, ‘P’  is used for identifying paragraphs, ‘H1’ to ‘H6’ for headers, 
+        ‘L’ for lists, ‘Div’ for block-level groups of elements, etc. This standard set is aimed at 
+        improving interoperability between applications producing or consuming PDF. </p>
+      <p>FOP provides a default mapping of Formatting Objects to elements from that standard set. 
+        For example, <code>fo:page-sequence</code> is mapped to ‘Part’, <code>fo:block</code> is 
+        mapped to ‘P’, <code>fo:list-block</code> to ‘L’, etc.</p>
+      <p>You may want to customize that mapping to improve the accuracy of the tagging or deal with 
+        particular FO constructs. For example, you may want to make use of the ‘H1’ to ‘H6’ tags to 
+        make the hierarchical structure of the document appear in the PDF. This is achieved by using 
+        the <code>role</code> XSL-FO property:</p>
+      <source>...
+&lt;fo:block role="H1" font-weight="bold"&gt;I. A Level 1 Heading&lt;/fo:block&gt;
+&lt;fo:block&gt;This is the first paragraph of the first section...&lt;/fo:block&gt;
+...</source>
+      <p>If a non-standard structure type is specified, FOP will issue a warning and fall back to 
+        the default tag associated to the Formatting Object.</p>
+    </section>
     <section id="testing">
       <title>Testing</title>
       <p>
           SVG graphics (or images in general) are treated as a single figure. Text contained in
           SVGs is not accessible. It's only possible to work with <code>fox:alt-text</code>.
         </li>
-        <li>
-          XSL-FO's role property is currently not supported. It could theoretically be used to
-          differentiate between headings and normal text. At the moment, the two are simply
-          identified as paragraphs.
-        </li>
         <li>
           The side regions (region-before, region-after etc.) are currently not specially
           identified. Screen readers may read their content at page changes.
         <li><a href="http://www.section508.gov/">US Government - Website on Section 508</a></li>
         <li><a href="http://en.wikipedia.org/wiki/Accessibility">Wikipedia on Accessibility in general</a></li>
         <li><a href="http://en.wikipedia.org/wiki/Portable_Document_Format#Accessibility">Wikipedia on Accessibility in PDF</a></li>
-        <li>
+        <li id="PDFReference">
           <a href="http://partners.adobe.com/public/developer/en/pdf/PDFReference.pdf">PDF 
             Reference 1.4</a> (look up chapters 9.7 "Tagged PDF" and 9.8 "Accessibility Support")
         </li>
index 8e9bcfc13053215d52139a608a57ebe9e0d081d9..0d93a250629a73894ee39c05926a9ca9c3712f1c 100644 (file)
@@ -86,8 +86,8 @@
   <xsl:template match="fo:leader"/>
       
 
-  <!-- Keep foi:ptr and fox:alt-text attributes, discard everything else -->
-  <xsl:template match="@foi:ptr|@fox:alt-text">
+  <!-- Keep foi:ptr, fox:alt-text and role attributes, discard everything else -->
+  <xsl:template match="@foi:ptr|@fox:alt-text|@role">
     <xsl:copy-of select="."/>
   </xsl:template>
 
index 2c13edca54577d4db422e5b02555478748aa6af0..26595bca164c1efe49b4587300e4cd9024cdbf4a 100644 (file)
 
 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;
 import org.apache.fop.pdf.PDFStructElem;
@@ -30,71 +34,137 @@ import org.apache.fop.pdf.PDFStructElem;
  */
 final class FOToPDFRoleMap {
 
-    private static final Map STANDARD_MAPPINGS = new java.util.HashMap();
-
-    private static final PDFName TFOOT = new PDFName("TFoot");
-    private static final PDFName THEAD = new PDFName("THead");
-    private static final PDFName NON_STRUCT = new PDFName("NonStruct");
-
-    static {
-        addMapping("block",                     "P");
+    /**
+     * Standard structure types defined by the PDF Reference, Fourth Edition (PDF 1.5).
+     */
+    private static final Map STANDARD_STRUCTURE_TYPES = new HashMap();
 
-        PDFName st = new PDFName("Div");
-        addMapping("block-container",           st);
-        addMapping("inline-container",          st);
-        addMapping("table-and-caption",         st);
-        addMapping("float",                     st);
+    private static final Map DEFAULT_MAPPINGS = new java.util.HashMap();
 
-        st = new PDFName("Span");
-        addMapping("inline",                    st);
-        addMapping("wrapper",                   st);
-        addMapping("character",                 st);
+    private static final PDFName THEAD;
+    private static final PDFName NON_STRUCT;
 
+    static {
+        // Create PDFNames for the standard structure types
+        // Table 10.18: Grouping elements
+        addStructureType("Document");
+        addStructureType("Part");
+        addStructureType("Art");
+        addStructureType("Sect");
+        addStructureType("Div");
+        addStructureType("BlockQuote");
+        addStructureType("Caption");
+        addStructureType("TOC");
+        addStructureType("TOCI");
+        addStructureType("Index");
+        addStructureType("NonStruct");
+        addStructureType("Private");
+        // Table 10.20: Paragraphlike elements
+        addStructureType("H");
+        addStructureType("H1");
+        addStructureType("H2");
+        addStructureType("H3");
+        addStructureType("H4");
+        addStructureType("H5");
+        addStructureType("H6");
+        addStructureType("P");
+        // Table 10.21: List elements
+        addStructureType("L");
+        addStructureType("LI");
+        addStructureType("Lbl");
+        addStructureType("LBody");
+        // Table 10.22: Table elements
+        addStructureType("Table");
+        addStructureType("TR");
+        addStructureType("TH");
+        addStructureType("TD");
+        addStructureType("THead");
+        addStructureType("TBody");
+        addStructureType("TFoot");
+        // Table 10.23: Inline-level structure elements
+        addStructureType("Span");
+        addStructureType("Quote");
+        addStructureType("Note");
+        addStructureType("Reference");
+        addStructureType("BibEntry");
+        addStructureType("Code");
+        addStructureType("Link");
+        addStructureType("Annot");
+        // Table 10.24: Ruby and Warichu elements
+        addStructureType("Ruby");
+        addStructureType("RB");
+        addStructureType("RT");
+        addStructureType("RP");
+        addStructureType("Warichu");
+        addStructureType("WT");
+        addStructureType("WP");
+        // Table 10.25: Illustration elements
+        addStructureType("Figure");
+        addStructureType("Formula");
+        addStructureType("Form");
+
+        NON_STRUCT = (PDFName) STANDARD_STRUCTURE_TYPES.get("NonStruct");
+        assert NON_STRUCT != null;
+        THEAD = (PDFName) STANDARD_STRUCTURE_TYPES.get("THead");
+        assert THEAD != null;
+
+        // Create the standard mappings
+        // Declarations and Pagination and Layout Formatting Objects
         addMapping("root",                      "Document");
         addMapping("page-sequence",             "Part");
         addMapping("flow",                      "Sect");
         addMapping("static-content",            "Sect");
-
-        st = new PDFName("Quote");
-        addMapping("page-number",               st);
-        addMapping("page-number-citation",      st);
-        addMapping("page-number-citation-last", st);
-
-        st = new PDFName("Figure");
-        addMapping("external-graphic",          st);
-        addMapping("instream-foreign-object",   st);
-
-        addMapping("table-caption",             "Caption");
+        // Block-level Formatting Objects
+        addMapping("block",                     "P");
+        addMapping("block-container",           "Div");
+        // Inline-level Formatting Objects
+        addMapping("character",                 "Span");
+        addMapping("external-graphic",          "Figure");
+        addMapping("instream-foreign-object",   "Figure");
+        addMapping("inline",                    "Span");
+        addMapping("inline-container",          "Div");
+        addMapping("page-number",               "Quote");
+        addMapping("page-number-citation",      "Quote");
+        addMapping("page-number-citation-last", "Quote");
+        // Formatting Objects for Tables
+        addMapping("table-and-caption",         "Div");
         addMapping("table",                     "Table");
+        addMapping("table-caption",             "Caption");
+        addMapping("table-header",              "THead");
+        addMapping("table-footer",              "TFoot");
         addMapping("table-body",                "TBody");
-        addMapping("table-header",              THEAD);
-        addMapping("table-footer",              TFOOT);
         addMapping("table-row",                 "TR");
         addMapping("table-cell",                new TableCellMapper());
-
+        // Formatting Objects for Lists
         addMapping("list-block",                "L");
         addMapping("list-item",                 "LI");
-        addMapping("list-item-label",           "Lbl");
         addMapping("list-item-body",            "LBody");
-
+        addMapping("list-item-label",           "Lbl");
+        // Dynamic Effects: Link and Multi Formatting Objects
         addMapping("basic-link",                "Link");
+        // Out-of-Line Formatting Objects
+        addMapping("float",                     "Div");
         addMapping("footnote",                  "Note");
         addMapping("footnote-body",             "Sect");
+        addMapping("wrapper",                   "Span");
         addMapping("marker",                    "Private");
     }
 
-    private static void addMapping(String fo, String pdfName) {
-        addMapping(fo, new PDFName(pdfName));
+    private static void addStructureType(String structureType) {
+        STANDARD_STRUCTURE_TYPES.put(structureType, new PDFName(structureType));
     }
 
-    private static void addMapping(String fo, PDFName pdfName) {
-        addMapping(fo, new SimpleMapper(pdfName));
+    private static void addMapping(String fo, String structureType) {
+        PDFName type = (PDFName) STANDARD_STRUCTURE_TYPES.get(structureType);
+        assert type != null;
+        addMapping(fo, new SimpleMapper(type));
     }
 
     private static void addMapping(String fo, Mapper mapper) {
-        STANDARD_MAPPINGS.put(fo, mapper);
+        DEFAULT_MAPPINGS.put(fo, mapper);
     }
 
+
     /**
      * Maps a Formatting Object to a PDFName representing the associated structure type.
      * @param fo the formatting object's local name
@@ -102,7 +172,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)STANDARD_MAPPINGS.get(fo);
+        Mapper mapper = (Mapper)DEFAULT_MAPPINGS.get(fo);
         if (mapper != null) {
             return mapper.getStructureType(parent);
         } else {
@@ -110,7 +180,27 @@ final class FOToPDFRoleMap {
         }
     }
 
-    private interface Mapper {
+    public static PDFName mapFormattingObject(Node fo, PDFObject parent,
+            EventBroadcaster eventBroadcaster) {
+        PDFName type = null;
+        Node role = fo.getAttributes().getNamedItemNS(null, "role");
+        if (role == null) {
+            type = mapFormattingObject(fo.getLocalName(), parent);
+        } else {
+            String customType = role.getNodeValue();
+            type = (PDFName) STANDARD_STRUCTURE_TYPES.get(customType);
+            if (type == null) {
+                String foName = fo.getLocalName();
+                type = mapFormattingObject(foName, parent);
+                PDFEventProducer.Provider.get(eventBroadcaster).nonStandardStructureType(fo,
+                        foName, customType, type.toString().substring(1));
+            }
+        }
+        assert type != null;
+        return type;
+    }
+
+    private static interface Mapper {
         PDFName getStructureType(PDFObject parent);
     }
 
@@ -130,18 +220,18 @@ final class FOToPDFRoleMap {
 
     private static class TableCellMapper implements Mapper {
 
-        private static final PDFName TD = new PDFName("TD");
-        private static final PDFName TH = new PDFName("TH");
-
         public PDFName getStructureType(PDFObject parent) {
             PDFStructElem grandParent = (PDFStructElem)
                 ((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())) {
-               return TH;
+               type = (PDFName) STANDARD_STRUCTURE_TYPES.get("TH");
             } else {
-               return TD;
+                type = (PDFName) STANDARD_STRUCTURE_TYPES.get("TD");
             }
+            assert type != null;
+            return type;
         }
 
     }
index a54bbb4e75a9048c81fbf9ce21f0dac22139fc98..6025fb486d5f77e3e5679ec547c12969d33b0877 100644 (file)
@@ -145,7 +145,8 @@ public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler {
             this.accessEnabled = getUserAgent().isAccessibilityEnabled();
             if (accessEnabled) {
                 pdfDoc.getRoot().makeTagged();
-                logicalStructureHandler = new PDFLogicalStructureHandler(pdfDoc);
+                logicalStructureHandler = new PDFLogicalStructureHandler(pdfDoc,
+                        getUserAgent().getEventBroadcaster());
             }
         } catch (IOException e) {
             throw new IFException("I/O error in startDocument()", e);
index d7040987089d530b6f1e9bddcb6eb49363f3598c..4d1b3a42bd158045df77f8fbc83bce73b10494df 100644 (file)
@@ -66,4 +66,15 @@ public interface PDFEventProducer extends EventProducer {
      */
     void nonFullyResolvedLinkTargets(Object source, int count);
 
+
+    /**
+     * Custom structure type is not standard as per the PDF reference.
+     *
+     * @param source the event source
+     * @param fo the local name of the formatting object having the custom type
+     * @param type custom structure type
+     * @param fallback default structure type used as a fallback
+     * @event.severity WARN
+     */
+    void nonStandardStructureType(Object source, String fo, String type, String fallback);
 }
index fd57d50996d6495b9a0d85248bb76451c712dfe1..f6425753dc292766495247d9599229310b6c2876 100644 (file)
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <catalogue xml:lang="en">
   <message key="org.apache.fop.render.pdf.PDFEventProducer.nonFullyResolvedLinkTargets">{count} link target{count,equals,1,,s} could not be fully resolved and now point{count,equals,1,,s} to the top of the page or {count,equals,1,is,are} dysfunctional.</message>
+  <message key="org.apache.fop.render.pdf.PDFEventProducer.nonStandardStructureType">‘{type}’ is not a standard structure type defined by the PDF Reference. Falling back to ‘{fallback}’.</message>
 </catalogue>
index d55094d48e467254dbd36a8449fa7b177d24acb2..42b87327053061917ab98d091e20e6ec407640ca 100644 (file)
@@ -26,6 +26,7 @@ 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;
@@ -52,6 +53,8 @@ class PDFLogicalStructureHandler {
 
     private final PDFDocument pdfDoc;
 
+    private final EventBroadcaster eventBroadcaster;
+
     /**
      * Map of references to the corresponding structure elements.
      */
@@ -105,8 +108,9 @@ class PDFLogicalStructureHandler {
      *
      * @param pdfDoc a document
      */
-    PDFLogicalStructureHandler(PDFDocument pdfDoc) {
+    PDFLogicalStructureHandler(PDFDocument pdfDoc, EventBroadcaster eventBroadcaster) {
         this.pdfDoc = pdfDoc;
+        this.eventBroadcaster = eventBroadcaster;
         PDFStructTreeRoot structTreeRoot = pdfDoc.getFactory().makeStructTreeRoot(parentTree);
         rootStructureElement = pdfDoc.getFactory().makeStructureElement(
                 FOToPDFRoleMap.mapFormattingObject("root", structTreeRoot), structTreeRoot);
@@ -148,15 +152,15 @@ class PDFLogicalStructureHandler {
         Node attr = node.getAttributes().getNamedItemNS(InternalElementMapping.URI, "ptr");
         assert attr != null;
         String ptr = attr.getNodeValue();
-        String nodeName = node.getLocalName();
         PDFStructElem structElem = pdfDoc.getFactory().makeStructureElement(
-                FOToPDFRoleMap.mapFormattingObject(nodeName, parent), parent);
+                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");
index 5d20bbd9fcbfed238827db94d8f7f6a13879a626..a4ba08911c5450bdfc65cc0287b09daee7228ecd 100644 (file)
@@ -243,7 +243,8 @@ public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConf
         this.pdfDoc = pdfUtil.setupPDFDocument(stream);
         if (accessEnabled) {
             pdfDoc.getRoot().makeTagged();
-            logicalStructureHandler = new PDFLogicalStructureHandler(pdfDoc);
+            logicalStructureHandler = new PDFLogicalStructureHandler(pdfDoc,
+                    userAgent.getEventBroadcaster());
         }
     }
 
index f7c7fc9b24644306f11e298883e237f11f6617c5..853fbdf1699425a25ce755303b927816194ebb3b 100644 (file)
       documents. Example: the fix of marks layering will be such a case when it's done.
     -->
     <release version="FOP Trunk" date="TBD">
+      <action context="Renderers" dev="VH" type="add">
+        Added possibility to customize PDF tagging via the ‘role’ property.
+      </action>
       <action context="Renderers" dev="CB" type="fix" fixes-bug="48237" due-to="Peter Hancock">
         Bugfix: AFP Renderer: Respect image color settings for svg 
       </action>          
          <action context="Renderers" dev="CB" type="fix" fixes-bug="48376" due-to="Venkat Reddy">
         Bugfix: AFP Renderer: Page Overlays not generated when using Intermediate Format
       </action>          
-         <action context="Renderers" dev="CB" type="fix" fixes-bug="48456">
+      <action context="Renderers" dev="CB" type="fix" fixes-bug="48456">
         Bugfix: AFP Renderer: Underline is incorrectly placed when reference-orientation != 0
       </action>
       <action context="Renderers" dev="CB" type="fix" fixes-bug="48453">
index cbe2879e1c6132ea7c1d391918c7077642e1fb32..391d3905517a5975f41a7bcfb19b1380771e20b4 100644 (file)
@@ -1,5 +1,5 @@
-his directory contains sample FO files for testing the accessibility features of 
-FOP.
+This directory contains sample FO files for testing the accessibility features
+of FOP.
 
 To every FO file in this directory correspond two PDF files in the pdf/ 
 sub-directory: one generated by the painter, one by the renderer. For example, 
index 03c57b212fc4c4c8b9896637b0845bbf57bd6cdc..81df372b5c483fdcd7b23e08badc3ab8943d8f19 100644 (file)
     <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
       <fo:block>(There’s another page sequence <fo:wrapper color="blue"><fo:basic-link 
             internal-destination="second">below</fo:basic-link></fo:wrapper>.)</fo:block>
-      <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL 
-        formatting objects (XSL-FO) and an output independent formatter<fo:footnote><fo:inline 
-            baseline-shift="super" font-size="70%">1</fo:inline><fo:footnote-body><fo:block>See the 
-              <fo:wrapper color="blue"><fo:basic-link 
+      <fo:block font-family="sans-serif" font-weight="bold" space-before="1em" space-after="0.2em" 
+        role="H1"><fo:block>About Apache FOP</fo:block></fo:block>
+      <fo:block>It is a print formatter driven by XSL formatting objects (XSL-FO) and an output 
+        independent formatter<fo:footnote><fo:inline baseline-shift="super" 
+            font-size="70%">1</fo:inline><fo:footnote-body><fo:block>See the <fo:wrapper 
+                color="blue"><fo:basic-link 
                   external-destination="http://xmlgraphics.apache.org/fop/">FOP 
                   website</fo:basic-link></fo:wrapper> for more 
               information</fo:block></fo:footnote-body></fo:footnote>. FOP has a nice logo: 
index 856e8ca92876e1f684c3db2b74381c70f3a2a14f..caf7a41f82189ec3ac7f42e5887d893da654e580 100644 (file)
Binary files a/test/accessibility/pdf/complete_painter_orig.pdf and b/test/accessibility/pdf/complete_painter_orig.pdf differ
index bcca16076f508d22814f3334f8cee739cffa054c..e7e4ed6c147d55e932ef589a290869c6d1446f67 100644 (file)
Binary files a/test/accessibility/pdf/complete_renderer_orig.pdf and b/test/accessibility/pdf/complete_renderer_orig.pdf differ
diff --git a/test/accessibility/pdf/role_non-standard_painter_orig.pdf b/test/accessibility/pdf/role_non-standard_painter_orig.pdf
new file mode 100644 (file)
index 0000000..f8b1c9d
Binary files /dev/null and b/test/accessibility/pdf/role_non-standard_painter_orig.pdf differ
diff --git a/test/accessibility/pdf/role_non-standard_renderer_orig.pdf b/test/accessibility/pdf/role_non-standard_renderer_orig.pdf
new file mode 100644 (file)
index 0000000..1700d7c
Binary files /dev/null and b/test/accessibility/pdf/role_non-standard_renderer_orig.pdf differ
diff --git a/test/accessibility/pdf/role_painter_orig.pdf b/test/accessibility/pdf/role_painter_orig.pdf
new file mode 100644 (file)
index 0000000..1eaaf1a
Binary files /dev/null and b/test/accessibility/pdf/role_painter_orig.pdf differ
diff --git a/test/accessibility/pdf/role_renderer_orig.pdf b/test/accessibility/pdf/role_renderer_orig.pdf
new file mode 100644 (file)
index 0000000..fc8e002
Binary files /dev/null and b/test/accessibility/pdf/role_renderer_orig.pdf differ
diff --git a/test/accessibility/role.fo b/test/accessibility/role.fo
new file mode 100644 (file)
index 0000000..e284cde
--- /dev/null
@@ -0,0 +1,125 @@
+<?xml version="1.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$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="page"
+      page-height="220pt" page-width="320pt" margin="10pt">
+      <fo:region-body/>
+    </fo:simple-page-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="page" language="en" country="GB">
+    <fo:flow flow-name="xsl-region-body" hyphenate="true" font-family="sans-serif">
+      <fo:block role="H1" font-weight="bold" font-size="150%"
+        space-before.minimum="1.5em"
+        space-before.optimum="2em"
+        space-before.maximum="3em"
+        space-before.precedence="1000"
+        space-after.minimum="0.2em"
+        space-after.optimum="0.2em"
+        space-after.maximum="0.5em"
+        space-after.precedence="1000">Title 1: To Start With</fo:block>
+      <fo:block role="H2" font-weight="bold" font-size="120%"
+        space-before.minimum="1.2em"
+        space-before.optimum="1.5em"
+        space-before.maximum="2em"
+        space-before.precedence="900"
+        space-after.minimum="0.2em"
+        space-after.optimum="0.2em"
+        space-after.maximum="0.5em"
+        space-after.precedence="900">Title 2: A Sub-Title</fo:block>
+      <fo:block text-align="justify">Apache FOP (Formatting Objects Processor) is a print formatter 
+        driven by XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java 
+        application that reads a formatting object (FO) tree and renders the resulting pages to a 
+        specified output.</fo:block>
+      <fo:block role="H2" font-weight="bold" font-size="120%"
+        space-before.minimum="1.2em"
+        space-before.optimum="1.5em"
+        space-before.maximum="2em"
+        space-before.precedence="900"
+        space-after.minimum="0.2em"
+        space-after.optimum="0.2em"
+        space-after.maximum="0.5em"
+        space-after.precedence="900">Title 2: Another Sub-Title</fo:block>
+      <fo:block text-align="justify">Apache FOP (Formatting Objects Processor) is a print formatter 
+        driven by XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java 
+        application that reads a formatting object (FO) tree and renders the resulting pages to a 
+        specified output.</fo:block>
+      <fo:block role="H1" font-weight="bold" font-size="150%"
+        space-before.minimum="1.5em"
+        space-before.optimum="2em"
+        space-before.maximum="3em"
+        space-before.precedence="1000"
+        space-after.minimum="0.2em"
+        space-after.optimum="0.2em"
+        space-after.maximum="0.5em"
+        space-after.precedence="1000">Title 1: Second Title</fo:block>
+      <fo:block role="H2" font-weight="bold" font-size="120%"
+        space-before.minimum="1.2em"
+        space-before.optimum="1.5em"
+        space-before.maximum="2em"
+        space-before.precedence="900"
+        space-after.minimum="0.2em"
+        space-after.optimum="0.2em"
+        space-after.maximum="0.5em"
+        space-after.precedence="900">Title 2: A Sample Table</fo:block>
+      <fo:block>See data below:</fo:block>
+      <fo:table table-layout="fixed" width="70%" start-indent="15%" border="0.5pt solid black">
+        <fo:table-header start-indent="0" font-weight="bold">
+          <fo:table-row>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Header 1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Header 2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+        </fo:table-header>
+        <fo:table-footer start-indent="0" font-weight="bold">
+          <fo:table-row>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Footer 1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Footer 2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+        </fo:table-footer>
+        <fo:table-body start-indent="0">
+          <fo:table-row>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Cell 1.1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Cell 1.2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+          <fo:table-row>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Cell 2.1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Cell 2.2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+        </fo:table-body>
+      </fo:table>
+      <fo:block text-align="justify" space-before="0.5em">That’s all folks.</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
diff --git a/test/accessibility/role_non-standard.fo b/test/accessibility/role_non-standard.fo
new file mode 100644 (file)
index 0000000..b6641aa
--- /dev/null
@@ -0,0 +1,125 @@
+<?xml version="1.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$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="page"
+      page-height="220pt" page-width="320pt" margin="10pt">
+      <fo:region-body/>
+    </fo:simple-page-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="page" language="en" country="GB">
+    <fo:flow flow-name="xsl-region-body" hyphenate="true" font-family="sans-serif">
+      <fo:block role="H1" font-weight="bold" font-size="150%"
+        space-before.minimum="1.5em"
+        space-before.optimum="2em"
+        space-before.maximum="3em"
+        space-before.precedence="1000"
+        space-after.minimum="0.2em"
+        space-after.optimum="0.2em"
+        space-after.maximum="0.5em"
+        space-after.precedence="1000">Title 1: To Start With</fo:block>
+      <fo:block role="Header2" font-weight="bold" font-size="120%"
+        space-before.minimum="1.2em"
+        space-before.optimum="1.5em"
+        space-before.maximum="2em"
+        space-before.precedence="900"
+        space-after.minimum="0.2em"
+        space-after.optimum="0.2em"
+        space-after.maximum="0.5em"
+        space-after.precedence="900">A Sub-Title With a Non-Standard Role</fo:block>
+      <fo:block text-align="justify">Apache FOP (Formatting Objects Processor) is a print formatter 
+        driven by XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java 
+        application that reads a formatting object (FO) tree and renders the resulting pages to a 
+        specified output.</fo:block>
+      <fo:block role="H2" font-weight="bold" font-size="120%"
+        space-before.minimum="1.2em"
+        space-before.optimum="1.5em"
+        space-before.maximum="2em"
+        space-before.precedence="900"
+        space-after.minimum="0.2em"
+        space-after.optimum="0.2em"
+        space-after.maximum="0.5em"
+        space-after.precedence="900">Title 2: Another Sub-Title</fo:block>
+      <fo:block text-align="justify">Apache FOP (Formatting Objects Processor) is a print formatter 
+        driven by XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java 
+        application that reads a formatting object (FO) tree and renders the resulting pages to a 
+        specified output.</fo:block>
+      <fo:block role="H1" font-weight="bold" font-size="150%"
+        space-before.minimum="1.5em"
+        space-before.optimum="2em"
+        space-before.maximum="3em"
+        space-before.precedence="1000"
+        space-after.minimum="0.2em"
+        space-after.optimum="0.2em"
+        space-after.maximum="0.5em"
+        space-after.precedence="1000">Title 1: Second Title</fo:block>
+      <fo:block role="H2" font-weight="bold" font-size="120%"
+        space-before.minimum="1.2em"
+        space-before.optimum="1.5em"
+        space-before.maximum="2em"
+        space-before.precedence="900"
+        space-after.minimum="0.2em"
+        space-after.optimum="0.2em"
+        space-after.maximum="0.5em"
+        space-after.precedence="900">Title 2: A Sample Table</fo:block>
+      <fo:block>See data below:</fo:block>
+      <fo:table table-layout="fixed" width="70%" start-indent="15%" border="0.5pt solid black">
+        <fo:table-header start-indent="0" font-weight="bold" role="TableHeader">
+          <fo:table-row>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Header 1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Header 2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+        </fo:table-header>
+        <fo:table-footer start-indent="0" font-weight="bold">
+          <fo:table-row>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Footer 1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Footer 2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+        </fo:table-footer>
+        <fo:table-body start-indent="0">
+          <fo:table-row>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Cell 1.1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Cell 1.2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+          <fo:table-row>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Cell 2.1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Cell 2.2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+        </fo:table-body>
+      </fo:table>
+      <fo:block text-align="justify" space-before="0.5em">That’s all folks.</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>