From 9e1c3f381c661eff5ebb45f3d442b0dc871dd865 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Tue, 29 May 2012 09:48:03 +0000 Subject: [PATCH] Added possibility to treat some content as artifact. If any fo:static-content or fo:wrapper element has their 'role' property set to 'artifact', then they and their descendants will be treated as artifacts. Suggested by Martin Koegler as part of Bugzilla #50852 git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1343632 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/accessibility/Accessibility.java | 6 ++ .../fo/FO2StructureTreeConverter.java | 25 +++++ src/java/org/apache/fop/fo/flow/Wrapper.java | 19 +++- .../fo/FO2StructureTreeConverterTestCase.java | 15 ++- .../apache/fop/accessibility/fo/artifact.fo | 97 ++++++++++++++++++ .../fop/accessibility/fo/fo2StructureTree.xsl | 2 + test/pdf/accessibility/pdf/role.pdf | Bin 19023 -> 18600 bytes test/pdf/accessibility/role.fo | 4 +- 8 files changed, 161 insertions(+), 7 deletions(-) create mode 100644 test/java/org/apache/fop/accessibility/fo/artifact.fo diff --git a/src/java/org/apache/fop/accessibility/Accessibility.java b/src/java/org/apache/fop/accessibility/Accessibility.java index c842cf43f..88ec6dbdd 100644 --- a/src/java/org/apache/fop/accessibility/Accessibility.java +++ b/src/java/org/apache/fop/accessibility/Accessibility.java @@ -28,6 +28,12 @@ public final class Accessibility { /** Constant string for the rendering options key to enable accessibility features. */ public static final String ACCESSIBILITY = "accessibility"; + /** + * The value to be set on the 'role' property for the element and its descendants to + * be considered as artifacts. + */ + public static final String ROLE_ARTIFACT = "artifact"; + private Accessibility() { } } diff --git a/src/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java b/src/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java index 47c227e9a..27469d6e0 100644 --- a/src/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java +++ b/src/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java @@ -23,6 +23,7 @@ import java.util.Stack; import org.xml.sax.SAXException; +import org.apache.fop.accessibility.Accessibility; import org.apache.fop.accessibility.StructureTreeEventHandler; import org.apache.fop.fo.DelegatingFOEventHandler; import org.apache.fop.fo.FOEventHandler; @@ -57,6 +58,8 @@ import org.apache.fop.fo.pagination.Flow; 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.CommonAccessibility; +import org.apache.fop.fo.properties.CommonAccessibilityHolder; /** * Allows to create the structure tree of an FO document, by converting FO @@ -355,6 +358,7 @@ public class FO2StructureTreeConverter extends DelegatingFOEventHandler { @Override public void startStatic(StaticContent staticContent) { + handleStartArtifact(staticContent); converter.startStatic(staticContent); super.startStatic(staticContent); } @@ -362,6 +366,7 @@ public class FO2StructureTreeConverter extends DelegatingFOEventHandler { @Override public void endStatic(StaticContent statisContent) { converter.endStatic(statisContent); + handleEndArtifact(statisContent); super.endStatic(statisContent); } @@ -454,6 +459,7 @@ public class FO2StructureTreeConverter extends DelegatingFOEventHandler { @Override public void startWrapper(Wrapper wrapper) { + handleStartArtifact(wrapper); converter.startWrapper(wrapper); super.startWrapper(wrapper); } @@ -461,6 +467,7 @@ public class FO2StructureTreeConverter extends DelegatingFOEventHandler { @Override public void endWrapper(Wrapper wrapper) { converter.endWrapper(wrapper); + handleEndArtifact(wrapper); super.endWrapper(wrapper); } @@ -488,4 +495,22 @@ public class FO2StructureTreeConverter extends DelegatingFOEventHandler { super.endExternalDocument(document); } + private void handleStartArtifact(CommonAccessibilityHolder fobj) { + if (isArtifact(fobj)) { + converters.push(converter); + converter = eventSwallower; + } + } + + private void handleEndArtifact(CommonAccessibilityHolder fobj) { + if (isArtifact(fobj)) { + converter = converters.pop(); + } + } + + private boolean isArtifact(CommonAccessibilityHolder fobj) { + CommonAccessibility accessibility = fobj.getCommonAccessibility(); + return Accessibility.ROLE_ARTIFACT.equalsIgnoreCase(accessibility.getRole()); + } + } diff --git a/src/java/org/apache/fop/fo/flow/Wrapper.java b/src/java/org/apache/fop/fo/flow/Wrapper.java index 1302e3134..0aec7ce16 100644 --- a/src/java/org/apache/fop/fo/flow/Wrapper.java +++ b/src/java/org/apache/fop/fo/flow/Wrapper.java @@ -26,7 +26,10 @@ import org.apache.fop.fo.Constants; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FOText; import org.apache.fop.fo.FObjMixed; +import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; +import org.apache.fop.fo.properties.CommonAccessibility; +import org.apache.fop.fo.properties.CommonAccessibilityHolder; /** * Class modelling the @@ -34,13 +37,13 @@ import org.apache.fop.fo.ValidationException; * The fo:wrapper object serves as a property holder for * its child node objects. */ -public class Wrapper extends FObjMixed { - // The value of properties relevant for fo:wrapper. - // End of property values +public class Wrapper extends FObjMixed implements CommonAccessibilityHolder { // used for FO validation private boolean blockOrInlineItemFound = false; + private CommonAccessibility commonAccessibility; + /** * Create a Wrapper instance that is a child of the * given {@link FONode} @@ -51,6 +54,12 @@ public class Wrapper extends FObjMixed { super(parent); } + @Override + public void bind(PropertyList pList) throws FOPException { + super.bind(pList); + commonAccessibility = CommonAccessibility.getInstance(pList); + } + @Override protected void startOfNode() throws FOPException { super.startOfNode(); @@ -136,6 +145,10 @@ public class Wrapper extends FObjMixed { return FO_WRAPPER; } + public CommonAccessibility getCommonAccessibility() { + return commonAccessibility; + } + @Override public boolean isDelimitedTextRangeBoundary ( int boundary ) { return false; diff --git a/test/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverterTestCase.java b/test/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverterTestCase.java index 9c53bdde3..863bfe797 100644 --- a/test/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverterTestCase.java +++ b/test/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverterTestCase.java @@ -19,8 +19,6 @@ package org.apache.fop.accessibility.fo; -import static org.junit.Assert.assertTrue; - import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -45,6 +43,8 @@ import org.w3c.dom.Document; import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; +import static org.junit.Assert.assertTrue; + import org.apache.fop.accessibility.StructureTree2SAXEventAdapter; import org.apache.fop.accessibility.StructureTreeEventHandler; import org.apache.fop.apps.FOPException; @@ -102,6 +102,17 @@ public class FO2StructureTreeConverterTestCase { testConverter(); } + @Test + public void testArtifact() throws Exception { + foLoader = new FOLoader() { + + public InputStream getFoInputStream() { + return getResource("artifact.fo"); + } + }; + testConverter(); + } + private Transformer createTransformer(Source xslt) throws TransformerFactoryConfigurationError, TransformerConfigurationException { TransformerFactory transformerFactory = TransformerFactory.newInstance(); diff --git a/test/java/org/apache/fop/accessibility/fo/artifact.fo b/test/java/org/apache/fop/accessibility/fo/artifact.fo new file mode 100644 index 000000000..c3d5fadf3 --- /dev/null +++ b/test/java/org/apache/fop/accessibility/fo/artifact.fo @@ -0,0 +1,97 @@ + + + + + + + + + + + + This piece of text is normal content that should be read out loud by a screen + reader. + + The following content will be treated as artifact: + + + + + A block as artifact. + + + + + Header 1.1 + Header 1.2 + + + Footer 1.1 + Footer 1.2 + + + + Cell 1.1 + Cell 1.2 + + + Cell 2.1 + Cell 2.2 + + + + + + + • + + + Item 1. + + + + + • + + + Item 2. + + + + + • + + + Item 3. + + + + + A block in a nested wrapper. + + + A block in a nested artifact wrapper. + + + Inside a nested wrapper. + An artifact wrapper inside the nested wrapper. + Inside a wrapper inside the artifact wrapper that is inside + the nested wrapper. Outside the wrapper inside the artifact + wrapper that is inside the nested wrapper. + Outside the artifact wrapper. + + + + + + Now we are back to normal content that is part of the logical + structure, should appear in the structure tree and should be read out loud by the screen + reader. + + + + + diff --git a/test/java/org/apache/fop/accessibility/fo/fo2StructureTree.xsl b/test/java/org/apache/fop/accessibility/fo/fo2StructureTree.xsl index ce326f3b1..db0dffb14 100644 --- a/test/java/org/apache/fop/accessibility/fo/fo2StructureTree.xsl +++ b/test/java/org/apache/fop/accessibility/fo/fo2StructureTree.xsl @@ -105,6 +105,8 @@ + + diff --git a/test/pdf/accessibility/pdf/role.pdf b/test/pdf/accessibility/pdf/role.pdf index 38fcf1bde3c847f0480323f16f90b38d310ddc0d..4dfb686c9f962f298f1b1611ca221d67eb0a300d 100644 GIT binary patch delta 3098 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 F{tNzI3>g3b diff --git a/test/pdf/accessibility/role.fo b/test/pdf/accessibility/role.fo index 885638592..b94c6ab67 100644 --- a/test/pdf/accessibility/role.fo +++ b/test/pdf/accessibility/role.fo @@ -24,8 +24,8 @@ - - + +