git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1365162 13f79535-47bb-0310-9956-ffa450edef68tags/fop-2_0
@@ -221,14 +221,17 @@ class StructureTreeEventTrigger extends FOEventHandler { | |||
@Override | |||
public void startCell(TableCell tc) { | |||
AttributesImpl attributes = new AttributesImpl(); | |||
int colSpan = tc.getNumberColumnsSpanned(); | |||
if (colSpan > 1) { | |||
addNoNamespaceAttribute(attributes, "number-columns-spanned", | |||
Integer.toString(colSpan)); | |||
} | |||
addSpanAttribute(attributes, "number-columns-spanned", tc.getNumberColumnsSpanned()); | |||
addSpanAttribute(attributes, "number-rows-spanned", tc.getNumberRowsSpanned()); | |||
startElement(tc, attributes); | |||
} | |||
private void addSpanAttribute(AttributesImpl attributes, String attributeName, int span) { | |||
if (span > 1) { | |||
addNoNamespaceAttribute(attributes, attributeName, Integer.toString(span)); | |||
} | |||
} | |||
@Override | |||
public void endCell(TableCell tc) { | |||
endElement(tc); |
@@ -99,6 +99,15 @@ public class PDFArray extends PDFObject { | |||
this(null, elements); | |||
} | |||
/** | |||
* Creates an array object made of the given elements. | |||
* | |||
* @param elements the array content | |||
*/ | |||
public PDFArray(List<?> elements) { | |||
this(null, elements); | |||
} | |||
/** | |||
* Create the array object | |||
* @param parent the array's parent if any |
@@ -33,6 +33,8 @@ import org.apache.fop.util.LanguageTags; | |||
*/ | |||
public class PDFStructElem extends PDFDictionary implements StructureTreeElement, CompressedObject { | |||
private static final PDFName TABLE = new PDFName("Table"); | |||
private PDFStructElem parentElement; | |||
/** | |||
@@ -40,6 +42,8 @@ public class PDFStructElem extends PDFDictionary implements StructureTreeElement | |||
*/ | |||
protected List<PDFObject> kids; | |||
private List<PDFDictionary> attributes; | |||
/** | |||
* Creates a new structure element. | |||
* | |||
@@ -143,9 +147,21 @@ public class PDFStructElem extends PDFDictionary implements StructureTreeElement | |||
@Override | |||
protected void writeDictionary(OutputStream out, StringBuilder textBuffer) throws IOException { | |||
attachKids(); | |||
attachAttributes(); | |||
super.writeDictionary(out, textBuffer); | |||
} | |||
private void attachAttributes() { | |||
if (attributes != null) { | |||
if (attributes.size() == 1) { | |||
put("A", attributes.get(0)); | |||
} else { | |||
PDFArray array = new PDFArray(attributes); | |||
put("A", array); | |||
} | |||
} | |||
} | |||
/** | |||
* Attaches all valid kids to the kids array. | |||
* | |||
@@ -175,6 +191,24 @@ public class PDFStructElem extends PDFDictionary implements StructureTreeElement | |||
return kidsAttached; | |||
} | |||
public void setTableAttributeColSpan(int colSpan) { | |||
setTableAttributeRowColumnSpan("ColSpan", colSpan); | |||
} | |||
public void setTableAttributeRowSpan(int rowSpan) { | |||
setTableAttributeRowColumnSpan("RowSpan", rowSpan); | |||
} | |||
private void setTableAttributeRowColumnSpan(String typeSpan, int span) { | |||
PDFDictionary attribute = new PDFDictionary(); | |||
attribute.put("O", TABLE); | |||
attribute.put(typeSpan, span); | |||
if (attributes == null) { | |||
attributes = new ArrayList<PDFDictionary>(2); | |||
} | |||
attributes.add(attribute); | |||
} | |||
/** | |||
* Class representing a placeholder for a PDF Structure Element. | |||
*/ |
@@ -90,11 +90,23 @@ class PDFStructureTreeBuilder implements StructureTreeEventHandler { | |||
PDFStructElem parent = ancestors.getFirst(); | |||
String role = attributes.getValue("role"); | |||
PDFStructElem structElem = createStructureElement(name, parent, role); | |||
setSpanAttributes(structElem, attributes); | |||
parent.addKid(structElem); | |||
ancestors.addFirst(structElem); | |||
return structElem; | |||
} | |||
private void setSpanAttributes(PDFStructElem structElem, Attributes attributes) { | |||
String columnSpan = attributes.getValue("number-columns-spanned"); | |||
if (columnSpan != null) { | |||
structElem.setTableAttributeColSpan(Integer.parseInt(columnSpan)); | |||
} | |||
String rowSpan = attributes.getValue("number-rows-spanned"); | |||
if (rowSpan != null) { | |||
structElem.setTableAttributeRowSpan(Integer.parseInt(rowSpan)); | |||
} | |||
} | |||
public void endNode(String name) { | |||
removeFirstAncestor(); | |||
} |
@@ -62,6 +62,10 @@ | |||
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="53596"> | |||
When PDF accessibility is enabled, the structure tree must contain information about the | |||
number of columns or rows spanned by a table cell. | |||
</action> | |||
<action context="Renderers" dev="MH" type="add" fixes-bug="53563" importance="low"> | |||
Removed a method call to the java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice() | |||
that could (in a headless environment) throw a java.awt.HeadlessException |
@@ -0,0 +1,147 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> | |||
<fo:layout-master-set> | |||
<fo:simple-page-master master-name="page" page-height="320pt" page-width="420pt" margin="10pt"> | |||
<fo:region-body display-align="center"/> | |||
</fo:simple-page-master> | |||
</fo:layout-master-set> | |||
<fo:page-sequence master-reference="page"> | |||
<fo:flow flow-name="xsl-region-body"> | |||
<fo:table table-layout="fixed" width="100%" border-collapse="separate" | |||
border-separation="4pt"> | |||
<fo:table-body> | |||
<fo:table-row> | |||
<fo:table-cell number-columns-spanned="2" background-color="orange" padding-left="1pt"> | |||
<fo:block>Cells 1.1 and 1.2.</fo:block> | |||
</fo:table-cell> | |||
<fo:table-cell> | |||
<fo:block>Cell 1.3.</fo:block> | |||
</fo:table-cell> | |||
<fo:table-cell> | |||
<fo:block>Cell 1.4.</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row> | |||
<fo:table-cell> | |||
<fo:block>Cell 2.1.</fo:block> | |||
</fo:table-cell> | |||
<fo:table-cell number-columns-spanned="2" background-color="orange" padding-left="1pt"> | |||
<fo:block>Cells 2.2 and 2.3.</fo:block> | |||
</fo:table-cell> | |||
<fo:table-cell> | |||
<fo:block>Cell 2.4.</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row> | |||
<fo:table-cell> | |||
<fo:block>Cell 3.1.</fo:block> | |||
</fo:table-cell> | |||
<fo:table-cell> | |||
<fo:block>Cell 3.2.</fo:block> | |||
</fo:table-cell> | |||
<fo:table-cell number-columns-spanned="2" background-color="orange" padding-left="1pt"> | |||
<fo:block>Cells 3.3 and 3.4.</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row> | |||
<fo:table-cell number-columns-spanned="3" background-color="orange" padding-left="1pt"> | |||
<fo:block>Cells 4.1, 4.2 and 4.3.</fo:block> | |||
</fo:table-cell> | |||
<fo:table-cell> | |||
<fo:block>Cell 4.4.</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row> | |||
<fo:table-cell number-columns-spanned="4" background-color="orange" padding-left="1pt"> | |||
<fo:block>Cells 5.1, 5.2, 5.3 and 5.4.</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
</fo:table-body> | |||
</fo:table> | |||
<fo:table table-layout="fixed" width="100%" space-before="40pt" border-collapse="separate" | |||
border-separation="4pt"> | |||
<fo:table-body> | |||
<fo:table-row> | |||
<fo:table-cell number-rows-spanned="2" background-color="orange" padding-left="1pt"> | |||
<fo:block>Cells 1.1</fo:block> | |||
<fo:block>and 2.1.</fo:block> | |||
</fo:table-cell> | |||
<fo:table-cell> | |||
<fo:block>Cell 1.2.</fo:block> | |||
</fo:table-cell> | |||
<fo:table-cell> | |||
<fo:block>Cell 1.3.</fo:block> | |||
</fo:table-cell> | |||
<fo:table-cell number-rows-spanned="4" background-color="orange" padding-left="1pt"> | |||
<fo:block>Cells 1.4,</fo:block> | |||
<fo:block>2.4,</fo:block> | |||
<fo:block>3.4</fo:block> | |||
<fo:block>and 4.4.</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row> | |||
<fo:table-cell number-rows-spanned="2" background-color="orange" padding-left="1pt"> | |||
<fo:block>Cells 2.2</fo:block> | |||
<fo:block>and 3.2.</fo:block> | |||
</fo:table-cell> | |||
<fo:table-cell number-rows-spanned="3" background-color="orange" padding-left="1pt"> | |||
<fo:block>Cells 2.3,</fo:block> | |||
<fo:block>3.3</fo:block> | |||
<fo:block>and 4.3.</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row> | |||
<fo:table-cell> | |||
<fo:block>Cell 3.1.</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row> | |||
<fo:table-cell> | |||
<fo:block>Cell 4.1.</fo:block> | |||
</fo:table-cell> | |||
<fo:table-cell> | |||
<fo:block>Cell 4.2.</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
</fo:table-body> | |||
</fo:table> | |||
<fo:table table-layout="fixed" width="100%" space-before="40pt" border-collapse="separate" | |||
border-separation="4pt"> | |||
<fo:table-body> | |||
<fo:table-row> | |||
<fo:table-cell number-rows-spanned="2" number-columns-spanned="3" | |||
background-color="orange" padding-left="1pt"> | |||
<fo:block>Cells 1.1, 1.2, 1.3</fo:block> | |||
<fo:block>and 2.1, 2.2, 2.3.</fo:block> | |||
</fo:table-cell> | |||
<fo:table-cell> | |||
<fo:block>Cell 1.4.</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row> | |||
<fo:table-cell> | |||
<fo:block>Cell 2.4.</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row> | |||
<fo:table-cell> | |||
<fo:block>Cell 3.1.</fo:block> | |||
</fo:table-cell> | |||
<fo:table-cell> | |||
<fo:block>Cell 3.2.</fo:block> | |||
</fo:table-cell> | |||
<fo:table-cell> | |||
<fo:block>Cell 3.3.</fo:block> | |||
</fo:table-cell> | |||
<fo:table-cell> | |||
<fo:block>Cell 3.4.</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
</fo:table-body> | |||
</fo:table> | |||
</fo:flow> | |||
</fo:page-sequence> | |||
</fo:root> |