git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1368420 13f79535-47bb-0310-9956-ffa450edef68tags/fop-2_0
@@ -37,6 +37,7 @@ import java.util.Map; | |||
import org.apache.commons.logging.Log; | |||
import org.apache.commons.logging.LogFactory; | |||
import org.apache.fop.pdf.StandardStructureAttributes.Table.Scope; | |||
import org.apache.fop.pdf.xref.CrossReferenceStream; | |||
import org.apache.fop.pdf.xref.CrossReferenceTable; | |||
import org.apache.fop.pdf.xref.TrailerDictionary; | |||
@@ -362,13 +363,30 @@ public class PDFDocument { | |||
* hierarchy | |||
* @return a dictionary of type StructElem | |||
*/ | |||
public PDFStructElem makeStructureElement(PDFName structureType, PDFObject parent) { | |||
public PDFStructElem makeStructureElement(StructureType structureType, PDFObject parent) { | |||
PDFStructElem structElem = new PDFStructElem(parent, structureType); | |||
assignObjectNumber(structElem); | |||
structureTreeElements.add(structElem); | |||
return structElem; | |||
} | |||
/** | |||
* Creates and returns a structure element. | |||
* | |||
* @param structureType the structure type of the new element (value for the | |||
* S entry) | |||
* @param parent the parent of the new structure element in the structure | |||
* hierarchy | |||
* @param scope the scope of the given table header element | |||
* @return a dictionary of type StructElem | |||
*/ | |||
public PDFStructElem makeStructureElement(StructureType structureType, PDFObject parent, | |||
Scope scope) { | |||
PDFStructElem structElem = makeStructureElement(structureType, parent); | |||
versionController.addTableHeaderScopeAttribute(structElem, scope); | |||
return structElem; | |||
} | |||
/** | |||
* Get the {@link PDFInfo} object for this document. | |||
* |
@@ -26,6 +26,7 @@ import java.util.List; | |||
import java.util.Locale; | |||
import org.apache.fop.accessibility.StructureTreeElement; | |||
import org.apache.fop.pdf.StandardStructureAttributes.Table; | |||
import org.apache.fop.util.LanguageTags; | |||
/** | |||
@@ -33,7 +34,7 @@ import org.apache.fop.util.LanguageTags; | |||
*/ | |||
public class PDFStructElem extends PDFDictionary implements StructureTreeElement, CompressedObject { | |||
private static final PDFName TABLE = new PDFName("Table"); | |||
private StructureType structureType; | |||
private PDFStructElem parentElement; | |||
@@ -50,12 +51,17 @@ public class PDFStructElem extends PDFDictionary implements StructureTreeElement | |||
* @param parent parent of this element | |||
* @param structureType the structure type of this element | |||
*/ | |||
PDFStructElem(PDFObject parent, PDFName structureType) { | |||
PDFStructElem(PDFObject parent, StructureType structureType) { | |||
this(parent); | |||
this.structureType = structureType; | |||
put("S", structureType.getName()); | |||
setParent(parent); | |||
} | |||
private PDFStructElem(PDFObject parent) { | |||
if (parent instanceof PDFStructElem) { | |||
parentElement = (PDFStructElem) parent; | |||
} | |||
put("S", structureType); | |||
setParent(parent); | |||
} | |||
/** | |||
@@ -113,8 +119,8 @@ public class PDFStructElem extends PDFDictionary implements StructureTreeElement | |||
* | |||
* @return the value of the S entry | |||
*/ | |||
public PDFName getStructureType() { | |||
return (PDFName) get("S"); | |||
public StructureType getStructureType() { | |||
return structureType; | |||
} | |||
/** | |||
@@ -201,7 +207,7 @@ public class PDFStructElem extends PDFDictionary implements StructureTreeElement | |||
private void setTableAttributeRowColumnSpan(String typeSpan, int span) { | |||
PDFDictionary attribute = new PDFDictionary(); | |||
attribute.put("O", TABLE); | |||
attribute.put("O", Table.NAME); | |||
attribute.put(typeSpan, span); | |||
if (attributes == null) { | |||
attributes = new ArrayList<PDFDictionary>(2); | |||
@@ -228,13 +234,8 @@ public class PDFStructElem extends PDFDictionary implements StructureTreeElement | |||
} | |||
} | |||
/** | |||
* Constructor | |||
* @param parent - | |||
* @param name - | |||
*/ | |||
public Placeholder(PDFObject parent, String name) { | |||
super(parent, new PDFName(name)); | |||
public Placeholder(PDFObject parent) { | |||
super(parent); | |||
} | |||
} | |||
@@ -0,0 +1,69 @@ | |||
/* | |||
* 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.pdf; | |||
/** | |||
* Standard attributes, as defined in section 10.7.5 of the PDF Reference, Fourth edition (PDF 1.5). | |||
*/ | |||
public final class StandardStructureAttributes { | |||
public static final class Table { | |||
/** | |||
* The name to use as an attribute owner. This is the value of the 'O' entry in | |||
* the attribute's dictionary. | |||
*/ | |||
public static final PDFName NAME = new PDFName("Table"); | |||
public static enum Scope { | |||
ROW("Row"), | |||
COLUMN("Column"), | |||
BOTH("Both"); | |||
private final PDFName name; | |||
private Scope(String name) { | |||
this.name = new PDFName(name); | |||
} | |||
/** | |||
* Returns the name of this attribute. | |||
* | |||
* @return a name suitable for use as a value in the attribute's dictionary | |||
*/ | |||
public PDFName getName() { | |||
return name; | |||
} | |||
/** | |||
* Sets the given scope on the given table header element. | |||
*/ | |||
static void addScopeAttribute(PDFStructElem th, Scope scope) { | |||
PDFDictionary scopeAttribute = new PDFDictionary(); | |||
scopeAttribute.put("O", Table.NAME); | |||
scopeAttribute.put("Scope", scope.getName()); | |||
th.put("A", scopeAttribute); | |||
} | |||
} | |||
} | |||
private StandardStructureAttributes() { } | |||
} |
@@ -0,0 +1,132 @@ | |||
/* | |||
* 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.pdf; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
/** | |||
* Standard structure types, as defined in section 10.7.4 of the PDF Reference, Fourth Edition (PDF 1.5). | |||
*/ | |||
public final class StandardStructureTypes { | |||
public static final class Grouping { | |||
public static final StructureType DOCUMENT = new StructureTypeImpl("Document"); | |||
public static final StructureType PART = new StructureTypeImpl("Part"); | |||
public static final StructureType ART = new StructureTypeImpl("Art"); | |||
public static final StructureType SECT = new StructureTypeImpl("Sect"); | |||
public static final StructureType DIV = new StructureTypeImpl("Div"); | |||
public static final StructureType BLOCK_QUOTE = new StructureTypeImpl("BlockQuote"); | |||
public static final StructureType CAPTION = new StructureTypeImpl("Caption"); | |||
public static final StructureType TOC = new StructureTypeImpl("TOC"); | |||
public static final StructureType TOCI = new StructureTypeImpl("TOCI"); | |||
public static final StructureType INDEX = new StructureTypeImpl("Index"); | |||
public static final StructureType NON_STRUCT = new StructureTypeImpl("NonStruct"); | |||
public static final StructureType PRIVATE = new StructureTypeImpl("Private"); | |||
} | |||
public static final class Paragraphlike { | |||
public static final StructureType H = new StructureTypeImpl("H"); | |||
public static final StructureType H1 = new StructureTypeImpl("H1"); | |||
public static final StructureType H2 = new StructureTypeImpl("H2"); | |||
public static final StructureType H3 = new StructureTypeImpl("H3"); | |||
public static final StructureType H4 = new StructureTypeImpl("H4"); | |||
public static final StructureType H5 = new StructureTypeImpl("H5"); | |||
public static final StructureType H6 = new StructureTypeImpl("H6"); | |||
public static final StructureType P = new StructureTypeImpl("P"); | |||
} | |||
public static final class List { | |||
public static final StructureType L = new StructureTypeImpl("L"); | |||
public static final StructureType LI = new StructureTypeImpl("LI"); | |||
public static final StructureType LBL = new StructureTypeImpl("Lbl"); | |||
public static final StructureType LBODY = new StructureTypeImpl("LBody"); | |||
} | |||
public static final class Table { | |||
public static final StructureType TABLE = new StructureTypeImpl("Table"); | |||
public static final StructureType TR = new StructureTypeImpl("TR"); | |||
public static final StructureType TH = new StructureTypeImpl("TH"); | |||
public static final StructureType TD = new StructureTypeImpl("TD"); | |||
public static final StructureType THEAD = new StructureTypeImpl("THead"); | |||
public static final StructureType TBODY = new StructureTypeImpl("TBody"); | |||
public static final StructureType TFOOT = new StructureTypeImpl("TFoot"); | |||
} | |||
public static final class InlineLevelStructure { | |||
public static final StructureType SPAN = new StructureTypeImpl("Span"); | |||
public static final StructureType QUOTE = new StructureTypeImpl("Quote"); | |||
public static final StructureType NOTE = new StructureTypeImpl("Note"); | |||
public static final StructureType REFERENCE = new StructureTypeImpl("Reference"); | |||
public static final StructureType BIB_ENTRY = new StructureTypeImpl("BibEntry"); | |||
public static final StructureType CODE = new StructureTypeImpl("Code"); | |||
public static final StructureType LINK = new StructureTypeImpl("Link"); | |||
public static final StructureType ANNOT = new StructureTypeImpl("Annot"); | |||
} | |||
public static final class RubyOrWarichu { | |||
public static final StructureType RUBY = new StructureTypeImpl("Ruby"); | |||
public static final StructureType RB = new StructureTypeImpl("RB"); | |||
public static final StructureType RT = new StructureTypeImpl("RT"); | |||
public static final StructureType RP = new StructureTypeImpl("RP"); | |||
public static final StructureType WARICHU = new StructureTypeImpl("Warichu"); | |||
public static final StructureType WT = new StructureTypeImpl("WT"); | |||
public static final StructureType WP = new StructureTypeImpl("WP"); | |||
} | |||
public static final class Illustration { | |||
public static final StructureType FIGURE = new StructureTypeImpl("Figure"); | |||
public static final StructureType FORMULA = new StructureTypeImpl("Formula"); | |||
public static final StructureType FORM = new StructureTypeImpl("Form"); | |||
} | |||
private static class StructureTypeImpl implements StructureType { | |||
private final PDFName name; | |||
protected StructureTypeImpl(String name) { | |||
this.name = new PDFName(name); | |||
StandardStructureTypes.STRUCTURE_TYPES.put(name, this); | |||
} | |||
public PDFName getName() { | |||
return name; | |||
} | |||
} | |||
private static final Map<String, StructureType> STRUCTURE_TYPES = new HashMap<String, StructureType>(); | |||
private StandardStructureTypes() { } | |||
/** | |||
* Returns the standard structure type of the given name. | |||
* | |||
* @param name the name of a structure type, case sensitive. For example, Document, | |||
* Sect, H1, etc. | |||
* @return the corresponding {@code StructureType} instance, or {@code null} if the given | |||
* name does not correspond to a standard structure type | |||
*/ | |||
public static StructureType get(String name) { | |||
return STRUCTURE_TYPES.get(name); | |||
} | |||
} |
@@ -0,0 +1,34 @@ | |||
/* | |||
* 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.pdf; | |||
/** | |||
* A structure type, as defined in Section 10.6.2 of the PDF Reference, fourth edition (PDF 1.5). | |||
*/ | |||
public interface StructureType { | |||
/** | |||
* Returns the name of this structure type. | |||
* | |||
* @return the name object identifying this structure type | |||
*/ | |||
PDFName getName(); | |||
} |
@@ -19,6 +19,8 @@ | |||
package org.apache.fop.pdf; | |||
import org.apache.fop.pdf.StandardStructureAttributes.Table.Scope; | |||
/** | |||
* An abstraction that controls the mutability of the PDF version for a document. | |||
*/ | |||
@@ -47,6 +49,8 @@ public abstract class VersionController { | |||
*/ | |||
public abstract void setPDFVersion(Version version); | |||
abstract void addTableHeaderScopeAttribute(PDFStructElem th, Scope scope); | |||
@Override | |||
public String toString() { | |||
return version.toString(); | |||
@@ -67,6 +71,13 @@ public abstract class VersionController { | |||
public void setPDFVersion(Version version) { | |||
throw new IllegalStateException("Cannot change the version of this PDF document."); | |||
} | |||
@Override | |||
void addTableHeaderScopeAttribute(PDFStructElem th, Scope scope) { | |||
if (super.version.compareTo(Version.V1_4) > 0) { | |||
Scope.addScopeAttribute(th, scope); | |||
} | |||
} | |||
} | |||
/** | |||
@@ -91,6 +102,12 @@ public abstract class VersionController { | |||
doc.getRoot().setVersion(version); | |||
} | |||
} | |||
@Override | |||
void addTableHeaderScopeAttribute(PDFStructElem th, Scope scope) { | |||
setPDFVersion(Version.V1_5); | |||
Scope.addScopeAttribute(th, scope); | |||
} | |||
} | |||
/** |
@@ -19,145 +19,66 @@ | |||
package org.apache.fop.render.pdf; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
import org.apache.fop.events.EventBroadcaster; | |||
import org.apache.fop.pdf.PDFName; | |||
import org.apache.fop.pdf.PDFObject; | |||
import org.apache.fop.pdf.PDFStructElem; | |||
import org.apache.fop.pdf.StandardStructureTypes; | |||
import org.apache.fop.pdf.StructureType; | |||
/** | |||
* This class provides the standard mappings from Formatting Objects to PDF structure types. | |||
*/ | |||
final class FOToPDFRoleMap { | |||
/** | |||
* Standard structure types defined by the PDF Reference, Fourth Edition (PDF 1.5). | |||
*/ | |||
private static final Map<String, PDFName> STANDARD_STRUCTURE_TYPES | |||
= new HashMap<String, PDFName>(); | |||
private static final Map<String, Mapper> DEFAULT_MAPPINGS | |||
= new java.util.HashMap<String, Mapper>(); | |||
private static final PDFName THEAD; | |||
private static final PDFName NON_STRUCT; | |||
private static final Map<String, Mapper> DEFAULT_MAPPINGS = new java.util.HashMap<String, Mapper>(); | |||
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 = STANDARD_STRUCTURE_TYPES.get("NonStruct"); | |||
assert NON_STRUCT != null; | |||
THEAD = 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"); | |||
addMapping("root", StandardStructureTypes.Grouping.DOCUMENT); | |||
addMapping("page-sequence", StandardStructureTypes.Grouping.PART); | |||
addMapping("flow", StandardStructureTypes.Grouping.SECT); | |||
addMapping("static-content", StandardStructureTypes.Grouping.SECT); | |||
// Block-level Formatting Objects | |||
addMapping("block", "P"); | |||
addMapping("block-container", "Div"); | |||
addMapping("block", StandardStructureTypes.Paragraphlike.P); | |||
addMapping("block-container", StandardStructureTypes.Grouping.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"); | |||
addMapping("character", StandardStructureTypes.InlineLevelStructure.SPAN); | |||
addMapping("external-graphic", StandardStructureTypes.Illustration.FIGURE); | |||
addMapping("instream-foreign-object", StandardStructureTypes.Illustration.FIGURE); | |||
addMapping("inline", StandardStructureTypes.InlineLevelStructure.SPAN); | |||
addMapping("inline-container", StandardStructureTypes.Grouping.DIV); | |||
addMapping("page-number", StandardStructureTypes.InlineLevelStructure.QUOTE); | |||
addMapping("page-number-citation", StandardStructureTypes.InlineLevelStructure.QUOTE); | |||
addMapping("page-number-citation-last", StandardStructureTypes.InlineLevelStructure.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-row", "TR"); | |||
addMapping("table-and-caption", StandardStructureTypes.Grouping.DIV); | |||
addMapping("table", StandardStructureTypes.Table.TABLE); | |||
addMapping("table-caption", StandardStructureTypes.Grouping.CAPTION); | |||
addMapping("table-header", StandardStructureTypes.Table.THEAD); | |||
addMapping("table-footer", StandardStructureTypes.Table.TFOOT); | |||
addMapping("table-body", StandardStructureTypes.Table.TBODY); | |||
addMapping("table-row", StandardStructureTypes.Table.TR); | |||
addMapping("table-cell", new TableCellMapper()); | |||
// Formatting Objects for Lists | |||
addMapping("list-block", "L"); | |||
addMapping("list-item", "LI"); | |||
addMapping("list-item-body", "LBody"); | |||
addMapping("list-item-label", "Lbl"); | |||
addMapping("list-block", StandardStructureTypes.List.L); | |||
addMapping("list-item", StandardStructureTypes.List.LI); | |||
addMapping("list-item-body", StandardStructureTypes.List.LBODY); | |||
addMapping("list-item-label", StandardStructureTypes.List.LBL); | |||
// Dynamic Effects: Link and Multi Formatting Objects | |||
addMapping("basic-link", "Link"); | |||
addMapping("basic-link", StandardStructureTypes.InlineLevelStructure.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 addStructureType(String structureType) { | |||
STANDARD_STRUCTURE_TYPES.put(structureType, new PDFName(structureType)); | |||
addMapping("float", StandardStructureTypes.Grouping.DIV); | |||
addMapping("footnote", StandardStructureTypes.InlineLevelStructure.NOTE); | |||
addMapping("footnote-body", StandardStructureTypes.Grouping.SECT); | |||
addMapping("wrapper", StandardStructureTypes.InlineLevelStructure.SPAN); | |||
addMapping("marker", StandardStructureTypes.Grouping.PRIVATE); | |||
} | |||
private static void addMapping(String fo, String structureType) { | |||
PDFName type = STANDARD_STRUCTURE_TYPES.get(structureType); | |||
assert type != null; | |||
addMapping(fo, new SimpleMapper(type)); | |||
private static void addMapping(String fo, StructureType structureType) { | |||
addMapping(fo, new SimpleMapper(structureType)); | |||
} | |||
private static void addMapping(String fo, Mapper mapper) { | |||
@@ -173,13 +94,13 @@ final class FOToPDFRoleMap { | |||
* @param eventBroadcaster the event broadcaster | |||
* @return the structure type or null if no match could be found | |||
*/ | |||
public static PDFName mapFormattingObject(String fo, String role, | |||
public static StructureType mapFormattingObject(String fo, String role, | |||
PDFObject parent, EventBroadcaster eventBroadcaster) { | |||
PDFName type = null; | |||
StructureType type = null; | |||
if (role == null) { | |||
type = getDefaultMappingFor(fo, parent); | |||
} else { | |||
type = STANDARD_STRUCTURE_TYPES.get(role); | |||
type = StandardStructureTypes.get(role); | |||
if (type == null) { | |||
type = getDefaultMappingFor(fo, parent); | |||
PDFEventProducer.Provider.get(eventBroadcaster).nonStandardStructureType(fo, | |||
@@ -196,28 +117,28 @@ final class FOToPDFRoleMap { | |||
* @param parent the parent of the structure element to be mapped | |||
* @return the structure type or NonStruct if no match could be found | |||
*/ | |||
private static PDFName getDefaultMappingFor(String fo, PDFObject parent) { | |||
private static StructureType getDefaultMappingFor(String fo, PDFObject parent) { | |||
Mapper mapper = DEFAULT_MAPPINGS.get(fo); | |||
if (mapper != null) { | |||
return mapper.getStructureType(parent); | |||
} else { | |||
return NON_STRUCT; | |||
return StandardStructureTypes.Grouping.NON_STRUCT; | |||
} | |||
} | |||
private interface Mapper { | |||
PDFName getStructureType(PDFObject parent); | |||
StructureType getStructureType(PDFObject parent); | |||
} | |||
private static class SimpleMapper implements Mapper { | |||
private PDFName structureType; | |||
private StructureType structureType; | |||
public SimpleMapper(PDFName structureType) { | |||
public SimpleMapper(StructureType structureType) { | |||
this.structureType = structureType; | |||
} | |||
public PDFName getStructureType(PDFObject parent) { | |||
public StructureType getStructureType(PDFObject parent) { | |||
return structureType; | |||
} | |||
@@ -225,17 +146,14 @@ final class FOToPDFRoleMap { | |||
private static class TableCellMapper implements Mapper { | |||
public PDFName getStructureType(PDFObject parent) { | |||
public StructureType getStructureType(PDFObject parent) { | |||
PDFStructElem grandParent = ((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())) { | |||
type = STANDARD_STRUCTURE_TYPES.get("TH"); | |||
if (grandParent.getStructureType() == StandardStructureTypes.Table.THEAD) { | |||
return StandardStructureTypes.Table.TH; | |||
} else { | |||
type = STANDARD_STRUCTURE_TYPES.get("TD"); | |||
return StandardStructureTypes.Table.TD; | |||
} | |||
assert type != null; | |||
return type; | |||
} | |||
} |
@@ -132,7 +132,7 @@ class PDFLogicalStructureHandler { | |||
? structureTreeElement.getParentStructElem() | |||
: structureTreeElement; | |||
pageParentTreeArray.add(parent); | |||
String type = parent.getStructureType().toString(); | |||
String type = parent.getStructureType().getName().toString(); | |||
int mcid = pageParentTreeArray.length() - 1; | |||
return new MarkedContentInfo(type, mcid, structureTreeElement); | |||
} |
@@ -29,18 +29,18 @@ import org.apache.fop.accessibility.StructureTreeEventHandler; | |||
import org.apache.fop.events.EventBroadcaster; | |||
import org.apache.fop.fo.extensions.ExtensionElementMapping; | |||
import org.apache.fop.pdf.PDFFactory; | |||
import org.apache.fop.pdf.PDFName; | |||
import org.apache.fop.pdf.PDFObject; | |||
import org.apache.fop.pdf.PDFParentTree; | |||
import org.apache.fop.pdf.PDFStructElem; | |||
import org.apache.fop.pdf.PDFStructTreeRoot; | |||
import org.apache.fop.pdf.StandardStructureAttributes.Table.Scope; | |||
import org.apache.fop.pdf.StandardStructureTypes.Table; | |||
import org.apache.fop.pdf.StructureType; | |||
class PDFStructureTreeBuilder implements StructureTreeEventHandler { | |||
private PDFFactory pdfFactory; | |||
private PDFLogicalStructureHandler logicalStructureHandler; | |||
private EventBroadcaster eventBroadcaster; | |||
private LinkedList<PDFStructElem> ancestors = new LinkedList<PDFStructElem>(); | |||
@@ -52,11 +52,10 @@ class PDFStructureTreeBuilder implements StructureTreeEventHandler { | |||
} | |||
void setLogicalStructureHandler(PDFLogicalStructureHandler logicalStructureHandler) { | |||
this.logicalStructureHandler = logicalStructureHandler; | |||
createRootStructureElement(); | |||
createRootStructureElement(logicalStructureHandler); | |||
} | |||
private void createRootStructureElement() { | |||
private void createRootStructureElement(PDFLogicalStructureHandler logicalStructureHandler) { | |||
assert rootStructureElement == null; | |||
PDFParentTree parentTree = logicalStructureHandler.getParentTree(); | |||
PDFStructTreeRoot structTreeRoot = pdfFactory.getDocument().makeStructTreeRoot(parentTree); | |||
@@ -79,8 +78,13 @@ class PDFStructureTreeBuilder implements StructureTreeEventHandler { | |||
} | |||
private PDFStructElem createStructureElement(String name, PDFObject parent, String role) { | |||
PDFName structureType = FOToPDFRoleMap.mapFormattingObject(name, role, parent, eventBroadcaster); | |||
return pdfFactory.getDocument().makeStructureElement(structureType, parent); | |||
StructureType structureType = FOToPDFRoleMap.mapFormattingObject(name, role, parent, | |||
eventBroadcaster); | |||
if (structureType == Table.TH) { | |||
return pdfFactory.getDocument().makeStructureElement(structureType, parent, Scope.COLUMN); | |||
} else { | |||
return pdfFactory.getDocument().makeStructureElement(structureType, parent); | |||
} | |||
} | |||
public void endPageSequence() { | |||
@@ -135,7 +139,7 @@ class PDFStructureTreeBuilder implements StructureTreeEventHandler { | |||
String role = attributes.getValue("role"); | |||
PDFStructElem structElem; | |||
if ("#PCDATA".equals(name)) { | |||
structElem = new PDFStructElem.Placeholder(parent, name); | |||
structElem = new PDFStructElem.Placeholder(parent); | |||
} else { | |||
structElem = createStructureElement(name, parent, role); | |||
} |
@@ -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="53639"> | |||
When PDF accessibility is enabled, the Scope attribute must be present in the structure tree | |||
for table header elements. | |||
</action> | |||
<action context="Fonts" dev="MH" type="add" fixes-bug="53600" due-to="Robert Meyer"> | |||
Added an event if a glyph and its metric information does not exist in the character set | |||
</action> |
@@ -0,0 +1,131 @@ | |||
/* | |||
* 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.pdf; | |||
import org.junit.Test; | |||
import org.mockito.ArgumentMatcher; | |||
import org.mockito.verification.VerificationMode; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.mockito.Matchers.any; | |||
import static org.mockito.Matchers.argThat; | |||
import static org.mockito.Matchers.eq; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.never; | |||
import static org.mockito.Mockito.times; | |||
import static org.mockito.Mockito.verify; | |||
import org.apache.fop.pdf.StandardStructureAttributes.Table.Scope; | |||
import org.apache.fop.pdf.StandardStructureTypes.Table; | |||
public class TableHeaderScopeTestCase { | |||
private static final String ATTRIBUTE_ENTRY = "A"; | |||
private VersionController controller; | |||
@Test | |||
public void pdfDocumentDelegatesToVersionController() { | |||
for (Scope scope : Scope.values()) { | |||
testMakeStructureElementWithScope(scope); | |||
} | |||
} | |||
private void testMakeStructureElementWithScope(Scope scope) { | |||
VersionController controller = mock(VersionController.class); | |||
PDFDocument document = new PDFDocument("Test", controller); | |||
document.makeStructTreeRoot(null); | |||
document.makeStructureElement(Table.TH, null, scope); | |||
verify(controller).addTableHeaderScopeAttribute(any(PDFStructElem.class), eq(scope)); | |||
} | |||
@Test | |||
public void versionControllerMayDelegateToScope() { | |||
fixedController14doesNotAddAttribute(); | |||
fixedController15addsAttribute(); | |||
dynamicControllerAddsAttribute(); | |||
} | |||
private void fixedController14doesNotAddAttribute() { | |||
controller = VersionController.getFixedVersionController(Version.V1_4); | |||
scopeMustNotBeAdded(); | |||
} | |||
private void fixedController15addsAttribute() { | |||
controller = VersionController.getFixedVersionController(Version.V1_5); | |||
scopeMustBeAdded(); | |||
} | |||
private void dynamicControllerAddsAttribute() { | |||
PDFDocument document = new PDFDocument("Test"); | |||
controller = VersionController.getDynamicVersionController(Version.V1_4, document); | |||
scopeMustBeAdded(); | |||
assertEquals(Version.V1_5, controller.getPDFVersion()); | |||
} | |||
private void scopeMustBeAdded() { | |||
scopeMustBeAdded(times(1)); | |||
} | |||
private void scopeMustNotBeAdded() { | |||
scopeMustBeAdded(never()); | |||
} | |||
private void scopeMustBeAdded(VerificationMode nTimes) { | |||
PDFStructElem structElem = mock(PDFStructElem.class); | |||
controller.addTableHeaderScopeAttribute(structElem, Scope.COLUMN); | |||
verify(structElem, nTimes).put(eq(ATTRIBUTE_ENTRY), any()); | |||
} | |||
@Test | |||
public void scopeAddsTheAttribute() { | |||
for (Scope scope : Scope.values()) { | |||
scopeAttributeMustBeAdded(scope); | |||
} | |||
} | |||
private void scopeAttributeMustBeAdded(Scope scope) { | |||
PDFStructElem structElem = mock(PDFStructElem.class); | |||
Scope.addScopeAttribute(structElem, scope); | |||
verify(structElem).put(eq(ATTRIBUTE_ENTRY), scopeAttribute(scope)); | |||
} | |||
private PDFDictionary scopeAttribute(Scope scope) { | |||
return argThat(new isScopeAttribute(scope)); | |||
} | |||
private static class isScopeAttribute extends ArgumentMatcher<PDFDictionary> { | |||
private final Scope expectedScope; | |||
public isScopeAttribute(Scope expectedScope) { | |||
this.expectedScope = expectedScope; | |||
} | |||
@Override | |||
public boolean matches(Object argument) { | |||
PDFDictionary attribute = (PDFDictionary) argument; | |||
return "/Table".equals(attribute.get("O").toString()) | |||
&& expectedScope.getName().toString().equals(attribute.get("Scope").toString()); | |||
} | |||
} | |||
} |
@@ -6,6 +6,7 @@ | |||
<font-base>../../resources/fonts/ttf/</font-base> | |||
<renderers> | |||
<renderer mime="application/pdf"> | |||
<version>1.4</version> | |||
<filterList> | |||
<value>null</value> | |||
</filterList> |