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-ffa450edef68pull/26/head
@@ -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() { } | |||
} |
@@ -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()); | |||
} | |||
} |
@@ -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 <a href=http://www.w3.org/TR/xsl/#fo_wrapper"> | |||
@@ -34,13 +37,13 @@ import org.apache.fop.fo.ValidationException; | |||
* The <code>fo:wrapper</code> 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; |
@@ -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(); |
@@ -0,0 +1,97 @@ | |||
<?xml version="1.0" standalone="no"?> | |||
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> | |||
<fo:layout-master-set> | |||
<fo:simple-page-master master-name="page" | |||
page-height="500pt" page-width="300pt" margin="20pt"> | |||
<fo:region-body/> | |||
</fo:simple-page-master> | |||
</fo:layout-master-set> | |||
<fo:page-sequence master-reference="page"> | |||
<fo:flow flow-name="xsl-region-body" text-align="justify"> | |||
<fo:block>This piece of text is normal content that should be read out loud by a screen | |||
reader.</fo:block> | |||
<fo:block space-before="10pt">The following content will be treated as artifact:</fo:block> | |||
<fo:wrapper role="artifact"> | |||
<fo:block-container border="1pt solid black" padding="5pt" background-color="#F0F0F0" | |||
space-before="10pt" start-indent="6pt" end-indent="6pt" color="#606060"> | |||
<fo:block start-indent="0" end-indent="0"> | |||
<fo:block>A block as artifact.</fo:block> | |||
<fo:table space-before="5pt" width="100%" table-layout="fixed"> | |||
<fo:table-column column-width="proportional-column-width(1)"/> | |||
<fo:table-column column-width="proportional-column-width(2)"/> | |||
<fo:table-header> | |||
<fo:table-cell border="1pt solid #606060"><fo:block>Header 1.1</fo:block></fo:table-cell> | |||
<fo:table-cell border="1pt solid #606060"><fo:block>Header 1.2</fo:block></fo:table-cell> | |||
</fo:table-header> | |||
<fo:table-footer> | |||
<fo:table-cell border="1pt solid #606060"><fo:block>Footer 1.1</fo:block></fo:table-cell> | |||
<fo:table-cell border="1pt solid #606060"><fo:block>Footer 1.2</fo:block></fo:table-cell> | |||
</fo:table-footer> | |||
<fo:table-body> | |||
<fo:table-row> | |||
<fo:table-cell border="1pt solid #606060"><fo:block>Cell 1.1</fo:block></fo:table-cell> | |||
<fo:table-cell border="1pt solid #606060"><fo:block>Cell 1.2</fo:block></fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row> | |||
<fo:table-cell border="1pt solid #606060"><fo:block>Cell 2.1</fo:block></fo:table-cell> | |||
<fo:table-cell border="1pt solid #606060"><fo:block>Cell 2.2</fo:block></fo:table-cell> | |||
</fo:table-row> | |||
</fo:table-body> | |||
</fo:table> | |||
<fo:list-block space-before="7pt" provisional-distance-between-starts="8pt" | |||
provisional-label-separation="5pt"> | |||
<fo:list-item> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block>•</fo:block> | |||
</fo:list-item-label> | |||
<fo:list-item-body start-indent="body-start()"> | |||
<fo:block>Item 1.</fo:block> | |||
</fo:list-item-body> | |||
</fo:list-item> | |||
<fo:list-item> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block>•</fo:block> | |||
</fo:list-item-label> | |||
<fo:list-item-body start-indent="body-start()"> | |||
<fo:block>Item 2.</fo:block> | |||
</fo:list-item-body> | |||
</fo:list-item> | |||
<fo:list-item> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block>•</fo:block> | |||
</fo:list-item-label> | |||
<fo:list-item-body start-indent="body-start()"> | |||
<fo:block>Item 3.</fo:block> | |||
</fo:list-item-body> | |||
</fo:list-item> | |||
</fo:list-block> | |||
<fo:wrapper> | |||
<fo:block>A block in a nested wrapper.</fo:block> | |||
</fo:wrapper> | |||
<fo:wrapper role="artifact"> | |||
<fo:block>A block in a nested artifact wrapper.</fo:block> | |||
</fo:wrapper> | |||
<fo:wrapper> | |||
<fo:block>Inside a nested wrapper. | |||
<fo:wrapper role="artifact">An artifact wrapper inside the nested wrapper. | |||
<fo:inline><fo:wrapper>Inside a wrapper inside the artifact wrapper that is inside | |||
the nested wrapper.</fo:wrapper> Outside the wrapper inside the artifact | |||
wrapper that is inside the nested wrapper.</fo:inline> | |||
</fo:wrapper> Outside the artifact wrapper.</fo:block> | |||
</fo:wrapper> | |||
</fo:block> | |||
</fo:block-container> | |||
</fo:wrapper> | |||
<fo:block space-before="10pt">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.</fo:block> | |||
</fo:flow> | |||
</fo:page-sequence> | |||
</fo:root> |
@@ -105,6 +105,8 @@ | |||
<xsl:call-template name="copy"/> | |||
</xsl:template> | |||
<xsl:template match="fo:wrapper[translate(normalize-space(@role), 'ARTIFCT', 'artifct') = 'artifact']"/> | |||
<!-- Discard descendants of fo:leader --> | |||
<xsl:template match="fo:leader"/> |
@@ -24,8 +24,8 @@ | |||
<fo:region-after extent="10pt"/> | |||
</fo:simple-page-master> | |||
</fo:layout-master-set> | |||
<fo:page-sequence master-reference="page" role="Art"> | |||
<fo:static-content flow-name="xsl-region-after" role="NonStruct" font-size="8pt"> | |||
<fo:page-sequence master-reference="page" language="en" country="GB" role="Art"> | |||
<fo:static-content flow-name="xsl-region-after" role="artifact" font-size="8pt"> | |||
<fo:block text-align="center"><fo:page-number/></fo:block> | |||
</fo:static-content> | |||
<fo:flow flow-name="xsl-region-body" role="NonStruct" hyphenate="true" |