git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_Accessibility@765979 13f79535-47bb-0310-9956-ffa450edef68tags/fop-1_0
@@ -44,7 +44,18 @@ public final class PDFAMode { | |||
return this.name; | |||
} | |||
/** @return true if this mode obey the restrictions established by PDF/A-1b. */ | |||
/** | |||
* Indicates whether this mode obeys the restrictions established by PDF/A-1a. | |||
* @return true if this mode obeys the restrictions established by PDF/A-1a. | |||
*/ | |||
public boolean isPDFA1LevelA() { | |||
return (this != DISABLED); | |||
} | |||
/** | |||
* Indicates whether this mode obeys the restrictions established by PDF/A-1b. | |||
* @return true if this mode obeys the restrictions established by PDF/A-1b. | |||
*/ | |||
public boolean isPDFA1LevelB() { | |||
return (this != DISABLED); | |||
//PDF/A-1a is a superset of PDF/A-1b! |
@@ -58,9 +58,6 @@ public class PDFProfile { | |||
*/ | |||
protected void validateProfileCombination() { | |||
if (pdfAMode != PDFAMode.DISABLED) { | |||
if (pdfAMode == PDFAMode.PDFA_1A) { | |||
throw new UnsupportedOperationException("PDF/A-1a is not implemented, yet"); | |||
} | |||
if (pdfAMode == PDFAMode.PDFA_1B) { | |||
if (pdfXMode != PDFXMode.DISABLED && pdfXMode != PDFXMode.PDFX_3_2003) { | |||
throw new PDFConformanceException( | |||
@@ -192,6 +189,32 @@ public class PDFProfile { | |||
} | |||
} | |||
/** | |||
* Checks a few things required for tagged PDF. | |||
*/ | |||
public void verifyTaggedPDF() { | |||
if (getPDFAMode().isPDFA1LevelA()) { | |||
final String err = "{0} requires the {1} dictionary entry to be set"; | |||
PDFDictionary markInfo = getDocument().getRoot().getMarkInfo(); | |||
if (markInfo == null) { | |||
throw new PDFConformanceException(format( | |||
"{0} requires the MarkInfo dictionary to be present", getPDFAMode())); | |||
} | |||
if (!Boolean.TRUE.equals(markInfo.get("Marked"))) { | |||
throw new PDFConformanceException(format(err, | |||
new Object[] {getPDFAMode(), "Marked"})); | |||
} | |||
if (getDocument().getRoot().getStructTreeRoot() == null) { | |||
throw new PDFConformanceException(format(err, | |||
new Object[] {getPDFAMode(), "StructTreeRoot"})); | |||
} | |||
if (getDocument().getRoot().getLanguage() == null) { | |||
throw new PDFConformanceException(format(err, | |||
new Object[] {getPDFAMode(), "Lang"})); | |||
} | |||
} | |||
} | |||
/** @return true if the ID entry must be present in the trailer. */ | |||
public boolean isIDEntryRequired() { | |||
return isPDFAActive() || isPDFXActive(); |
@@ -19,6 +19,9 @@ | |||
package org.apache.fop.pdf; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
/** | |||
* Class representing a Root (/Catalog) object. | |||
*/ | |||
@@ -56,7 +59,7 @@ public class PDFRoot extends PDFDictionary { | |||
* object must be created before the PDF document is | |||
* generated, but it is not assigned an object ID until | |||
* it is about to be written (immediately before the xref | |||
* table as part of the trsailer). (mark-fop@inomial.com) | |||
* table as part of the trailer). (mark-fop@inomial.com) | |||
* | |||
* @param objnum the object's number | |||
* @param pages the PDFPages object | |||
@@ -68,6 +71,12 @@ public class PDFRoot extends PDFDictionary { | |||
setRootPages(pages); | |||
} | |||
/** {@inheritDoc} */ | |||
protected int output(OutputStream stream) throws IOException { | |||
getDocument().getProfile().verifyTaggedPDF(); | |||
return super.output(stream); | |||
} | |||
/** | |||
* Set the page mode for the PDF document. | |||
* | |||
@@ -280,4 +289,11 @@ public class PDFRoot extends PDFDictionary { | |||
put("MarkInfo", dict); //new PDFMarkInfo() | |||
} | |||
/** | |||
* Returns the MarkInfo dictionary. | |||
* @return the MarkInfo dictionary (or null if it's not present) | |||
*/ | |||
public PDFDictionary getMarkInfo() { | |||
return (PDFDictionary)get("MarkInfo"); | |||
} | |||
} |
@@ -306,8 +306,15 @@ public class PDFDocumentHandler extends AbstractBinaryWritingIFDocumentHandler { | |||
if (getUserAgent().isAccessibilityEnabled()) { | |||
try { | |||
if (this.pdfDoc.getRoot().getLanguage() == null) { | |||
//No language has been set on the first page-sequence, so fall back to "en". | |||
this.pdfDoc.getRoot().setLanguage("en"); | |||
String fallbackLanguage; | |||
if (this.pdfDoc.getProfile().getPDFAMode().isPDFA1LevelA()) { | |||
//According to Annex B of ISO-19005-1:2005(E), section B.2 | |||
fallbackLanguage = "x-unknown"; | |||
} else { | |||
//No language has been set on the first page-sequence, so fall back to "en". | |||
fallbackLanguage = "en"; | |||
} | |||
this.pdfDoc.getRoot().setLanguage(fallbackLanguage); | |||
} | |||
if (reducedFOTree == null) { |
@@ -37,6 +37,7 @@ import org.apache.xmlgraphics.xmp.Metadata; | |||
import org.apache.xmlgraphics.xmp.schemas.XMPBasicAdapter; | |||
import org.apache.xmlgraphics.xmp.schemas.XMPBasicSchema; | |||
import org.apache.fop.accessibility.AccessibilityUtil; | |||
import org.apache.fop.apps.FOUserAgent; | |||
import org.apache.fop.fo.extensions.xmp.XMPMetadata; | |||
import org.apache.fop.pdf.PDFAMode; | |||
@@ -109,7 +110,7 @@ class PDFRenderingUtil implements PDFConfigurationConstants { | |||
private void initialize() { | |||
PDFEncryptionParams params | |||
= (PDFEncryptionParams)userAgent.getRendererOptions().get(ENCRYPTION_PARAMS); | |||
= (PDFEncryptionParams)userAgent.getRendererOptions().get(ENCRYPTION_PARAMS); | |||
if (params != null) { | |||
this.encryptionParams = params; //overwrite if available | |||
} | |||
@@ -161,6 +162,10 @@ class PDFRenderingUtil implements PDFConfigurationConstants { | |||
if (s != null) { | |||
this.pdfAMode = PDFAMode.valueOf(s); | |||
} | |||
if (this.pdfAMode.isPDFA1LevelA()) { | |||
//Enable accessibility if PDF/A-1a is enabled because it requires tagged PDF. | |||
userAgent.getRendererOptions().put(AccessibilityUtil.ACCESSIBILITY, Boolean.TRUE); | |||
} | |||
s = (String)userAgent.getRendererOptions().get(PDF_X_MODE); | |||
if (s != null) { | |||
this.pdfXMode = PDFXMode.valueOf(s); |