]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Bugzilla #53980: PDF accessibility: Store language information coming from fo:block...
authorVincent Hennebert <vhennebert@apache.org>
Mon, 8 Oct 2012 17:47:48 +0000 (17:47 +0000)
committerVincent Hennebert <vhennebert@apache.org>
Mon, 8 Oct 2012 17:47:48 +0000 (17:47 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1395692 13f79535-47bb-0310-9956-ffa450edef68

24 files changed:
src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java
src/java/org/apache/fop/area/AreaTreeParser.java
src/java/org/apache/fop/area/PageSequence.java
src/java/org/apache/fop/fo/pagination/PageSequence.java
src/java/org/apache/fop/fo/pagination/Root.java
src/java/org/apache/fop/fo/properties/CommonHyphenation.java
src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java
src/java/org/apache/fop/render/intermediate/IFRenderer.java
src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java
src/java/org/apache/fop/render/xml/XMLRenderer.java
status.xml
test/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverterTestCase.java
test/java/org/apache/fop/accessibility/fo/fo2StructureTree.xsl
test/java/org/apache/fop/accessibility/fo/language.fo [new file with mode: 0644]
test/java/org/apache/fop/fo/properties/CommonHyphenationTestCase.java [new file with mode: 0644]
test/layoutengine/hyphenation-testcases/block_hyphenation_kerning.xml
test/layoutengine/standard-testcases/page-sequence_language.xml
test/pdf/accessibility/language.fo [new file with mode: 0644]
test/pdf/accessibility/pdf/complete.pdf
test/pdf/accessibility/pdf/language.pdf [new file with mode: 0644]
test/pdf/accessibility/pdf/side-regions.pdf
test/pdf/accessibility/pdf/table_row-col-span.pdf
test/pdf/accessibility/pdf/text_2.pdf
test/pdf/accessibility/pdf/th_scope.pdf

index 09a814ef59044c9b9ea5a32b2fd5b1c6438d2687..6a763a6f67c6f8c1e33ff5f8fc30fbddc160ff32 100644 (file)
@@ -22,7 +22,8 @@ package org.apache.fop.accessibility.fo;
 import java.util.Locale;
 import java.util.Stack;
 
-import org.xml.sax.SAXException;
+import javax.xml.XMLConstants;
+
 import org.xml.sax.helpers.AttributesImpl;
 
 import org.apache.fop.accessibility.StructureTreeElement;
@@ -59,8 +60,11 @@ import org.apache.fop.fo.flow.table.TableRow;
 import org.apache.fop.fo.pagination.Flow;
 import org.apache.fop.fo.pagination.LayoutMasterSet;
 import org.apache.fop.fo.pagination.PageSequence;
+import org.apache.fop.fo.pagination.Root;
 import org.apache.fop.fo.pagination.StaticContent;
 import org.apache.fop.fo.properties.CommonAccessibilityHolder;
+import org.apache.fop.fo.properties.CommonHyphenation;
+import org.apache.fop.util.LanguageTags;
 import org.apache.fop.util.XMLUtil;
 
 /**
@@ -76,16 +80,20 @@ class StructureTreeEventTrigger extends FOEventHandler {
 
     private final Stack<Boolean> inTableHeader = new Stack<Boolean>();
 
+    private final Stack<Locale> locales = new Stack<Locale>();
+
     public StructureTreeEventTrigger(StructureTreeEventHandler structureTreeEventHandler) {
         this.structureTreeEventHandler = structureTreeEventHandler;
     }
 
     @Override
-    public void startDocument() throws SAXException {
+    public void startRoot(Root root) {
+        locales.push(root.getLocale());
     }
 
     @Override
-    public void endDocument() throws SAXException {
+    public void endRoot(Root root) {
+        locales.pop();
     }
 
     @Override
@@ -93,13 +101,11 @@ class StructureTreeEventTrigger extends FOEventHandler {
         if (layoutMasterSet == null) {
             layoutMasterSet = pageSeq.getRoot().getLayoutMasterSet();
         }
-        Locale locale = null;
-        if (pageSeq.getLanguage() != null) {
-            if (pageSeq.getCountry() != null) {
-                locale = new Locale(pageSeq.getLanguage(), pageSeq.getCountry());
-            } else {
-                locale = new Locale(pageSeq.getLanguage());
-            }
+        Locale locale = pageSeq.getLocale();
+        if (locale != null) {
+            locales.push(locale);
+        } else {
+            locales.push(locales.peek());
         }
         String role = pageSeq.getCommonAccessibility().getRole();
         structureTreeEventHandler.startPageSequence(locale, role);
@@ -108,6 +114,7 @@ class StructureTreeEventTrigger extends FOEventHandler {
     @Override
     public void endPageSequence(PageSequence pageSeq) {
         structureTreeEventHandler.endPageSequence();
+        locales.pop();
     }
 
     @Override
@@ -171,12 +178,28 @@ class StructureTreeEventTrigger extends FOEventHandler {
 
     @Override
     public void startBlock(Block bl) {
-        startElement(bl);
+        CommonHyphenation hyphProperties = bl.getCommonHyphenation();
+        AttributesImpl attributes = createLangAttribute(hyphProperties);
+        startElement(bl, attributes);
+    }
+
+    private AttributesImpl createLangAttribute(CommonHyphenation hyphProperties) {
+        Locale locale = hyphProperties.getLocale();
+        AttributesImpl attributes = new AttributesImpl();
+        if (locale == null || locale.equals(locales.peek())) {
+            locales.push(locales.peek());
+        } else {
+            locales.push(locale);
+            addAttribute(attributes, XMLConstants.XML_NS_URI, "lang", "xml",
+                    LanguageTags.toLanguageTag(locale));
+        }
+        return attributes;
     }
 
     @Override
     public void endBlock(Block bl) {
         endElement(bl);
+        locales.pop();
     }
 
     @Override
@@ -393,8 +416,10 @@ class StructureTreeEventTrigger extends FOEventHandler {
 
     @Override
     public void character(Character c) {
-        startElementWithID(c);
+        AttributesImpl attributes = createLangAttribute(c.getCommonHyphenation());
+        startElementWithID(c, attributes);
         endElement(c);
+        locales.pop();
     }
 
     @Override
@@ -409,7 +434,10 @@ class StructureTreeEventTrigger extends FOEventHandler {
     }
 
     private void startElementWithID(FONode node) {
-        AttributesImpl attributes = new AttributesImpl();
+        startElementWithID(node, new AttributesImpl());
+    }
+
+    private void startElementWithID(FONode node, AttributesImpl attributes) {
         String localName = node.getLocalName();
         if (node instanceof CommonAccessibilityHolder) {
             addRole((CommonAccessibilityHolder) node, attributes);
index e965d15fc1fb78e7a95ac942260d20e816954197..a606f97270bd5692c4de2e4abdeab74dd9e7fa68 100644 (file)
@@ -84,6 +84,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.LanguageTags;
 import org.apache.fop.util.XMLConstants;
 import org.apache.fop.util.XMLUtil;
 
@@ -394,10 +395,10 @@ public class AreaTreeParser {
 
             public void startElement(Attributes attributes) {
                 PageSequence pageSequence = new PageSequence(null);
-                String lang = attributes.getValue("language");
-                pageSequence.setLanguage(lang);
-                String country = attributes.getValue("country");
-                pageSequence.setCountry(country);
+                String lang = attributes.getValue(javax.xml.XMLConstants.XML_NS_URI, "lang");
+                if (lang != null) {
+                    pageSequence.setLocale(LanguageTags.toLocale(lang));
+                }
                 transferForeignObjects(attributes, pageSequence);
                 areaStack.push(pageSequence);
             }
index 1f0411b006b2817472757be7a380c3fffe95d392..1244766022053ea9fb3bbb18f7499957374e4528 100644 (file)
@@ -20,6 +20,7 @@
 package org.apache.fop.area;
 
 import java.util.List;
+import java.util.Locale;
 
 /**
  * Represents a page sequence in the area tree.
@@ -28,8 +29,8 @@ public class PageSequence extends AreaTreeObject {
 
     private List<PageViewport> pages = new java.util.ArrayList<PageViewport>();
     private LineArea title;
-    private String language;
-    private String country;
+
+    private Locale locale;
 
     /**
      * Main constructor
@@ -88,43 +89,21 @@ public class PageSequence extends AreaTreeObject {
     }
 
     /**
-     * Returns the language of the page-sequence.
-     * @return the language (the value of the language property, "none" is mapped to null)
-     */
-    public String getLanguage() {
-        return this.language;
-    }
-
-    /**
-     * Sets the language that applies to this page-sequence.
-     * @param language the language to set ("none" is mapped to null)
-     */
-    public void setLanguage(String language) {
-        if ("none".equals(language)) {
-            this.language = null;
-        } else {
-            this.language = language;
-        }
-    }
-
-    /**
-     * Returns the country of the page-sequence.
-     * @return the country (the value of the country property, "none" is mapped to null)
+     * Sets the locale that applies to this page-sequence.
+     *
+     * @param locale the locale to set
      */
-    public String getCountry() {
-        return this.country;
+    public void setLocale(Locale locale) {
+        this.locale = locale;
     }
 
     /**
-     * Sets the country that applies to this page-sequence.
-     * @param country the country to set ("none" is mapped to null)
+     * Returns the locale of this page-sequence.
+     *
+     * @return the locale, {@code null} if not set
      */
-    public void setCountry(String country) {
-        if ("none".equals(country)) {
-            this.country = null;
-        } else {
-            this.country = country;
-        }
+    public Locale getLocale() {
+        return locale;
     }
 
 }
index 63114b507a3455500bcb887b07b4d81113cf8609..6039dafebf1b45b96d03b2b1aaf9a7b6e6a2ff5c 100644 (file)
@@ -19,6 +19,7 @@
 
 package org.apache.fop.fo.pagination;
 
+import java.util.Locale;
 import java.util.Map;
 import java.util.Stack;
 
@@ -30,6 +31,7 @@ import org.apache.fop.datatypes.Numeric;
 import org.apache.fop.fo.FONode;
 import org.apache.fop.fo.PropertyList;
 import org.apache.fop.fo.ValidationException;
+import org.apache.fop.fo.properties.CommonHyphenation;
 import org.apache.fop.traits.Direction;
 import org.apache.fop.traits.WritingMode;
 import org.apache.fop.traits.WritingModeTraits;
@@ -41,13 +43,11 @@ import org.apache.fop.traits.WritingModeTraitsGetter;
  */
 public class PageSequence extends AbstractPageSequence implements WritingModeTraitsGetter {
 
-    // The value of FO traits (refined properties) that apply to fo:page-sequence.
-    private String country;
-    private String language;
     private String masterReference;
     private Numeric referenceOrientation;
     private WritingModeTraits writingModeTraits;
-    // End of trait values
+
+    private Locale locale;
 
     // There doesn't seem to be anything in the spec requiring flows
     // to be in the order given, only that they map to the regions
@@ -90,8 +90,9 @@ public class PageSequence extends AbstractPageSequence implements WritingModeTra
     /** {@inheritDoc} */
     public void bind(PropertyList pList) throws FOPException {
         super.bind(pList);
-        country = pList.get(PR_COUNTRY).getString();
-        language = pList.get(PR_LANGUAGE).getString();
+        String country = pList.get(PR_COUNTRY).getString();
+        String language = pList.get(PR_LANGUAGE).getString();
+        locale = CommonHyphenation.toLocale(language, country);
         masterReference = pList.get(PR_MASTER_REFERENCE).getString();
         referenceOrientation = pList.get(PR_REFERENCE_ORIENTATION).getNumeric();
         writingModeTraits = new WritingModeTraits
@@ -320,20 +321,8 @@ public class PageSequence extends AbstractPageSequence implements WritingModeTra
         return FO_PAGE_SEQUENCE;
     }
 
-    /**
-     * Get the value of the <code>country</code> trait.
-     * @return the country trait value
-     */
-    public String getCountry() {
-        return this.country;
-    }
-
-    /**
-     * Get the value of the <code>language</code> trait.
-     * @return the language trait value
-     */
-    public String getLanguage() {
-        return this.language;
+    public Locale getLocale() {
+        return locale;
     }
 
     /**
index 1a2ce718beee3f654f8e7a92bbca4b4b62386d6c..6db8d6db1167eb91641ee5482a21872802f10d7a 100644 (file)
@@ -36,6 +36,7 @@ import org.apache.fop.fo.extensions.destination.Destination;
 import org.apache.fop.fo.pagination.bookmarks.BookmarkTree;
 import org.apache.fop.fo.properties.CommonAccessibility;
 import org.apache.fop.fo.properties.CommonAccessibilityHolder;
+import org.apache.fop.fo.properties.CommonHyphenation;
 
 /**
  * Class modeling the <a href="http://www.w3.org/TR/xsl/#fo_root">
@@ -92,17 +93,7 @@ public class Root extends FObj implements CommonAccessibilityHolder {
         mediaUsage = pList.get(PR_MEDIA_USAGE).getEnum();
         String language = pList.get(PR_LANGUAGE).getString();
         String country = pList.get(PR_COUNTRY).getString();
-        if (isLocalePropertySet(language)) {
-            if (isLocalePropertySet(country)) {
-                locale = new Locale(language, country);
-            } else {
-                locale = new Locale(language);
-            }
-        }
-    }
-
-    private boolean isLocalePropertySet(String property) {
-        return property != null && !property.equals("none");
+        locale = CommonHyphenation.toLocale(language, country);
     }
 
      /** {@inheritDoc} */
index 8394a4b189032f83bf08c9803258cad8177eb1ee..d5f4c538b54176dcc59fe6b2ab0c12853b0d2b31 100644 (file)
@@ -19,6 +19,8 @@
 
 package org.apache.fop.fo.properties;
 
+import java.util.Locale;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -185,6 +187,41 @@ public final class CommonHyphenation {
         return font.getCharWidth(hyphChar);
     }
 
+    /**
+     * Creates and returns a {@link Locale} representation of the language and country.
+     *
+     * @return the language (and the country if set) represented as a locale, {@code null}
+     * if the language has not been set (i.e., has been left to its initial value of
+     * "none")
+     */
+    public Locale getLocale() {
+        return toLocale(language.getString(), country.getString());
+    }
+
+    /**
+     * Creates and returns a {@link Locale} representation of the given language, and the
+     * given country if set. The country is considered to be set if not {@code null} and
+     * not set to "none".
+     *
+     * @return the language and country represented as a locale, {@code null} if the
+     * language is null or "none" (case insensitive)
+     */
+    public static Locale toLocale(String language, String country) {
+        Locale locale = null;
+        if (isDefined(language)) {
+            if (isDefined(country)) {
+                locale = new Locale(language, country);
+            } else {
+                locale = new Locale(language);
+            }
+        }
+        return locale;
+    }
+
+    private static boolean isDefined(String property) {
+        return !(property == null || property.equalsIgnoreCase("none"));
+    }
+
     /** {@inheritDoc} */
     public boolean equals(Object obj) {
         if (obj == this) {
index 43f231cf3efddb6aeec30b00447c37a2241798a5..577f172ebf873626e00ec4f034d7025ba97c787a 100644 (file)
@@ -99,8 +99,7 @@ public class PageSequenceLayoutManager extends AbstractPageSequenceLayoutManager
         org.apache.fop.area.PageSequence pageSequenceAreaObject
                 = new org.apache.fop.area.PageSequence(title);
         transferExtensions(pageSequenceAreaObject);
-        pageSequenceAreaObject.setLanguage(getPageSequence().getLanguage());
-        pageSequenceAreaObject.setCountry(getPageSequence().getCountry());
+        pageSequenceAreaObject.setLocale(getPageSequence().getLocale());
         areaTreeModel.startPageSequence(pageSequenceAreaObject);
         if (log.isDebugEnabled()) {
             log.debug("Starting layout");
index 57f13ac071e28f382d773e1f515be0b59ede5901..771929809f30846d8bc71e5a1999b73333d155f7 100644 (file)
@@ -520,7 +520,7 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
                 this.inPageSequence = true;
             }
             establishForeignAttributes(pageSequence.getForeignAttributes());
-            documentHandler.getContext().setLanguage(toLocale(pageSequence));
+            documentHandler.getContext().setLanguage(pageSequence.getLocale());
             documentHandler.startPageSequence(null);
             resetForeignAttributes();
             processExtensionAttachments(pageSequence);
@@ -529,17 +529,6 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
         }
     }
 
-    private Locale toLocale(PageSequence pageSequence) {
-        if (pageSequence.getLanguage() != null) {
-            if (pageSequence.getCountry() != null) {
-                return new Locale(pageSequence.getLanguage(), pageSequence.getCountry());
-            } else {
-                return new Locale(pageSequence.getLanguage());
-            }
-        }
-        return null;
-    }
-
     private Metadata createDefaultDocumentMetadata() {
         Metadata xmp = new Metadata();
         DublinCoreAdapter dc = DublinCoreSchema.getAdapter(xmp);
index 031224ffb956c18bc5a6fdca34ef41c5d505ad43..08aad08f6159d4aff66dd48cd7fa97b10020cc96 100644 (file)
@@ -23,6 +23,8 @@ import java.util.LinkedList;
 import java.util.Locale;
 import java.util.Map;
 
+import javax.xml.XMLConstants;
+
 import org.xml.sax.Attributes;
 import org.xml.sax.helpers.AttributesImpl;
 
@@ -42,6 +44,7 @@ import org.apache.fop.pdf.StandardStructureTypes.Grouping;
 import org.apache.fop.pdf.StandardStructureTypes.Table;
 import org.apache.fop.pdf.StructureHierarchyMember;
 import org.apache.fop.pdf.StructureType;
+import org.apache.fop.util.LanguageTags;
 import org.apache.fop.util.XMLUtil;
 
 class PDFStructureTreeBuilder implements StructureTreeEventHandler {
@@ -62,10 +65,10 @@ class PDFStructureTreeBuilder implements StructureTreeEventHandler {
         addBuilder("static-content",            regionBuilder);
         addBuilder("flow",                      regionBuilder);
         // Block-level Formatting Objects
-        addBuilder("block",                     StandardStructureTypes.Paragraphlike.P);
+        addBuilder("block", new LanguageHolderBuilder(StandardStructureTypes.Paragraphlike.P));
         addBuilder("block-container",           StandardStructureTypes.Grouping.DIV);
         // Inline-level Formatting Objects
-        addBuilder("character",                 StandardStructureTypes.InlineLevelStructure.SPAN);
+        addBuilder("character", new LanguageHolderBuilder(StandardStructureTypes.InlineLevelStructure.SPAN));
         addBuilder("external-graphic",          new ImageBuilder());
         addBuilder("instream-foreign-object",   new ImageBuilder());
         addBuilder("inline",                    StandardStructureTypes.InlineLevelStructure.SPAN);
@@ -192,6 +195,23 @@ class PDFStructureTreeBuilder implements StructureTreeEventHandler {
 
     }
 
+    private static class LanguageHolderBuilder extends DefaultStructureElementBuilder {
+
+        LanguageHolderBuilder(StructureType structureType) {
+            super(structureType);
+        }
+
+        @Override
+        protected void setAttributes(PDFStructElem structElem, Attributes attributes) {
+            String xmlLang = attributes.getValue(XMLConstants.XML_NS_URI, "lang");
+            if (xmlLang != null) {
+                Locale locale = LanguageTags.toLocale(xmlLang);
+                structElem.setLanguage(locale);
+            }
+        }
+
+    }
+
     private static class ImageBuilder extends DefaultStructureElementBuilder {
 
         ImageBuilder() {
index cf3cbe5a2ae46fe8eca0c3c0ede2cace9c13401a..4a920d18df3f3c95b14c4a0e03892e4808c4bc9c 100644 (file)
@@ -27,8 +27,10 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 
+import javax.xml.XMLConstants;
 import javax.xml.transform.TransformerConfigurationException;
 import javax.xml.transform.sax.SAXTransformerFactory;
 import javax.xml.transform.sax.TransformerHandler;
@@ -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.LanguageTags;
 import org.apache.fop.util.XMLUtil;
 
 /**
@@ -450,11 +453,9 @@ public class XMLRenderer extends AbstractXMLRenderer {
         endPageSequence();  // move this before handleDocumentExtensionAttachments() ?
         startedSequence = true;
         atts.clear();
-        if (pageSequence.getLanguage() != null) {
-            addAttribute("language", pageSequence.getLanguage());
-        }
-        if (pageSequence.getCountry() != null) {
-            addAttribute("country", pageSequence.getCountry());
+        Locale locale = pageSequence.getLocale();
+        if (locale != null) {
+            addAttribute(new QName(XMLConstants.XML_NS_URI, "xml:lang"), LanguageTags.toLanguageTag(locale));
         }
         transferForeignObjects(pageSequence);
         startElement("pageSequence", atts);
index 76b25a9eb44841083709f68b125b412fd6525be5..78cf4efc2412afbc30e5479f9c835e2a8863b907 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" fixes-bug="53980">
+        PDF accessibility: Store language information coming from fo:block or fo:character in the 
+        structure tree.
+      </action>
       <action context="Layout" dev="MH" type="add" fixes-bug="53924" due-to="Luis Bernardo">
         Support for retrieve-table-markers
       </action>
index 87b9705763b10be94a3226b5904f76ff0678224d..a86b5b2b264e0742d7ccb82c3d1c7cf6bd5c9efb 100644 (file)
@@ -96,6 +96,11 @@ public class FO2StructureTreeConverterTestCase {
         testConverter("table-header_scope.fo");
     }
 
+    @Test
+    public void testLanguage() throws Exception {
+        testConverter("language.fo");
+    }
+
     private static InputStream getResource(String name) {
         return FO2StructureTreeConverterTestCase.class.getResourceAsStream(name);
     }
index 90d74a7c4a97b5e434cc85049ade70fe8c5250ee..a9de38db1a5ca7e19bbbc771c501d6236bbae79b 100644 (file)
   <xsl:template match="fo:leader"/>
 
 
-  <!-- Keep fox:alt-text and role attributes, discard everything else -->
+  <!-- Keep the relevant attributes, discard everything else -->
   <xsl:template match="@fox:alt-text|@role">
     <xsl:copy-of select="."/>
   </xsl:template>
 
+  <xsl:template match="fo:block/@language[. != ../ancestor::*[@language][1]/@language]
+                  |fo:character/@language[. != ../ancestor::*[@language][1]/@language]">
+    <xsl:attribute name="xml:lang">
+      <xsl:value-of select="."/>
+      <xsl:if test="../@country[. != 'none']">
+        <xsl:text>-</xsl:text>
+        <xsl:value-of select="../@country"/>
+      </xsl:if>
+    </xsl:attribute>
+  </xsl:template>
+
   <xsl:template match="@*"/>
 
 
diff --git a/test/java/org/apache/fop/accessibility/fo/language.fo b/test/java/org/apache/fop/accessibility/fo/language.fo
new file mode 100644 (file)
index 0000000..8dfb269
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" standalone="no"?>
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
+  xmlns:fox="http://xmlgraphics.apache.org/fop/extensions"
+  font-family="sans-serif">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="page"
+      page-height="170pt" page-width="220pt" margin="10pt">
+      <fo:region-body display-align="center"/>
+    </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" line-height="10pt" font-size="8pt" space-before="5pt" 
+      space-after="5pt">
+      <fo:block>This block of text is written in the default language of the page sequence, which is 
+        British English.</fo:block>
+      <fo:block language="fr" country="FR" space-before="inherit" space-after="inherit">Ce text est 
+        écrit dans une autre langue, en l’occurence le français de France.
+        <fo:block language="en" country="US" space-before="inherit" start-indent="1em" 
+          space-after="inherit">However, this block of French text encloses a block of American 
+          English.
+          <fo:block space-before="inherit" start-indent="2em" space-after="inherit" language="en" 
+            country="US">The structure element corresponding to this block should have no language 
+            set as it is the same as on the parent block.</fo:block></fo:block>
+        Maintenant on revient au français.</fo:block>
+      <fo:block space-before="inherit">And now we are back to the English language, with a 
+        <fo:character character="F" language="fr" country="none" color="blue"/>rench 
+        character.</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
diff --git a/test/java/org/apache/fop/fo/properties/CommonHyphenationTestCase.java b/test/java/org/apache/fop/fo/properties/CommonHyphenationTestCase.java
new file mode 100644 (file)
index 0000000..0291464
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * 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.fo.properties;
+
+import java.util.Locale;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+public class CommonHyphenationTestCase {
+
+    private final String lang = "en";
+
+    @Test
+    public void testToLocaleNull() {
+        Locale locale = CommonHyphenation.toLocale(null, null);
+        assertNull(locale);
+        locale = CommonHyphenation.toLocale("none", null);
+        assertNull(locale);
+        locale = CommonHyphenation.toLocale("NoNe", "US");
+        assertNull(locale);
+    }
+
+    @Test
+    public void testToLocaleWithJustLanguage() {
+        Locale locale = new Locale(lang);
+        assertEquals(locale, CommonHyphenation.toLocale(lang, null));
+        assertEquals(locale, CommonHyphenation.toLocale(lang, "none"));
+        assertEquals(locale, CommonHyphenation.toLocale(lang, "NONE"));
+    }
+
+    @Test
+    public void testToLocaleWithLanguageAndCountry() {
+        Locale locale = new Locale(lang, "US");
+        assertEquals(locale, CommonHyphenation.toLocale(lang, "US"));
+        assertEquals(locale, CommonHyphenation.toLocale(lang, "us"));
+    }
+
+}
index 084f1e685c0fb9774a1c0f3f35eab54f746622dd..9f94969cb8108505d2beb1b792e4637bb6b78122 100644 (file)
@@ -45,8 +45,7 @@
   </fo>
   <checks>
     <eval expected="1" xpath="count(//pageViewport)"/>
-    <eval expected="en" xpath="/areaTree/pageSequence/@language"/>
-    <true xpath="not(boolean(/areaTree/pageSequence/@country))"/>
+    <eval expected="en" xpath="/areaTree/pageSequence/@xml:lang"/>
     
     <eval expected="17230" xpath="//flow/block[1]/lineArea[1]/text[1]/@twsadjust"/>
     <eval expected="-1339" xpath="//flow/block[1]/lineArea[2]/text[1]/@twsadjust"/>
index f2fa610bc38a4ae8b55f91458dfdd223014183b4..4ff0fe3b3f4136e0c3c48a0b08ea782feb3238cd 100644 (file)
     </fo:root>
   </fo>
   <checks>
-    <eval expected="en" xpath="/areaTree/pageSequence[1]/@language"/>
-    <true xpath="not(boolean(/areaTree/pageSequence[1]/@country))"/>
+    <eval expected="en" xpath="/areaTree/pageSequence[1]/@xml:lang"/>
 
-    <eval expected="en" xpath="/areaTree/pageSequence[2]/@language"/>
-    <eval expected="US" xpath="/areaTree/pageSequence[2]/@country"/>
+    <eval expected="en-US" xpath="/areaTree/pageSequence[2]/@xml:lang"/>
     
-    <eval expected="de" xpath="/areaTree/pageSequence[3]/@language"/>
-    <eval expected="CH" xpath="/areaTree/pageSequence[3]/@country"/>
+    <eval expected="de-CH" xpath="/areaTree/pageSequence[3]/@xml:lang"/>
     
-    <eval expected="de" xpath="/areaTree/pageSequence[4]/@language"/>
-    <true xpath="not(boolean(/areaTree/pageSequence[4]/@country))"/>
+    <eval expected="de" xpath="/areaTree/pageSequence[4]/@xml:lang"/>
   </checks>
   <if-checks xmlns:if="http://xmlgraphics.apache.org/fop/intermediate">
     <eval expected="en" xpath="//if:page-sequence[1]/@xml:lang"/>
diff --git a/test/pdf/accessibility/language.fo b/test/pdf/accessibility/language.fo
new file mode 100644 (file)
index 0000000..8dfb269
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" standalone="no"?>
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
+  xmlns:fox="http://xmlgraphics.apache.org/fop/extensions"
+  font-family="sans-serif">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="page"
+      page-height="170pt" page-width="220pt" margin="10pt">
+      <fo:region-body display-align="center"/>
+    </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" line-height="10pt" font-size="8pt" space-before="5pt" 
+      space-after="5pt">
+      <fo:block>This block of text is written in the default language of the page sequence, which is 
+        British English.</fo:block>
+      <fo:block language="fr" country="FR" space-before="inherit" space-after="inherit">Ce text est 
+        écrit dans une autre langue, en l’occurence le français de France.
+        <fo:block language="en" country="US" space-before="inherit" start-indent="1em" 
+          space-after="inherit">However, this block of French text encloses a block of American 
+          English.
+          <fo:block space-before="inherit" start-indent="2em" space-after="inherit" language="en" 
+            country="US">The structure element corresponding to this block should have no language 
+            set as it is the same as on the parent block.</fo:block></fo:block>
+        Maintenant on revient au français.</fo:block>
+      <fo:block space-before="inherit">And now we are back to the English language, with a 
+        <fo:character character="F" language="fr" country="none" color="blue"/>rench 
+        character.</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
index a9bb3df778058759fb011eff424d053dbd2a3386..38d9bc4997db94a662b1e068e788d9c4e2d16c49 100644 (file)
Binary files a/test/pdf/accessibility/pdf/complete.pdf and b/test/pdf/accessibility/pdf/complete.pdf differ
diff --git a/test/pdf/accessibility/pdf/language.pdf b/test/pdf/accessibility/pdf/language.pdf
new file mode 100644 (file)
index 0000000..ee4cd0b
Binary files /dev/null and b/test/pdf/accessibility/pdf/language.pdf differ
index 6e5da939341841abbfa8a4243a61b88a18e74b2a..1bd64e115bca1eb00949dcfca60194d4fe68a3bd 100644 (file)
Binary files a/test/pdf/accessibility/pdf/side-regions.pdf and b/test/pdf/accessibility/pdf/side-regions.pdf differ
index 65921fe5a63d28c01840bf82eba1c15b9b0fec65..603717d2ef3d32d7d5c2bf443c7be6a0aa52bc72 100644 (file)
Binary files a/test/pdf/accessibility/pdf/table_row-col-span.pdf and b/test/pdf/accessibility/pdf/table_row-col-span.pdf differ
index 0283764cd2ea4da1db1eed02f4fb74a4eb80b825..4411b302f6c738c2323357418b0ef380c6667ca6 100644 (file)
Binary files a/test/pdf/accessibility/pdf/text_2.pdf and b/test/pdf/accessibility/pdf/text_2.pdf differ
index 596ffb7db71bb323271bfa2f6f4f83fa2e0b9468..27159520b60fb7f3f831d274ab48da7a329c6c11 100644 (file)
Binary files a/test/pdf/accessibility/pdf/th_scope.pdf and b/test/pdf/accessibility/pdf/th_scope.pdf differ