You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by vh...@apache.org on 2009/10/27 20:07:58 UTC
svn commit: r830293 [2/2] - in /xmlgraphics/fop/trunk: ./
src/documentation/content/xdocs/ src/documentation/content/xdocs/trunk/
src/java/META-INF/services/ src/java/org/apache/fop/accessibility/
src/java/org/apache/fop/apps/ src/java/org/apache/fop/a...
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFPage.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFPage.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFPage.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFPage.java Tue Oct 27 19:07:52 2009
@@ -154,4 +154,33 @@
return this.pageIndex;
}
+ /**
+ * Sets the "StructParents" value.
+ * @param structParents the integer key of this object's entry in the structural parent tree.
+ */
+ public void setStructParents(int structParents) {
+ put("StructParents", structParents);
+ //This is a PDF 1.5 feature. It is set as a work-around for a bug in Adobe Acrobat
+ //which reports this missing even if the PDF file is PDF 1.4.
+ setTabs(new PDFName("S"));
+ }
+
+ /**
+ * Returns the value of the StructParents entry.
+ *
+ * @return the StructParents value, <code>null</code> if the entry has not been set
+ */
+ public Integer getStructParents() {
+ return (Integer) get("StructParents");
+ }
+
+ /**
+ * Specifies the tab order for annotations on a page.
+ * @param value one of the allowed values (see PDF 1.5)
+ * @since PDF 1.5
+ */
+ public void setTabs(PDFName value) {
+ put("Tabs", value);
+ }
+
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFProfile.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFProfile.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFProfile.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFProfile.java Tue Oct 27 19:07:52 2009
@@ -58,9 +58,6 @@
*/
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 @@
}
}
+ /**
+ * 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();
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFRoot.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFRoot.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFRoot.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFRoot.java Tue Oct 27 19:07:52 2009
@@ -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 @@
* 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 @@
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.
*
@@ -252,4 +261,39 @@
put("Lang", lang);
}
+ /**
+ * Sets the StructTreeRoot object. Used for accessibility.
+ * @param structTreeRoot of this document
+ */
+ public void setStructTreeRoot(PDFStructTreeRoot structTreeRoot) {
+ if (structTreeRoot == null) {
+ throw new NullPointerException("structTreeRoot must not be null");
+ }
+ put("StructTreeRoot", structTreeRoot);
+ }
+
+ /**
+ * Returns the StructTreeRoot object.
+ * @return the structure tree root (or null if accessibility is not enabled)
+ */
+ public PDFStructTreeRoot getStructTreeRoot() {
+ return (PDFStructTreeRoot)get("StructTreeRoot");
+ }
+
+ /**
+ * Marks this document as conforming to the Tagged PDF conventions.
+ */
+ public void makeTagged() {
+ PDFDictionary dict = new PDFDictionary();
+ dict.put("Marked", Boolean.TRUE);
+ 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");
+ }
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/AbstractRendererConfigurator.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/AbstractRendererConfigurator.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/AbstractRendererConfigurator.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/AbstractRendererConfigurator.java Tue Oct 27 19:07:52 2009
@@ -20,6 +20,7 @@
package org.apache.fop.render;
import org.apache.avalon.framework.configuration.Configuration;
+
import org.apache.fop.apps.FOUserAgent;
/**
@@ -29,7 +30,7 @@
public abstract class AbstractRendererConfigurator extends AbstractConfigurator {
private static final String TYPE = "renderer";
-
+
/**
* Default constructor
* @param userAgent user agent
@@ -55,7 +56,7 @@
protected Configuration getRendererConfig(String mimeType) {
return super.getConfig(mimeType);
}
-
+
/**
* {@inheritDoc}
*/
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFConstants.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFConstants.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFConstants.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFConstants.java Tue Oct 27 19:07:52 2009
@@ -50,4 +50,6 @@
String EL_BORDER_RECT = "border-rect";
String EL_FONT = "font";
String EL_TEXT = "text";
+ /** Parent element of the logical structure tree. */
+ String EL_STRUCTURE_TREE = "structure-tree";
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFContext.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFContext.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFContext.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFContext.java Tue Oct 27 19:07:52 2009
@@ -20,6 +20,7 @@
package org.apache.fop.render.intermediate;
import java.util.Collections;
+import java.util.Locale;
import java.util.Map;
import org.apache.xmlgraphics.util.QName;
@@ -43,6 +44,10 @@
/** foreign attributes: Map<QName, Object> */
private Map foreignAttributes = Collections.EMPTY_MAP;
+ private Locale language;
+
+ private String structurePointer;
+
/**
* Main constructor.
* @param ua the user agent
@@ -108,4 +113,46 @@
setForeignAttributes(null);
}
+ /**
+ * Sets the currently applicable language.
+ * @param lang the language
+ */
+ public void setLanguage(Locale lang) {
+ this.language = lang;
+ }
+
+ /**
+ * Returns the currently applicable language.
+ * @return the language (or null if the language is undefined)
+ */
+ public Locale getLanguage() {
+ return this.language;
+ }
+
+ /**
+ * Sets the structure pointer for the following painted marks. This method is used when
+ * accessibility features are enabled.
+ * @param ptr the structure pointer
+ */
+ public void setStructurePointer(String ptr) {
+ this.structurePointer = ptr;
+ }
+
+ /**
+ * Resets the current structure pointer.
+ * @see #setStructurePointer(String)
+ */
+ public void resetStructurePointer() {
+ setStructurePointer(null);
+ }
+
+ /**
+ * Returns the current structure pointer.
+ * @return the structure pointer (or null if no pointer is active)
+ * @see #setStructurePointer(String)
+ */
+ public String getStructurePointer() {
+ return this.structurePointer;
+ }
+
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFParser.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFParser.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFParser.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFParser.java Tue Oct 27 19:07:52 2009
@@ -25,6 +25,7 @@
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.util.Map;
+import java.util.Set;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
@@ -34,7 +35,6 @@
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
-
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
@@ -46,6 +46,8 @@
import org.apache.xmlgraphics.util.QName;
+import org.apache.fop.accessibility.AccessibilityEventProducer;
+import org.apache.fop.accessibility.StructureTreeBuilder;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.fo.ElementMapping;
import org.apache.fop.fo.ElementMappingRegistry;
@@ -59,6 +61,7 @@
import org.apache.fop.util.ContentHandlerFactoryRegistry;
import org.apache.fop.util.DOMBuilderContentHandlerFactory;
import org.apache.fop.util.DefaultErrorListener;
+import org.apache.fop.util.DelegatingContentHandler;
import org.apache.fop.util.XMLUtil;
/**
@@ -73,6 +76,15 @@
private static SAXTransformerFactory tFactory
= (SAXTransformerFactory)SAXTransformerFactory.newInstance();
+ private static Set handledNamespaces = new java.util.HashSet();
+
+ static {
+ handledNamespaces.add(XMLNS_NAMESPACE_URI);
+ handledNamespaces.add(XML_NAMESPACE);
+ handledNamespaces.add(NAMESPACE);
+ handledNamespaces.add(XLINK_NAMESPACE);
+ }
+
/**
* Parses an intermediate file and paints it.
* @param src the Source instance pointing to the intermediate file
@@ -140,6 +152,26 @@
private ContentHandler navParser;
+ private StructureTreeBuilder structureTreeBuilder;
+
+ private ContentHandler structureTreeBuilderWrapper;
+
+ private Attributes pageSequenceAttributes;
+
+ private final class StructureTreeBuilderWrapper extends DelegatingContentHandler {
+
+ private StructureTreeBuilderWrapper()
+ throws SAXException {
+ super(structureTreeBuilder.getHandlerForNextPageSequence());
+ }
+
+ public void endDocument() throws SAXException {
+ super.endDocument();
+ startIFElement(EL_PAGE_SEQUENCE, pageSequenceAttributes);
+ pageSequenceAttributes = null;
+ }
+ }
+
public Handler(IFDocumentHandler documentHandler, FOUserAgent userAgent,
ElementMappingRegistry elementMappingRegistry) {
this.documentHandler = documentHandler;
@@ -163,6 +195,11 @@
elementHandlers.put(EL_LINE, new LineHandler());
elementHandlers.put(EL_BORDER_RECT, new BorderRectHandler());
elementHandlers.put(EL_IMAGE, new ImageHandler());
+
+ if (userAgent.isAccessibilityEnabled()) {
+ structureTreeBuilder = new StructureTreeBuilder(tFactory);
+ userAgent.setStructureTree(structureTreeBuilder.getStructureTree());
+ }
}
private void establishForeignAttributes(Map foreignAttributes) {
@@ -173,31 +210,50 @@
documentHandler.getContext().resetForeignAttributes();
}
+ private void establishStructurePointer(String ptr) {
+ documentHandler.getContext().setStructurePointer(ptr);
+ }
+
+ private void resetStructurePointer() {
+ documentHandler.getContext().resetStructurePointer();
+ }
+
/** {@inheritDoc} */
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
if (delegate != null) {
- //delegateStack.push(qName);
delegateDepth++;
delegate.startElement(uri, localName, qName, attributes);
} else {
boolean handled = true;
if (NAMESPACE.equals(uri)) {
- lastAttributes = new AttributesImpl(attributes);
- ElementHandler elementHandler = (ElementHandler)elementHandlers.get(localName);
- content.setLength(0);
- ignoreCharacters = true;
- if (elementHandler != null) {
- ignoreCharacters = elementHandler.ignoreCharacters();
- try {
- elementHandler.startElement(attributes);
- } catch (IFException ife) {
- handleIFException(ife);
+ if (localName.equals(EL_PAGE_SEQUENCE) && userAgent.isAccessibilityEnabled()) {
+ pageSequenceAttributes = new AttributesImpl(attributes);
+ structureTreeBuilderWrapper = new StructureTreeBuilderWrapper();
+ } else if (localName.equals(EL_STRUCTURE_TREE)) {
+ if (userAgent.isAccessibilityEnabled()) {
+ delegate = structureTreeBuilderWrapper;
+ } else {
+ /* Delegate to a handler that does nothing */
+ delegate = new DefaultHandler();
}
- } else if ("extension-attachments".equals(localName)) {
- //TODO implement me
+ delegateDepth++;
+ delegate.startDocument();
+ delegate.startElement(uri, localName, qName, attributes);
} else {
- handled = false;
+ if (pageSequenceAttributes != null) {
+ /*
+ * This means that no structure-element tag was
+ * found in the XML, otherwise a
+ * StructureTreeBuilderWrapper object would have
+ * been created, which would have reset the
+ * pageSequenceAttributes field.
+ */
+ AccessibilityEventProducer.Provider
+ .get(userAgent.getEventBroadcaster())
+ .noStructureTreeInXML(this);
+ }
+ handled = startIFElement(localName, attributes);
}
} else if (DocumentNavigationExtensionConstants.NAMESPACE.equals(uri)) {
if (this.navParser == null) {
@@ -241,6 +297,25 @@
}
}
+ private boolean startIFElement(String localName, Attributes attributes)
+ throws SAXException {
+ lastAttributes = new AttributesImpl(attributes);
+ ElementHandler elementHandler = (ElementHandler)elementHandlers.get(localName);
+ content.setLength(0);
+ ignoreCharacters = true;
+ if (elementHandler != null) {
+ ignoreCharacters = elementHandler.ignoreCharacters();
+ try {
+ elementHandler.startElement(attributes);
+ } catch (IFException ife) {
+ handleIFException(ife);
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
private void handleIFException(IFException ife) throws SAXException {
if (ife.getCause() instanceof SAXException) {
//unwrap
@@ -352,6 +427,11 @@
public void startElement(Attributes attributes) throws IFException {
String id = attributes.getValue("id");
+ String xmllang = attributes.getValue(XML_NAMESPACE, "lang");
+ if (xmllang != null) {
+ documentHandler.getContext().setLanguage(
+ XMLUtil.convertRFC3066ToLocale(xmllang));
+ }
Map foreignAttributes = getForeignAttributes(lastAttributes);
establishForeignAttributes(foreignAttributes);
documentHandler.startPageSequence(id);
@@ -360,6 +440,7 @@
public void endElement() throws IFException {
documentHandler.endPageSequence();
+ documentHandler.getContext().setLanguage(null);
}
}
@@ -484,7 +565,9 @@
s = lastAttributes.getValue("word-spacing");
int wordSpacing = (s != null ? Integer.parseInt(s) : 0);
int[] dx = XMLUtil.getAttributeAsIntArray(lastAttributes, "dx");
+ setStructurePointer(lastAttributes);
painter.drawText(x, y, letterSpacing, wordSpacing, dx, content.toString());
+ resetStructurePointer();
}
public boolean ignoreCharacters() {
@@ -579,6 +662,7 @@
int height = Integer.parseInt(lastAttributes.getValue("height"));
Map foreignAttributes = getForeignAttributes(lastAttributes);
establishForeignAttributes(foreignAttributes);
+ setStructurePointer(lastAttributes);
if (foreignObject != null) {
painter.drawImage(foreignObject,
new Rectangle(x, y, width, height));
@@ -592,6 +676,7 @@
painter.drawImage(uri, new Rectangle(x, y, width, height));
}
resetForeignAttributes();
+ resetStructurePointer();
inForeignObject = false;
}
@@ -632,11 +717,7 @@
for (int i = 0, c = atts.getLength(); i < c; i++) {
String ns = atts.getURI(i);
if (ns.length() > 0) {
- if ("http://www.w3.org/2000/xmlns/".equals(ns)) {
- continue;
- } else if (NAMESPACE.equals(ns)) {
- continue;
- } else if (XLINK_NAMESPACE.equals(ns)) {
+ if (handledNamespaces.contains(ns)) {
continue;
}
if (foreignAttributes == null) {
@@ -649,6 +730,13 @@
return foreignAttributes;
}
+ private void setStructurePointer(Attributes attributes) {
+ String ptr = attributes.getValue("ptr");
+ if (ptr != null && ptr.length() > 0) {
+ establishStructurePointer(ptr);
+ }
+ }
+
/** {@inheritDoc} */
public void characters(char[] ch, int start, int length) throws SAXException {
if (delegate != null) {
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFRenderer.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFRenderer.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFRenderer.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFRenderer.java Tue Oct 27 19:07:52 2009
@@ -30,6 +30,7 @@
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Stack;
@@ -493,6 +494,7 @@
try {
if (this.inPageSequence) {
documentHandler.endPageSequence();
+ documentHandler.getContext().setLanguage(null);
} else {
if (this.documentMetadata == null) {
this.documentMetadata = createDefaultDocumentMetadata();
@@ -502,6 +504,7 @@
this.inPageSequence = true;
}
establishForeignAttributes(pageSequence.getForeignAttributes());
+ documentHandler.getContext().setLanguage(toLocale(pageSequence));
documentHandler.startPageSequence(null);
resetForeignAttributes();
processExtensionAttachments(pageSequence);
@@ -510,6 +513,17 @@
}
}
+ private Locale toLocale(PageSequence pageSequence) {
+ if (pageSequence.getLanguage() != null) {
+ if (pageSequence.getCountry() != null) {
+ return new Locale(pageSequence.getLanguage(), pageSequence.getCountry());
+ } else {
+ return new Locale(pageSequence.getLanguage());
+ }
+ }
+ return null;
+ }
+
private Metadata createDefaultDocumentMetadata() {
Metadata xmp = new Metadata();
DublinCoreAdapter dc = DublinCoreSchema.getAdapter(xmp);
@@ -604,6 +618,14 @@
documentHandler.getContext().resetForeignAttributes();
}
+ private void establishStructurePointer(String ptr) {
+ documentHandler.getContext().setStructurePointer(ptr);
+ }
+
+ private void resetStructurePointer() {
+ documentHandler.getContext().resetStructurePointer();
+ }
+
/** {@inheritDoc} */
protected void saveGraphicsState() {
graphicContextStack.push(graphicContext);
@@ -824,17 +846,20 @@
currentIPPosition = saveIP;
currentBPPosition = saveBP;
- currentBPPosition += (int)(bv.getAllocBPD());
+ currentBPPosition += bv.getAllocBPD();
}
viewportDimensionStack.pop();
}
/** {@inheritDoc} */
public void renderViewport(Viewport viewport) {
+ String ptr = (String) viewport.getTrait(Trait.PTR);
+ establishStructurePointer(ptr);
Dimension dim = new Dimension(viewport.getIPD(), viewport.getBPD());
viewportDimensionStack.push(dim);
super.renderViewport(viewport);
viewportDimensionStack.pop();
+ resetStructurePointer();
}
/** {@inheritDoc} */
@@ -892,6 +917,7 @@
// stuff we only need if a link must be created:
Rectangle ipRect = null;
AbstractAction action = null;
+ String ptr = (String) ip.getTrait(Trait.PTR); // used for accessibility
// make sure the rect is determined *before* calling super!
int ipp = currentIPPosition;
int bpp = currentBPPosition + ip.getOffset();
@@ -935,6 +961,7 @@
// warn if link trait found but not allowed, else create link
if (linkTraitFound) {
+ action.setStructurePointer(ptr); // used for accessibility
Link link = new Link(action, ipRect);
this.deferredLinks.add(link);
}
@@ -969,6 +996,8 @@
String fontName = getInternalFontNameForArea(text);
int size = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue();
+ String ptr = (String)text.getTrait(Trait.PTR); // used for accessibility
+ establishStructurePointer(ptr);
// This assumes that *all* CIDFonts use a /ToUnicode mapping
Typeface tf = getTypeface(fontName);
@@ -990,6 +1019,7 @@
textUtil.flush();
renderTextDecoration(tf, size, text, bl, rx);
+ resetStructurePointer();
}
/** {@inheritDoc} */
@@ -1060,10 +1090,10 @@
private static final int INITIAL_BUFFER_SIZE = 16;
private int[] dx = new int[INITIAL_BUFFER_SIZE];
private int lastDXPos = 0;
- private StringBuffer text = new StringBuffer();
+ private final StringBuffer text = new StringBuffer();
private int startx, starty;
private int tls, tws;
- private boolean combined = false;
+ private final boolean combined = false;
void addChar(char ch) {
text.append(ch);
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFSerializer.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFSerializer.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFSerializer.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/IFSerializer.java Tue Oct 27 19:07:52 2009
@@ -27,16 +27,19 @@
import java.awt.geom.AffineTransform;
import java.util.Iterator;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import org.w3c.dom.Document;
-
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import org.apache.xmlgraphics.util.QName;
import org.apache.xmlgraphics.util.XMLizable;
+import org.apache.fop.accessibility.StructureTree;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.render.PrintRendererConfigurator;
import org.apache.fop.render.RenderingContext;
@@ -60,6 +63,7 @@
implements IFConstants, IFPainter, IFDocumentNavigationHandler {
private IFDocumentHandler mimicHandler;
+ private int pageSequenceIndex; // used for accessibility
/** Holds the intermediate format state */
private IFState state;
@@ -210,8 +214,23 @@
if (id != null) {
atts.addAttribute(XML_NAMESPACE, "id", "xml:id", XMLUtil.CDATA, id);
}
+ Locale lang = getContext().getLanguage();
+ if (lang != null) {
+ atts.addAttribute(XML_NAMESPACE, "lang", "xml:lang", XMLUtil.CDATA,
+ XMLUtil.toRFC3066(lang));
+ }
addForeignAttributes(atts);
handler.startElement(EL_PAGE_SEQUENCE, atts);
+ if (this.getUserAgent().isAccessibilityEnabled()) {
+ StructureTree structureTree = getUserAgent().getStructureTree();
+ handler.startElement(EL_STRUCTURE_TREE); // add structure tree
+ NodeList nodes = structureTree.getPageSequence(pageSequenceIndex++);
+ for (int i = 0, n = nodes.getLength(); i < n; i++) {
+ Node node = nodes.item(i);
+ new DOM2SAX(handler).writeFragment(node);
+ }
+ handler.endElement(EL_STRUCTURE_TREE);
+ }
} catch (SAXException e) {
throw new IFException("SAX error in startPageSequence()", e);
}
@@ -392,13 +411,14 @@
addAttribute(atts, "width", Integer.toString(rect.width));
addAttribute(atts, "height", Integer.toString(rect.height));
addForeignAttributes(atts);
+ addStructurePointerAttribute(atts);
handler.element(EL_IMAGE, atts);
} catch (SAXException e) {
throw new IFException("SAX error in startGroup()", e);
}
}
- private void addForeignAttributes(AttributesImpl atts) {
+ private void addForeignAttributes(AttributesImpl atts) throws SAXException {
Map foreignAttributes = getContext().getForeignAttributes();
if (!foreignAttributes.isEmpty()) {
Iterator iter = foreignAttributes.entrySet().iterator();
@@ -418,6 +438,7 @@
addAttribute(atts, "width", Integer.toString(rect.width));
addAttribute(atts, "height", Integer.toString(rect.height));
addForeignAttributes(atts);
+ addStructurePointerAttribute(atts);
handler.startElement(EL_IMAGE, atts);
new DOM2SAX(handler).writeDocument(doc, true);
handler.endElement(EL_IMAGE);
@@ -531,6 +552,7 @@
if (dx != null) {
addAttribute(atts, "dx", IFUtil.toString(dx));
}
+ addStructurePointerAttribute(atts);
handler.startElement(EL_TEXT, atts);
char[] chars = text.toCharArray();
handler.characters(chars, 0, chars.length);
@@ -617,7 +639,8 @@
}
private void addAttribute(AttributesImpl atts,
- org.apache.xmlgraphics.util.QName attribute, String value) {
+ org.apache.xmlgraphics.util.QName attribute, String value) throws SAXException {
+ handler.startPrefixMapping(attribute.getPrefix(), attribute.getNamespaceURI());
XMLUtil.addAttribute(atts, attribute, value);
}
@@ -625,6 +648,13 @@
XMLUtil.addAttribute(atts, localName, value);
}
+ private void addStructurePointerAttribute(AttributesImpl atts) {
+ String ptr = getContext().getStructurePointer();
+ if (ptr != null) {
+ addAttribute(atts, "ptr", ptr);
+ }
+ }
+
// ---=== IFDocumentNavigationHandler ===---
private Map incompleteActions = new java.util.HashMap();
@@ -696,6 +726,9 @@
AttributesImpl atts = new AttributesImpl();
atts.addAttribute(null, "rect", "rect",
XMLConstants.CDATA, IFUtil.toString(link.getTargetRect()));
+ if (getUserAgent().isAccessibilityEnabled()) {
+ addAttribute(atts, "ptr", link.getAction().getStructurePointer());
+ }
try {
handler.startElement(DocumentNavigationExtensionConstants.LINK, atts);
serializeXMLizable(link.getAction());
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/extensions/AbstractAction.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/extensions/AbstractAction.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/extensions/AbstractAction.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/extensions/AbstractAction.java Tue Oct 27 19:07:52 2009
@@ -27,6 +27,7 @@
public abstract class AbstractAction implements XMLizable {
private String id;
+ private String structurePointer;
/**
* Sets an ID to make the action referencable.
@@ -45,6 +46,22 @@
}
/**
+ * Sets the structure element corresponding to this action.
+ * @param structurePointer a reference to the structure element
+ */
+ public void setStructurePointer(String structurePointer) {
+ this.structurePointer = structurePointer;
+ }
+
+ /**
+ * Returns the structure element corresponding to this action.
+ * @return the reference to the structure element
+ */
+ public String getStructurePointer() {
+ return structurePointer;
+ }
+
+ /**
* Indicates whether the action has an ID and is therefore referencable.
* @return true if the action has an ID
*/
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/extensions/DocumentNavigationHandler.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/extensions/DocumentNavigationHandler.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/extensions/DocumentNavigationHandler.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/intermediate/extensions/DocumentNavigationHandler.java Tue Oct 27 19:07:52 2009
@@ -48,6 +48,8 @@
private IFDocumentNavigationHandler navHandler;
+ private String structurePointer;
+
/**
* Main constructor.
* @param navHandler the navigation handler that will receive the events
@@ -96,6 +98,7 @@
throw new SAXException(localName + " must be the root element!");
}
Rectangle targetRect = XMLUtil.getAttributeAsRectangle(attributes, "rect");
+ structurePointer = attributes.getValue("ptr");
Link link = new Link(null, targetRect);
objectStack.push(link);
} else if (GOTO_XY.getLocalName().equals(localName)) {
@@ -118,6 +121,9 @@
}
action = new GoToXYAction(id, pageIndex, location);
}
+ if (structurePointer != null) {
+ action.setStructurePointer(structurePointer);
+ }
objectStack.push(action);
} else if (GOTO_URI.getLocalName().equals(localName)) {
String id = attributes.getValue("id");
@@ -128,6 +134,9 @@
if (id != null) {
action.setID(id);
}
+ if (structurePointer != null) {
+ action.setStructurePointer(structurePointer);
+ }
objectStack.push(action);
} else {
throw new SAXException(
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java Tue Oct 27 19:07:52 2009
@@ -56,6 +56,8 @@
/** Text generation utility holding the current font status */
protected PDFTextUtil textutil;
+ private boolean inMarkedContentSequence;
+ private boolean inArtifactMode;
/**
* Main constructor. Creates a new PDF stream and additional helper classes for text painting
@@ -153,6 +155,40 @@
currentStream.add("q\n");
}
+ /** {@inheritDoc} */
+ protected void saveGraphicsState(String structElemType, int sequenceNum) {
+ endTextObject();
+ currentState.save();
+ beginMarkedContentSequence(structElemType, sequenceNum);
+ currentStream.add("q\n");
+ }
+
+ /**
+ * Begins a new marked content sequence (BDC or BMC). If the parameter structElemType is null,
+ * the sequenceNum is ignored and instead of a BDC with the MCID as parameter, an "Artifact"
+ * and a BMC command is generated.
+ * @param structElemType Structure Element Type
+ * @param mcid Sequence number
+ */
+ protected void beginMarkedContentSequence(String structElemType, int mcid) {
+ assert !this.inMarkedContentSequence;
+ assert !this.inArtifactMode;
+ if (structElemType != null) {
+ currentStream.add(structElemType + " <</MCID " + String.valueOf(mcid) + ">>\n"
+ + "BDC\n");
+ } else {
+ currentStream.add("/Artifact\nBMC\n");
+ this.inArtifactMode = true;
+ }
+ this.inMarkedContentSequence = true;
+ }
+
+ void endMarkedContentSequence() {
+ currentStream.add("EMC\n");
+ this.inMarkedContentSequence = false;
+ this.inArtifactMode = false;
+ }
+
/**
* Restored the graphics state valid before the previous {@link #saveGraphicsState()}.
* @param popState true if the state should also be popped, false if only the PDF command
@@ -166,11 +202,42 @@
}
}
- /** {@inheritDoc} */
+ /**
+ * Same as {@link #restoreGraphicsState(boolean)}, with <code>true</code> as
+ * a parameter.
+ */
protected void restoreGraphicsState() {
restoreGraphicsState(true);
}
+ /**
+ * Same as {@link #restoreGraphicsState()}, additionally ending the current
+ * marked content sequence if any.
+ */
+ protected void restoreGraphicsStateAccess() {
+ endTextObject();
+ currentStream.add("Q\n");
+ if (this.inMarkedContentSequence) {
+ endMarkedContentSequence();
+ }
+ currentState.restore();
+ }
+
+ /**
+ * Separates 2 text elements, ending the current marked content sequence and
+ * starting a new one.
+ *
+ * @param structElemType structure element type
+ * @param mcid sequence number
+ * @see #beginMarkedContentSequence(String, int)
+ */
+ protected void separateTextElements(String structElemType, int mcid) {
+ textutil.endTextObject();
+ endMarkedContentSequence();
+ beginMarkedContentSequence(structElemType, mcid);
+ textutil.beginTextObject();
+ }
+
/** Indicates the beginning of a text object. */
protected void beginTextObject() {
if (!textutil.isInTextObject()) {
@@ -178,9 +245,27 @@
}
}
+ /**
+ * Indicates the beginning of a marked-content text object.
+ *
+ * @param structElemType structure element type
+ * @param mcid sequence number
+ * @see #beginTextObject()
+ * @see #beginMarkedContentSequence(String, int)
+ */
+ protected void beginTextObject(String structElemType, int mcid) {
+ if (!textutil.isInTextObject()) {
+ beginMarkedContentSequence(structElemType, mcid);
+ textutil.beginTextObject();
+ }
+ }
+
/** Indicates the end of a text object. */
protected void endTextObject() {
if (textutil.isInTextObject()) {
+ if (this.inMarkedContentSequence) {
+ endMarkedContentSequence();
+ }
textutil.endTextObject();
}
}
@@ -326,5 +411,28 @@
restoreGraphicsState();
}
+ /**
+ * Places a previously registered image at a certain place on the page,
+ * bracketing it as a marked-content sequence.
+ *
+ * @param x X coordinate
+ * @param y Y coordinate
+ * @param w width for image
+ * @param h height for image
+ * @param xobj the image XObject
+ * @param structElemType structure element type
+ * @param mcid sequence number
+ * @see #beginMarkedContentSequence(String, int)
+ */
+ public void placeImage(float x, float y, float w, float h, PDFXObject xobj,
+ String structElemType, int mcid) {
+ saveGraphicsState(structElemType, mcid);
+ add(format(w) + " 0 0 "
+ + format(-h) + " "
+ + format(x) + " "
+ + format(y + h)
+ + " cm\n" + xobj.getName() + " Do\n");
+ restoreGraphicsStateAccess();
+ }
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFDocumentHandler.java Tue Oct 27 19:07:52 2009
@@ -28,6 +28,8 @@
import java.io.IOException;
import java.util.Map;
+import org.w3c.dom.NodeList;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -50,6 +52,7 @@
import org.apache.fop.render.intermediate.IFDocumentNavigationHandler;
import org.apache.fop.render.intermediate.IFException;
import org.apache.fop.render.intermediate.IFPainter;
+import org.apache.fop.util.XMLUtil;
/**
* {@link IFDocumentHandler} implementation that produces PDF.
@@ -59,6 +62,12 @@
/** logging instance */
private static Log log = LogFactory.getLog(PDFDocumentHandler.class);
+ private int pageSequenceIndex;
+
+ private boolean accessEnabled;
+
+ private PDFLogicalStructureHandler logicalStructureHandler;
+
/** the PDF Document being created */
protected PDFDocument pdfDoc;
@@ -86,7 +95,7 @@
/** Used for bookmarks/outlines. */
protected Map pageReferences = new java.util.HashMap();
- private PDFDocumentNavigationHandler documentNavigationHandler
+ private final PDFDocumentNavigationHandler documentNavigationHandler
= new PDFDocumentNavigationHandler(this);
/**
@@ -97,7 +106,7 @@
/** {@inheritDoc} */
public boolean supportsPagesOutOfOrder() {
- return true;
+ return !accessEnabled;
}
/** {@inheritDoc} */
@@ -125,11 +134,20 @@
return this.pdfUtil;
}
+ PDFLogicalStructureHandler getLogicalStructureHandler() {
+ return logicalStructureHandler;
+ }
+
/** {@inheritDoc} */
public void startDocument() throws IFException {
super.startDocument();
try {
this.pdfDoc = pdfUtil.setupPDFDocument(this.outputStream);
+ this.accessEnabled = getUserAgent().isAccessibilityEnabled();
+ if (accessEnabled) {
+ pdfDoc.getRoot().makeTagged();
+ logicalStructureHandler = new PDFLogicalStructureHandler(pdfDoc);
+ }
} catch (IOException e) {
throw new IFException("I/O error in startDocument()", e);
}
@@ -145,7 +163,6 @@
try {
pdfDoc.getResources().addFonts(pdfDoc, fontInfo);
pdfDoc.outputTrailer(this.outputStream);
-
this.pdfDoc = null;
pdfResources = null;
@@ -160,7 +177,18 @@
/** {@inheritDoc} */
public void startPageSequence(String id) throws IFException {
- //TODO page sequence title, country and language
+ //TODO page sequence title
+
+ if (this.pdfDoc.getRoot().getLanguage() == null
+ && getContext().getLanguage() != null) {
+ //No document-level language set, so we use the first page-sequence's language
+ this.pdfDoc.getRoot().setLanguage(XMLUtil.toRFC3066(getContext().getLanguage()));
+ }
+
+ if (accessEnabled) {
+ NodeList nodes = getUserAgent().getStructureTree().getPageSequence(pageSequenceIndex++);
+ logicalStructureHandler.processStructureTree(nodes, getContext().getLanguage());
+ }
}
/** {@inheritDoc} */
@@ -198,13 +226,17 @@
toPointAndScale(cropBox, scaleX, scaleY),
toPointAndScale(bleedBox, scaleX, scaleY),
toPointAndScale(trimBox, scaleX, scaleY));
+ if (accessEnabled) {
+ logicalStructureHandler.startPage(currentPage);
+ }
pdfUtil.generatePageLabel(index, name);
currentPageRef = new PageReference(currentPage, size);
this.pageReferences.put(new Integer(index), currentPageRef);
- this.generator = new PDFContentGenerator(this.pdfDoc, this.outputStream, this.currentPage);
+ this.generator = new PDFContentGenerator(this.pdfDoc, this.outputStream,
+ this.currentPage);
// Transform the PDF's default coordinate system (0,0 at lower left) to the PDFPainter's
AffineTransform basicPageTransform = new AffineTransform(1, 0, 0, -1, 0,
(scaleY * size.height) / 1000f);
@@ -221,7 +253,7 @@
/** {@inheritDoc} */
public IFPainter startPageContent() throws IFException {
- return new PDFPainter(this);
+ return new PDFPainter(this, logicalStructureHandler);
}
/** {@inheritDoc} */
@@ -231,6 +263,9 @@
/** {@inheritDoc} */
public void endPage() throws IFException {
+ if (accessEnabled) {
+ logicalStructureHandler.endPage();
+ }
try {
this.documentNavigationHandler.commit();
this.pdfDoc.registerObject(generator.getStream());
@@ -267,8 +302,8 @@
static final class PageReference {
- private PDFReference pageRef;
- private Dimension pageDimension;
+ private final PDFReference pageRef;
+ private final Dimension pageDimension;
private PageReference(PDFPage page, Dimension dim) {
this.pageRef = page.makeReference();
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFDocumentNavigationHandler.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFDocumentNavigationHandler.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFDocumentNavigationHandler.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFDocumentNavigationHandler.java Tue Oct 27 19:07:52 2009
@@ -47,10 +47,10 @@
*/
public class PDFDocumentNavigationHandler implements IFDocumentNavigationHandler {
- private PDFDocumentHandler documentHandler;
+ private final PDFDocumentHandler documentHandler;
- private Map incompleteActions = new java.util.HashMap();
- private Map completeActions = new java.util.HashMap();
+ private final Map incompleteActions = new java.util.HashMap();
+ private final Map completeActions = new java.util.HashMap();
/**
* Default constructor.
@@ -111,6 +111,11 @@
PDFLink pdfLink = getPDFDoc().getFactory().makeLink(
targetRect2D, pdfAction);
if (pdfLink != null) {
+ String ptr = link.getAction().getStructurePointer();
+ if (documentHandler.getUserAgent().isAccessibilityEnabled()
+ && ptr != null && ptr.length() > 0) {
+ documentHandler.getLogicalStructureHandler().addLinkContentItem(pdfLink, ptr);
+ }
documentHandler.currentPage.addAnnotation(pdfLink);
}
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFImageHandlerGraphics2D.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFImageHandlerGraphics2D.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFImageHandlerGraphics2D.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFImageHandlerGraphics2D.java Tue Oct 27 19:07:52 2009
@@ -35,6 +35,7 @@
import org.apache.fop.render.AbstractImageHandlerGraphics2D;
import org.apache.fop.render.RendererContext;
import org.apache.fop.render.RenderingContext;
+import org.apache.fop.render.pdf.PDFLogicalStructureHandler.MarkedContentInfo;
import org.apache.fop.svg.PDFGraphics2D;
/**
@@ -63,6 +64,9 @@
renderer.currentPage,
renderer.getFontInfo());
Rectangle effPos = new Rectangle(origin.x + pos.x, origin.y + pos.y, pos.width, pos.height);
+ if (context.getUserAgent().isAccessibilityEnabled()) {
+ pdfContext.setMarkedContentInfo(renderer.addCurrentImageToStructureTree());
+ }
handleImage(pdfContext, image, effPos);
return null;
}
@@ -87,7 +91,13 @@
float sy = fheight / (float)imh;
generator.comment("G2D start");
- generator.saveGraphicsState();
+ boolean accessibilityEnabled = context.getUserAgent().isAccessibilityEnabled();
+ if (accessibilityEnabled) {
+ MarkedContentInfo mci = pdfContext.getMarkedContentInfo();
+ generator.saveGraphicsState(mci.tag, mci.mcid);
+ } else {
+ generator.saveGraphicsState();
+ }
generator.updateColor(Color.black, false, null);
generator.updateColor(Color.black, true, null);
@@ -115,7 +125,11 @@
imageG2D.getGraphics2DImagePainter().paint(graphics, area);
generator.add(graphics.getString());
- generator.restoreGraphicsState();
+ if (accessibilityEnabled) {
+ generator.restoreGraphicsStateAccess();
+ } else {
+ generator.restoreGraphicsState();
+ }
generator.comment("G2D end");
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFImageHandlerRawJPEG.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFImageHandlerRawJPEG.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFImageHandlerRawJPEG.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFImageHandlerRawJPEG.java Tue Oct 27 19:07:52 2009
@@ -34,6 +34,7 @@
import org.apache.fop.render.ImageHandler;
import org.apache.fop.render.RendererContext;
import org.apache.fop.render.RenderingContext;
+import org.apache.fop.render.pdf.PDFLogicalStructureHandler.MarkedContentInfo;
/**
* Image handler implementation which handles raw JPEG images for PDF output.
@@ -82,7 +83,12 @@
float y = (float)pos.getY() / 1000f;
float w = (float)pos.getWidth() / 1000f;
float h = (float)pos.getHeight() / 1000f;
- generator.placeImage(x, y, w, h, xobj);
+ if (context.getUserAgent().isAccessibilityEnabled()) {
+ MarkedContentInfo mci = pdfContext.getMarkedContentInfo();
+ generator.placeImage(x, y, w, h, xobj, mci.tag, mci.mcid);
+ } else {
+ generator.placeImage(x, y, w, h, xobj);
+ }
}
/** {@inheritDoc} */
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFImageHandlerRenderedImage.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFImageHandlerRenderedImage.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFImageHandlerRenderedImage.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFImageHandlerRenderedImage.java Tue Oct 27 19:07:52 2009
@@ -34,6 +34,7 @@
import org.apache.fop.render.ImageHandler;
import org.apache.fop.render.RendererContext;
import org.apache.fop.render.RenderingContext;
+import org.apache.fop.render.pdf.PDFLogicalStructureHandler.MarkedContentInfo;
/**
* Image handler implementation which handles RenderedImage instances for PDF output.
@@ -83,7 +84,12 @@
float y = (float)pos.getY() / 1000f;
float w = (float)pos.getWidth() / 1000f;
float h = (float)pos.getHeight() / 1000f;
- generator.placeImage(x, y, w, h, xobj);
+ if (context.getUserAgent().isAccessibilityEnabled()) {
+ MarkedContentInfo mci = pdfContext.getMarkedContentInfo();
+ generator.placeImage(x, y, w, h, xobj, mci.tag, mci.mcid);
+ } else {
+ generator.placeImage(x, y, w, h, xobj);
+ }
}
/** {@inheritDoc} */
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java Tue Oct 27 19:07:52 2009
@@ -40,6 +40,7 @@
import org.apache.fop.image.loader.batik.BatikImageFlavors;
import org.apache.fop.render.ImageHandler;
import org.apache.fop.render.RenderingContext;
+import org.apache.fop.render.pdf.PDFLogicalStructureHandler.MarkedContentInfo;
import org.apache.fop.svg.PDFAElementBridge;
import org.apache.fop.svg.PDFBridgeContext;
import org.apache.fop.svg.PDFGraphics2D;
@@ -101,8 +102,8 @@
float w = (float)ctx.getDocumentSize().getWidth() * 1000f;
float h = (float)ctx.getDocumentSize().getHeight() * 1000f;
- float sx = pos.width / (float)w;
- float sy = pos.height / (float)h;
+ float sx = pos.width / w;
+ float sy = pos.height / h;
//Scaling and translation for the bounding box of the image
AffineTransform scaling = new AffineTransform(
@@ -121,6 +122,10 @@
*/
generator.comment("SVG setup");
generator.saveGraphicsState();
+ if (context.getUserAgent().isAccessibilityEnabled()) {
+ MarkedContentInfo mci = pdfContext.getMarkedContentInfo();
+ generator.beginMarkedContentSequence(mci.tag, mci.mcid);
+ }
generator.setColor(Color.black, false);
generator.setColor(Color.black, true);
@@ -168,7 +173,11 @@
eventProducer.svgRenderingError(this, e, image.getInfo().getOriginalURI());
}
generator.getState().restore();
- generator.restoreGraphicsState();
+ if (context.getUserAgent().isAccessibilityEnabled()) {
+ generator.restoreGraphicsStateAccess();
+ } else {
+ generator.restoreGraphicsState();
+ }
generator.comment("SVG end");
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFPainter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFPainter.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFPainter.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFPainter.java Tue Oct 27 19:07:52 2009
@@ -29,9 +29,6 @@
import org.w3c.dom.Document;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontTriplet;
@@ -47,6 +44,7 @@
import org.apache.fop.render.intermediate.IFContext;
import org.apache.fop.render.intermediate.IFException;
import org.apache.fop.render.intermediate.IFState;
+import org.apache.fop.render.pdf.PDFLogicalStructureHandler.MarkedContentInfo;
import org.apache.fop.traits.BorderProps;
import org.apache.fop.traits.RuleStyle;
import org.apache.fop.util.CharUtilities;
@@ -56,26 +54,33 @@
*/
public class PDFPainter extends AbstractIFPainter {
- /** logging instance */
- private static Log log = LogFactory.getLog(PDFPainter.class);
-
- private PDFDocumentHandler documentHandler;
+ private final PDFDocumentHandler documentHandler;
/** The current content generator */
protected PDFContentGenerator generator;
- private PDFBorderPainter borderPainter;
+ private final PDFBorderPainter borderPainter;
+
+ private boolean accessEnabled;
+
+ private MarkedContentInfo imageMCI;
+
+ private PDFLogicalStructureHandler logicalStructureHandler;
/**
* Default constructor.
* @param documentHandler the parent document handler
+ * @param logicalStructureHandler the logical structure handler
*/
- public PDFPainter(PDFDocumentHandler documentHandler) {
+ public PDFPainter(PDFDocumentHandler documentHandler,
+ PDFLogicalStructureHandler logicalStructureHandler) {
super();
this.documentHandler = documentHandler;
+ this.logicalStructureHandler = logicalStructureHandler;
this.generator = documentHandler.generator;
this.borderPainter = new PDFBorderPainter(this.generator);
this.state = IFState.create();
+ accessEnabled = this.getUserAgent().isAccessibilityEnabled();
}
/** {@inheritDoc} */
@@ -122,22 +127,36 @@
}
/** {@inheritDoc} */
- public void drawImage(String uri, Rectangle rect) throws IFException {
+ public void drawImage(String uri, Rectangle rect)
+ throws IFException {
PDFXObject xobject = getPDFDoc().getXObject(uri);
if (xobject != null) {
- placeImage(rect, xobject);
- return;
+ if (accessEnabled) {
+ String ptr = getContext().getStructurePointer();
+ prepareImageMCID(ptr);
+ placeImageAccess(rect, xobject);
+ } else {
+ placeImage(rect, xobject);
+ }
+ } else {
+ if (accessEnabled) {
+ String ptr = getContext().getStructurePointer();
+ prepareImageMCID(ptr);
+ }
+ drawImageUsingURI(uri, rect);
+ flushPDFDoc();
}
+ }
- drawImageUsingURI(uri, rect);
-
- flushPDFDoc();
+ private void prepareImageMCID(String ptr) {
+ imageMCI = logicalStructureHandler.addImageContentItem(ptr);
}
/** {@inheritDoc} */
protected RenderingContext createRenderingContext() {
PDFRenderingContext pdfContext = new PDFRenderingContext(
getUserAgent(), generator, this.documentHandler.currentPage, getFontInfo());
+ pdfContext.setMarkedContentInfo(imageMCI);
return pdfContext;
}
@@ -158,11 +177,31 @@
+ " cm " + xobj.getName() + " Do\n");
generator.restoreGraphicsState();
}
+ /**
+ * Places a previously registered image at a certain place on the page - Accessibility version
+ * @param x X coordinate
+ * @param y Y coordinate
+ * @param w width for image
+ * @param h height for image
+ * @param xobj the image XObject
+ */
+ private void placeImageAccess(Rectangle rect, PDFXObject xobj) {
+ generator.saveGraphicsState(imageMCI.tag, imageMCI.mcid);
+ generator.add(format(rect.width) + " 0 0 "
+ + format(-rect.height) + " "
+ + format(rect.x) + " "
+ + format(rect.y + rect.height )
+ + " cm " + xobj.getName() + " Do\n");
+ generator.restoreGraphicsStateAccess();
+ }
/** {@inheritDoc} */
public void drawImage(Document doc, Rectangle rect) throws IFException {
+ if (accessEnabled) {
+ String ptr = getContext().getStructurePointer();
+ prepareImageMCID(ptr);
+ }
drawImageUsingDocument(doc, rect);
-
flushPDFDoc();
}
@@ -253,10 +292,22 @@
}
/** {@inheritDoc} */
- public void drawText(int x, int y, int letterSpacing, int wordSpacing, int[] dx, String text)
+ public void drawText(int x, int y, int letterSpacing, int wordSpacing, int[] dx,
+ String text)
throws IFException {
- generator.updateColor(state.getTextColor(), true, null);
- generator.beginTextObject();
+ if (accessEnabled) {
+ String ptr = getContext().getStructurePointer();
+ MarkedContentInfo mci = logicalStructureHandler.addTextContentItem(ptr);
+ if (generator.getTextUtil().isInTextObject()) {
+ generator.separateTextElements(mci.tag, mci.mcid);
+ }
+ generator.updateColor(state.getTextColor(), true, null);
+ generator.beginTextObject(mci.tag, mci.mcid);
+ } else {
+ generator.updateColor(state.getTextColor(), true, null);
+ generator.beginTextObject();
+ }
+
FontTriplet triplet = new FontTriplet(
state.getFontFamily(), state.getFontStyle(), state.getFontWeight());
//TODO Ignored: state.getFontVariant()
@@ -277,7 +328,7 @@
PDFTextUtil textutil = generator.getTextUtil();
textutil.updateTf(fontKey, fontSize, tf.isMultiByte());
- generator.updateCharacterSpacing((float)letterSpacing / 1000f);
+ generator.updateCharacterSpacing(letterSpacing / 1000f);
textutil.writeTextMatrix(new AffineTransform(1, 0, 0, -1, x / 1000f, y / 1000f));
int l = text.length();
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderer.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderer.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderer.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderer.java Tue Oct 27 19:07:52 2009
@@ -31,8 +31,12 @@
import java.io.OutputStream;
import java.util.Iterator;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+
import org.apache.xmlgraphics.image.loader.ImageException;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.ImageInfo;
@@ -61,6 +65,7 @@
import org.apache.fop.area.inline.Leader;
import org.apache.fop.area.inline.SpaceArea;
import org.apache.fop.area.inline.TextArea;
+import org.apache.fop.area.inline.Viewport;
import org.apache.fop.area.inline.WordArea;
import org.apache.fop.datatypes.URISpecification;
import org.apache.fop.events.ResourceEventProducer;
@@ -91,9 +96,11 @@
import org.apache.fop.render.AbstractPathOrientedRenderer;
import org.apache.fop.render.Graphics2DAdapter;
import org.apache.fop.render.RendererContext;
+import org.apache.fop.render.pdf.PDFLogicalStructureHandler.MarkedContentInfo;
import org.apache.fop.traits.RuleStyle;
import org.apache.fop.util.AbstractPaintingState;
import org.apache.fop.util.CharUtilities;
+import org.apache.fop.util.XMLUtil;
import org.apache.fop.util.AbstractPaintingState.AbstractData;
/**
@@ -127,7 +134,7 @@
* this is used for prepared pages that cannot be immediately
* rendered
*/
- protected Map pages = null;
+ private Map pages;
/**
* Maps unique PageViewport key to PDF page reference
@@ -193,6 +200,14 @@
/** Image handler registry */
private final PDFImageHandlerRegistry imageHandlerRegistry = new PDFImageHandlerRegistry();
+ private boolean accessEnabled;
+
+ private PDFLogicalStructureHandler logicalStructureHandler;
+
+ private int pageSequenceIndex;
+
+ /** Reference in the structure tree to the image being rendered. */
+ private String imageReference;
/**
* create the PDF renderer
@@ -204,6 +219,7 @@
public void setUserAgent(FOUserAgent agent) {
super.setUserAgent(agent);
this.pdfUtil = new PDFRenderingUtil(getUserAgent());
+ accessEnabled = agent.isAccessibilityEnabled();
}
PDFRenderingUtil getPDFUtil() {
@@ -225,6 +241,10 @@
}
ostream = stream;
this.pdfDoc = pdfUtil.setupPDFDocument(stream);
+ if (accessEnabled) {
+ pdfDoc.getRoot().makeTagged();
+ logicalStructureHandler = new PDFLogicalStructureHandler(pdfDoc);
+ }
}
/**
@@ -274,8 +294,7 @@
* {@inheritDoc}
*/
public boolean supportsOutOfOrder() {
- //return false;
- return true;
+ return !accessEnabled;
}
/**
@@ -394,17 +413,24 @@
info.setTitle(str);
}
}
+ Locale language = null;
if (pageSequence.getLanguage() != null) {
String lang = pageSequence.getLanguage();
String country = pageSequence.getCountry();
- String langCode = lang + (country != null ? "-" + country : "");
+ if (lang != null) {
+ language = (country == null) ? new Locale(lang) : new Locale(lang, country);
+ }
if (pdfDoc.getRoot().getLanguage() == null) {
//Only set if not set already (first non-null is used)
//Note: No checking is performed whether the values are valid!
- pdfDoc.getRoot().setLanguage(langCode);
+ pdfDoc.getRoot().setLanguage(XMLUtil.toRFC3066(language));
}
}
pdfUtil.generateDefaultXMPMetadata();
+ if (accessEnabled) {
+ NodeList nodes = getUserAgent().getStructureTree().getPageSequence(pageSequenceIndex++);
+ logicalStructureHandler.processStructureTree(nodes, language);
+ }
}
/**
@@ -457,6 +483,10 @@
}
currentPageRef = currentPage.referencePDF();
+ if (accessEnabled) {
+ logicalStructureHandler.startPage(currentPage);
+ }
+
Rectangle bounds = page.getViewArea();
pageHeight = bounds.height;
@@ -474,6 +504,10 @@
super.renderPage(page);
+ if (accessEnabled) {
+ logicalStructureHandler.endPage();
+ }
+
this.pdfDoc.registerObject(generator.getStream());
currentPage.setContents(generator.getStream());
PDFAnnotList annots = currentPage.getAnnotations();
@@ -903,11 +937,22 @@
+ pdfDoc.getProfile());
} else if (action != null) {
PDFLink pdfLink = factory.makeLink(ipRect, action);
+ if (accessEnabled) {
+ String ptr = (String) ip.getTrait(Trait.PTR);
+ logicalStructureHandler.addLinkContentItem(pdfLink, ptr);
+ }
currentPage.addAnnotation(pdfLink);
}
}
}
+ /** {@inheritDoc} */
+ public void renderViewport(Viewport viewport) {
+ imageReference = (String) viewport.getTrait(Trait.PTR);
+ super.renderViewport(viewport);
+ imageReference = null;
+ }
+
private Typeface getTypeface(String fontName) {
Typeface tf = (Typeface) fontInfo.getFonts().get(fontName);
if (tf instanceof LazyFont) {
@@ -922,7 +967,16 @@
Color ct = (Color) text.getTrait(Trait.COLOR);
updateColor(ct, true);
- beginTextObject();
+ if (accessEnabled) {
+ String ptr = (String) text.getTrait(Trait.PTR);
+ MarkedContentInfo mci = logicalStructureHandler.addTextContentItem(ptr);
+ if (generator.getTextUtil().isInTextObject()) {
+ generator.separateTextElements(mci.tag, mci.mcid);
+ }
+ generator.beginTextObject(mci.tag, mci.mcid);
+ } else {
+ beginTextObject();
+ }
String fontName = getInternalFontNameForArea(text);
int size = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue();
@@ -1178,13 +1232,22 @@
* @param xobj the image XObject
*/
public void placeImage(float x, float y, float w, float h, PDFXObject xobj) {
- saveGraphicsState();
+ if (accessEnabled) {
+ MarkedContentInfo mci = logicalStructureHandler.addImageContentItem(imageReference);
+ generator.saveGraphicsState(mci.tag, mci.mcid);
+ } else {
+ saveGraphicsState();
+ }
generator.add(format(w) + " 0 0 "
+ format(-h) + " "
+ format(currentIPPosition / 1000f + x) + " "
+ format(currentBPPosition / 1000f + h + y)
+ " cm\n" + xobj.getName() + " Do\n");
- restoreGraphicsState();
+ if (accessEnabled) {
+ generator.restoreGraphicsStateAccess();
+ } else {
+ restoreGraphicsState();
+ }
}
/** {@inheritDoc} */
@@ -1205,6 +1268,18 @@
return context;
}
+ /** {@inheritDoc} */
+ public void renderDocument(Document doc, String ns, Rectangle2D pos, Map foreignAttributes) {
+ if (accessEnabled) {
+ MarkedContentInfo mci = logicalStructureHandler.addImageContentItem(imageReference);
+ generator.beginMarkedContentSequence(mci.tag, mci.mcid);
+ }
+ super.renderDocument(doc, ns, pos, foreignAttributes);
+ if (accessEnabled) {
+ generator.endMarkedContentSequence();
+ }
+ }
+
/**
* Render leader area.
* This renders a leader area which is an area with a rule.
@@ -1272,5 +1347,9 @@
public void setEncryptionParams(PDFEncryptionParams encryptionParams) {
this.pdfUtil.setEncryptionParams(encryptionParams);
}
+
+ MarkedContentInfo addCurrentImageToStructureTree() {
+ return logicalStructureHandler.addImageContentItem(imageReference);
+ }
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderingContext.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderingContext.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderingContext.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderingContext.java Tue Oct 27 19:07:52 2009
@@ -25,6 +25,7 @@
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.pdf.PDFPage;
import org.apache.fop.render.AbstractRenderingContext;
+import org.apache.fop.render.pdf.PDFLogicalStructureHandler.MarkedContentInfo;
/**
* Rendering context for PDF production.
@@ -34,6 +35,7 @@
private PDFContentGenerator generator;
private FontInfo fontInfo;
private PDFPage page;
+ private MarkedContentInfo mci;
/**
* Main constructor.
@@ -79,4 +81,11 @@
return this.fontInfo;
}
+ void setMarkedContentInfo(MarkedContentInfo mci) {
+ this.mci = mci;
+ }
+
+ MarkedContentInfo getMarkedContentInfo() {
+ return mci;
+ }
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderingUtil.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderingUtil.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderingUtil.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderingUtil.java Tue Oct 27 19:07:52 2009
@@ -37,6 +37,7 @@
import org.apache.xmlgraphics.xmp.schemas.XMPBasicAdapter;
import org.apache.xmlgraphics.xmp.schemas.XMPBasicSchema;
+import org.apache.fop.accessibility.Accessibility;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.fo.extensions.xmp.XMPMetadata;
import org.apache.fop.pdf.PDFAMode;
@@ -109,7 +110,7 @@
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 @@
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(Accessibility.ACCESSIBILITY, Boolean.TRUE);
+ }
s = (String)userAgent.getRendererOptions().get(PDF_X_MODE);
if (s != null) {
this.pdfXMode = PDFXMode.valueOf(s);
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/txt/TXTRenderer.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/txt/TXTRenderer.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/txt/TXTRenderer.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/txt/TXTRenderer.java Tue Oct 27 19:07:52 2009
@@ -28,6 +28,8 @@
import java.util.List;
import java.util.Map;
+import org.apache.xmlgraphics.util.UnitConv;
+
import org.apache.fop.apps.FOPException;
import org.apache.fop.area.Area;
import org.apache.fop.area.CTM;
@@ -37,7 +39,6 @@
import org.apache.fop.render.AbstractPathOrientedRenderer;
import org.apache.fop.render.txt.border.AbstractBorderElement;
import org.apache.fop.render.txt.border.BorderManager;
-import org.apache.xmlgraphics.util.UnitConv;
/**
* Renderer that renders areas to plain text.
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/xml/XMLRenderer.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/xml/XMLRenderer.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/xml/XMLRenderer.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/xml/XMLRenderer.java Tue Oct 27 19:07:52 2009
@@ -34,7 +34,8 @@
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
-
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.apache.xmlgraphics.util.QName;
@@ -86,6 +87,7 @@
import org.apache.fop.render.RendererContext;
import org.apache.fop.render.XMLHandler;
import org.apache.fop.util.ColorUtil;
+import org.apache.fop.util.DOM2SAX;
/**
* Renderer that renders areas to XML for debugging purposes.
@@ -105,6 +107,8 @@
/** If not null, the XMLRenderer will mimic another renderer by using its font setup. */
protected Renderer mimic;
+ private int pageSequenceIndex;
+
/**
* Creates a new XML renderer.
*/
@@ -440,6 +444,20 @@
}
transferForeignObjects(pageSequence);
startElement("pageSequence", atts);
+ if (this.getUserAgent().isAccessibilityEnabled()) {
+ String structureTreeElement = "structureTree";
+ startElement(structureTreeElement);
+ NodeList nodes = getUserAgent().getStructureTree().getPageSequence(pageSequenceIndex++);
+ for (int i = 0, n = nodes.getLength(); i < n; i++) {
+ Node node = nodes.item(i);
+ try {
+ new DOM2SAX(handler).writeFragment(node);
+ } catch (SAXException e) {
+ handleSAXException(e);
+ }
+ }
+ endElement(structureTreeElement);
+ }
handleExtensionAttachments(pageSequence.getExtensionAttachments());
LineArea seqTitle = pageSequence.getTitle();
if (seqTitle != null) {
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/util/DOM2SAX.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/util/DOM2SAX.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/util/DOM2SAX.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/util/DOM2SAX.java Tue Oct 27 19:07:52 2009
@@ -26,7 +26,6 @@
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
-
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;
@@ -79,6 +78,15 @@
}
/**
+ * Writes the given fragment using the given ContentHandler.
+ * @param node DOM node
+ * @throws SAXException In case of a problem while writing XML
+ */
+ public void writeFragment(Node node) throws SAXException {
+ writeNode(node);
+ }
+
+ /**
* Begin the scope of namespace prefix. Forward the event to the SAX handler
* only if the prefix is unknown or it is mapped to a different URI.
*/
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/util/XMLUtil.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/util/XMLUtil.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/util/XMLUtil.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/util/XMLUtil.java Tue Oct 27 19:07:52 2009
@@ -21,6 +21,7 @@
import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;
+import java.util.Locale;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
@@ -170,4 +171,39 @@
atts.addAttribute("", localName, localName, XMLUtil.CDATA, value);
}
+ /**
+ * Converts a {@link Locale} instance to an RFC 3066 compliant language identifier.
+ * @param language the language
+ * @return the formatted language identifier
+ */
+ public static String toRFC3066(Locale language) {
+ if (language == null || language.getLanguage().length() == 0) {
+ return null;
+ }
+ StringBuffer sb = new StringBuffer();
+ sb.append(language.getLanguage());
+ if (language.getCountry().length() > 0) {
+ sb.append('-');
+ sb.append(language.getCountry());
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Converts an RFC 3066 compliant language identifier to a {@link Locale} instance.
+ * @param lang the language string
+ * @return the converted locale instance
+ */
+ public static Locale convertRFC3066ToLocale(String lang) {
+ if (lang == null || lang.length() == 0) {
+ return null;
+ }
+ String[] parts = lang.split("-");
+ if (parts.length == 1) {
+ return new Locale(parts[0]);
+ } else {
+ return new Locale(parts[0], parts[1]);
+ }
+ }
+
}
Modified: xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/svg/SVGPainter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/svg/SVGPainter.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/svg/SVGPainter.java (original)
+++ xmlgraphics/fop/trunk/src/sandbox/org/apache/fop/render/svg/SVGPainter.java Tue Oct 27 19:07:52 2009
@@ -324,8 +324,9 @@
}
/** {@inheritDoc} */
- public void drawText(int x, int y, int letterSpacing, int wordSpacing, int[] dx, String text)
- throws IFException {
+
+ public void drawText(int x, int y, int letterSpacing, int wordSpacing, int[] dx,
+ String text) throws IFException {
try {
establish(MODE_TEXT);
AttributesImpl atts = new AttributesImpl();
Modified: xmlgraphics/fop/trunk/status.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/status.xml?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/status.xml (original)
+++ xmlgraphics/fop/trunk/status.xml Tue Oct 27 19:07:52 2009
@@ -58,6 +58,9 @@
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="JM,VH" type="add" fixes-bug="46705" due-to="Jost Klopfstein">
+ Added basic accessibility and Tagged PDF support.
+ </action>
<action context="Code" dev="JM" type="add">
Added support for encoding CMYK bitmap images (IOCA FS45) and TIFF images as embedded objects.
</action>
Modified: xmlgraphics/fop/trunk/test/java/org/apache/fop/render/pdf/PDFAConformanceTestCase.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/java/org/apache/fop/render/pdf/PDFAConformanceTestCase.java?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/test/java/org/apache/fop/render/pdf/PDFAConformanceTestCase.java (original)
+++ xmlgraphics/fop/trunk/test/java/org/apache/fop/render/pdf/PDFAConformanceTestCase.java Tue Oct 27 19:07:52 2009
@@ -99,7 +99,8 @@
foFile = new File(foBaseDir, "with-cmyk-images.fo");
try {
convertFO(foFile, getUserAgent(), dumpPDF);
- fail("Expected PDFConformanceException. PDF/A-1 does not allow PostScript XObjects.");
+ fail("Expected PDFConformanceException."
+ + " PDF/A-1 does not allow mixing DeviceRGB and DeviceCMYK.");
} catch (PDFConformanceException e) {
//Good!
}
Modified: xmlgraphics/fop/trunk/test/layoutengine/standard-testcases/foreign-attributes.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/layoutengine/standard-testcases/foreign-attributes.xml?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/test/layoutengine/standard-testcases/foreign-attributes.xml (original)
+++ xmlgraphics/fop/trunk/test/layoutengine/standard-testcases/foreign-attributes.xml Tue Oct 27 19:07:52 2009
@@ -31,9 +31,6 @@
</fo:layout-master-set>
<fo:page-sequence master-reference="normal">
<fo:flow flow-name="xsl-region-body">
- <fo:block id="eg">
- <fo:external-graphic src="../../resources/images/bgimg300dpi.jpg" fox:alt="description"/>
- </fo:block>
<fo:block id="bl">
<fo:basic-link external-destination="url(http://xmlgraphics.apache.org/fop/)" fox:blah="fop">FOP</fo:basic-link>
</fo:block>
@@ -43,7 +40,6 @@
</fo>
<checks xmlns:fox="http://xmlgraphics.apache.org/fop/extensions">
<eval expected="bar" xpath="//pageViewport[1]/@fox:foo"/>
- <eval expected="description" xpath="//block[@prod-id='eg']//image/@fox:alt"/>
<!--eval expected="fop" xpath="//block[@prod-id='bl']/inlineparent/@fox:blah"/> NYI -->
</checks>
</testcase>
Modified: xmlgraphics/fop/trunk/test/layoutengine/standard-testcases/page-sequence_language.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/layoutengine/standard-testcases/page-sequence_language.xml?rev=830293&r1=830292&r2=830293&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/test/layoutengine/standard-testcases/page-sequence_language.xml (original)
+++ xmlgraphics/fop/trunk/test/layoutengine/standard-testcases/page-sequence_language.xml Tue Oct 27 19:07:52 2009
@@ -65,4 +65,10 @@
<eval expected="de" xpath="/areaTree/pageSequence[4]/@language"/>
<true xpath="not(boolean(/areaTree/pageSequence[4]/@country))"/>
</checks>
+ <if-checks xmlns:if="http://xmlgraphics.apache.org/fop/intermediate">
+ <eval expected="en" xpath="//if:page-sequence[1]/@xml:lang"/>
+ <eval expected="en-US" xpath="//if:page-sequence[2]/@xml:lang"/>
+ <eval expected="de-CH" xpath="//if:page-sequence[3]/@xml:lang"/>
+ <eval expected="de" xpath="//if:page-sequence[4]/@xml:lang"/>
+ </if-checks>
</testcase>
---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org