git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1368420 13f79535-47bb-0310-9956-ffa450edef68pull/26/head
import org.apache.commons.logging.Log; | import org.apache.commons.logging.Log; | ||||
import org.apache.commons.logging.LogFactory; | 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.CrossReferenceStream; | ||||
import org.apache.fop.pdf.xref.CrossReferenceTable; | import org.apache.fop.pdf.xref.CrossReferenceTable; | ||||
import org.apache.fop.pdf.xref.TrailerDictionary; | import org.apache.fop.pdf.xref.TrailerDictionary; | ||||
* hierarchy | * hierarchy | ||||
* @return a dictionary of type StructElem | * @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); | PDFStructElem structElem = new PDFStructElem(parent, structureType); | ||||
assignObjectNumber(structElem); | assignObjectNumber(structElem); | ||||
structureTreeElements.add(structElem); | structureTreeElements.add(structElem); | ||||
return 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. | * Get the {@link PDFInfo} object for this document. | ||||
* | * |
import java.util.Locale; | import java.util.Locale; | ||||
import org.apache.fop.accessibility.StructureTreeElement; | import org.apache.fop.accessibility.StructureTreeElement; | ||||
import org.apache.fop.pdf.StandardStructureAttributes.Table; | |||||
import org.apache.fop.util.LanguageTags; | import org.apache.fop.util.LanguageTags; | ||||
/** | /** | ||||
*/ | */ | ||||
public class PDFStructElem extends PDFDictionary implements StructureTreeElement, CompressedObject { | public class PDFStructElem extends PDFDictionary implements StructureTreeElement, CompressedObject { | ||||
private static final PDFName TABLE = new PDFName("Table"); | |||||
private StructureType structureType; | |||||
private PDFStructElem parentElement; | private PDFStructElem parentElement; | ||||
* @param parent parent of this element | * @param parent parent of this element | ||||
* @param structureType the structure type 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) { | if (parent instanceof PDFStructElem) { | ||||
parentElement = (PDFStructElem) parent; | parentElement = (PDFStructElem) parent; | ||||
} | } | ||||
put("S", structureType); | |||||
setParent(parent); | |||||
} | } | ||||
/** | /** | ||||
* | * | ||||
* @return the value of the S entry | * @return the value of the S entry | ||||
*/ | */ | ||||
public PDFName getStructureType() { | |||||
return (PDFName) get("S"); | |||||
public StructureType getStructureType() { | |||||
return structureType; | |||||
} | } | ||||
/** | /** | ||||
private void setTableAttributeRowColumnSpan(String typeSpan, int span) { | private void setTableAttributeRowColumnSpan(String typeSpan, int span) { | ||||
PDFDictionary attribute = new PDFDictionary(); | PDFDictionary attribute = new PDFDictionary(); | ||||
attribute.put("O", TABLE); | |||||
attribute.put("O", Table.NAME); | |||||
attribute.put(typeSpan, span); | attribute.put(typeSpan, span); | ||||
if (attributes == null) { | if (attributes == null) { | ||||
attributes = new ArrayList<PDFDictionary>(2); | attributes = new ArrayList<PDFDictionary>(2); | ||||
} | } | ||||
} | } | ||||
/** | |||||
* Constructor | |||||
* @param parent - | |||||
* @param name - | |||||
*/ | |||||
public Placeholder(PDFObject parent, String name) { | |||||
super(parent, new PDFName(name)); | |||||
public Placeholder(PDFObject parent) { | |||||
super(parent); | |||||
} | } | ||||
} | } | ||||
/* | |||||
* 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() { } | |||||
} |
/* | |||||
* 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); | |||||
} | |||||
} |
/* | |||||
* 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(); | |||||
} |
package org.apache.fop.pdf; | 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. | * An abstraction that controls the mutability of the PDF version for a document. | ||||
*/ | */ | ||||
*/ | */ | ||||
public abstract void setPDFVersion(Version version); | public abstract void setPDFVersion(Version version); | ||||
abstract void addTableHeaderScopeAttribute(PDFStructElem th, Scope scope); | |||||
@Override | @Override | ||||
public String toString() { | public String toString() { | ||||
return version.toString(); | return version.toString(); | ||||
public void setPDFVersion(Version version) { | public void setPDFVersion(Version version) { | ||||
throw new IllegalStateException("Cannot change the version of this PDF document."); | 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); | |||||
} | |||||
} | |||||
} | } | ||||
/** | /** | ||||
doc.getRoot().setVersion(version); | doc.getRoot().setVersion(version); | ||||
} | } | ||||
} | } | ||||
@Override | |||||
void addTableHeaderScopeAttribute(PDFStructElem th, Scope scope) { | |||||
setPDFVersion(Version.V1_5); | |||||
Scope.addScopeAttribute(th, scope); | |||||
} | |||||
} | } | ||||
/** | /** |
package org.apache.fop.render.pdf; | package org.apache.fop.render.pdf; | ||||
import java.util.HashMap; | |||||
import java.util.Map; | import java.util.Map; | ||||
import org.apache.fop.events.EventBroadcaster; | import org.apache.fop.events.EventBroadcaster; | ||||
import org.apache.fop.pdf.PDFName; | |||||
import org.apache.fop.pdf.PDFObject; | import org.apache.fop.pdf.PDFObject; | ||||
import org.apache.fop.pdf.PDFStructElem; | 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. | * This class provides the standard mappings from Formatting Objects to PDF structure types. | ||||
*/ | */ | ||||
final class FOToPDFRoleMap { | 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 { | 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 | // Create the standard mappings | ||||
// Declarations and Pagination and Layout Formatting Objects | // 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 | // 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 | // 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 | // 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()); | addMapping("table-cell", new TableCellMapper()); | ||||
// Formatting Objects for Lists | // 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 | // Dynamic Effects: Link and Multi Formatting Objects | ||||
addMapping("basic-link", "Link"); | |||||
addMapping("basic-link", StandardStructureTypes.InlineLevelStructure.LINK); | |||||
// Out-of-Line Formatting Objects | // 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) { | private static void addMapping(String fo, Mapper mapper) { | ||||
* @param eventBroadcaster the event broadcaster | * @param eventBroadcaster the event broadcaster | ||||
* @return the structure type or null if no match could be found | * @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) { | PDFObject parent, EventBroadcaster eventBroadcaster) { | ||||
PDFName type = null; | |||||
StructureType type = null; | |||||
if (role == null) { | if (role == null) { | ||||
type = getDefaultMappingFor(fo, parent); | type = getDefaultMappingFor(fo, parent); | ||||
} else { | } else { | ||||
type = STANDARD_STRUCTURE_TYPES.get(role); | |||||
type = StandardStructureTypes.get(role); | |||||
if (type == null) { | if (type == null) { | ||||
type = getDefaultMappingFor(fo, parent); | type = getDefaultMappingFor(fo, parent); | ||||
PDFEventProducer.Provider.get(eventBroadcaster).nonStandardStructureType(fo, | PDFEventProducer.Provider.get(eventBroadcaster).nonStandardStructureType(fo, | ||||
* @param parent the parent of the structure element to be mapped | * @param parent the parent of the structure element to be mapped | ||||
* @return the structure type or NonStruct if no match could be found | * @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); | Mapper mapper = DEFAULT_MAPPINGS.get(fo); | ||||
if (mapper != null) { | if (mapper != null) { | ||||
return mapper.getStructureType(parent); | return mapper.getStructureType(parent); | ||||
} else { | } else { | ||||
return NON_STRUCT; | |||||
return StandardStructureTypes.Grouping.NON_STRUCT; | |||||
} | } | ||||
} | } | ||||
private interface Mapper { | private interface Mapper { | ||||
PDFName getStructureType(PDFObject parent); | |||||
StructureType getStructureType(PDFObject parent); | |||||
} | } | ||||
private static class SimpleMapper implements Mapper { | private static class SimpleMapper implements Mapper { | ||||
private PDFName structureType; | |||||
private StructureType structureType; | |||||
public SimpleMapper(PDFName structureType) { | |||||
public SimpleMapper(StructureType structureType) { | |||||
this.structureType = structureType; | this.structureType = structureType; | ||||
} | } | ||||
public PDFName getStructureType(PDFObject parent) { | |||||
public StructureType getStructureType(PDFObject parent) { | |||||
return structureType; | return structureType; | ||||
} | } | ||||
private static class TableCellMapper implements Mapper { | private static class TableCellMapper implements Mapper { | ||||
public PDFName getStructureType(PDFObject parent) { | |||||
public StructureType getStructureType(PDFObject parent) { | |||||
PDFStructElem grandParent = ((PDFStructElem) parent).getParentStructElem(); | PDFStructElem grandParent = ((PDFStructElem) parent).getParentStructElem(); | ||||
//TODO What to do with cells from table-footer? Currently they are mapped on TD. | //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 { | } else { | ||||
type = STANDARD_STRUCTURE_TYPES.get("TD"); | |||||
return StandardStructureTypes.Table.TD; | |||||
} | } | ||||
assert type != null; | |||||
return type; | |||||
} | } | ||||
} | } |
? structureTreeElement.getParentStructElem() | ? structureTreeElement.getParentStructElem() | ||||
: structureTreeElement; | : structureTreeElement; | ||||
pageParentTreeArray.add(parent); | pageParentTreeArray.add(parent); | ||||
String type = parent.getStructureType().toString(); | |||||
String type = parent.getStructureType().getName().toString(); | |||||
int mcid = pageParentTreeArray.length() - 1; | int mcid = pageParentTreeArray.length() - 1; | ||||
return new MarkedContentInfo(type, mcid, structureTreeElement); | return new MarkedContentInfo(type, mcid, structureTreeElement); | ||||
} | } |
import org.apache.fop.events.EventBroadcaster; | import org.apache.fop.events.EventBroadcaster; | ||||
import org.apache.fop.fo.extensions.ExtensionElementMapping; | import org.apache.fop.fo.extensions.ExtensionElementMapping; | ||||
import org.apache.fop.pdf.PDFFactory; | import org.apache.fop.pdf.PDFFactory; | ||||
import org.apache.fop.pdf.PDFName; | |||||
import org.apache.fop.pdf.PDFObject; | import org.apache.fop.pdf.PDFObject; | ||||
import org.apache.fop.pdf.PDFParentTree; | import org.apache.fop.pdf.PDFParentTree; | ||||
import org.apache.fop.pdf.PDFStructElem; | import org.apache.fop.pdf.PDFStructElem; | ||||
import org.apache.fop.pdf.PDFStructTreeRoot; | 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 { | class PDFStructureTreeBuilder implements StructureTreeEventHandler { | ||||
private PDFFactory pdfFactory; | private PDFFactory pdfFactory; | ||||
private PDFLogicalStructureHandler logicalStructureHandler; | |||||
private EventBroadcaster eventBroadcaster; | private EventBroadcaster eventBroadcaster; | ||||
private LinkedList<PDFStructElem> ancestors = new LinkedList<PDFStructElem>(); | private LinkedList<PDFStructElem> ancestors = new LinkedList<PDFStructElem>(); | ||||
} | } | ||||
void setLogicalStructureHandler(PDFLogicalStructureHandler logicalStructureHandler) { | void setLogicalStructureHandler(PDFLogicalStructureHandler logicalStructureHandler) { | ||||
this.logicalStructureHandler = logicalStructureHandler; | |||||
createRootStructureElement(); | |||||
createRootStructureElement(logicalStructureHandler); | |||||
} | } | ||||
private void createRootStructureElement() { | |||||
private void createRootStructureElement(PDFLogicalStructureHandler logicalStructureHandler) { | |||||
assert rootStructureElement == null; | assert rootStructureElement == null; | ||||
PDFParentTree parentTree = logicalStructureHandler.getParentTree(); | PDFParentTree parentTree = logicalStructureHandler.getParentTree(); | ||||
PDFStructTreeRoot structTreeRoot = pdfFactory.getDocument().makeStructTreeRoot(parentTree); | PDFStructTreeRoot structTreeRoot = pdfFactory.getDocument().makeStructTreeRoot(parentTree); | ||||
} | } | ||||
private PDFStructElem createStructureElement(String name, PDFObject parent, String role) { | 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() { | public void endPageSequence() { | ||||
String role = attributes.getValue("role"); | String role = attributes.getValue("role"); | ||||
PDFStructElem structElem; | PDFStructElem structElem; | ||||
if ("#PCDATA".equals(name)) { | if ("#PCDATA".equals(name)) { | ||||
structElem = new PDFStructElem.Placeholder(parent, name); | |||||
structElem = new PDFStructElem.Placeholder(parent); | |||||
} else { | } else { | ||||
structElem = createStructureElement(name, parent, role); | structElem = createStructureElement(name, parent, role); | ||||
} | } |
documents. Example: the fix of marks layering will be such a case when it's done. | documents. Example: the fix of marks layering will be such a case when it's done. | ||||
--> | --> | ||||
<release version="FOP Trunk" date="TBD"> | <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"> | <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 | Added an event if a glyph and its metric information does not exist in the character set | ||||
</action> | </action> |
/* | |||||
* 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()); | |||||
} | |||||
} | |||||
} |
<font-base>../../resources/fonts/ttf/</font-base> | <font-base>../../resources/fonts/ttf/</font-base> | ||||
<renderers> | <renderers> | ||||
<renderer mime="application/pdf"> | <renderer mime="application/pdf"> | ||||
<version>1.4</version> | |||||
<filterList> | <filterList> | ||||
<value>null</value> | <value>null</value> | ||||
</filterList> | </filterList> |