diff options
Diffstat (limited to 'src/java/org/apache/fop')
-rw-r--r-- | src/java/org/apache/fop/render/pdf/PDFContentGenerator.java | 2 | ||||
-rw-r--r-- | src/java/org/apache/fop/render/pdf/PDFRenderer.java | 91 |
2 files changed, 84 insertions, 9 deletions
diff --git a/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java b/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java index 9cff94f6a..942d5c72c 100644 --- a/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java +++ b/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java @@ -183,7 +183,7 @@ public class PDFContentGenerator { this.inMarkedContentSequence = true; } - private void endMarkedContentSequence() { + void endMarkedContentSequence() { currentStream.add("EMC\n"); this.inMarkedContentSequence = false; this.inArtifactMode = false; diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java index 3b737150b..4da0330c5 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java @@ -31,8 +31,12 @@ import java.io.IOException; 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.InlineParent; 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.pdf.PDFXObject; 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 @@ public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConf * 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 @@ public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConf /** Image handler registry */ private final PDFImageHandlerRegistry imageHandlerRegistry = new PDFImageHandlerRegistry(); + private boolean accessEnabled; + + private PDFLogicalStructureHandler logicalStructureHandler; + + private int pageSequenceNumber; + + /** Reference in the structure tree to the image being rendered. */ + private String imageReference; /** * create the PDF renderer @@ -204,6 +219,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConf public void setUserAgent(FOUserAgent agent) { super.setUserAgent(agent); this.pdfUtil = new PDFRenderingUtil(getUserAgent()); + accessEnabled = agent.isAccessibilityEnabled(); } PDFRenderingUtil getPDFUtil() { @@ -225,6 +241,10 @@ public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConf } ostream = stream; this.pdfDoc = pdfUtil.setupPDFDocument(stream); + if (accessEnabled) { + pdfDoc.getRoot().makeTagged(); + logicalStructureHandler = new PDFLogicalStructureHandler(pdfDoc); + } } /** @@ -274,8 +294,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConf * {@inheritDoc} */ public boolean supportsOutOfOrder() { - //return false; - return true; + return !accessEnabled; } /** @@ -394,17 +413,25 @@ public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConf 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( + ++pageSequenceNumber); + logicalStructureHandler.processStructureTree(nodes, language); + } } /** @@ -457,6 +484,10 @@ public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConf } currentPageRef = currentPage.referencePDF(); + if (accessEnabled) { + logicalStructureHandler.startPage(currentPage); + } + Rectangle bounds = page.getViewArea(); pageHeight = bounds.height; @@ -474,6 +505,10 @@ public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConf super.renderPage(page); + if (accessEnabled) { + logicalStructureHandler.endPage(); + } + this.pdfDoc.registerObject(generator.getStream()); currentPage.setContents(generator.getStream()); PDFAnnotList annots = currentPage.getAnnotations(); @@ -903,11 +938,21 @@ public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConf + 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); + } + private Typeface getTypeface(String fontName) { Typeface tf = (Typeface) fontInfo.getFonts().get(fontName); if (tf instanceof LazyFont) { @@ -922,7 +967,16 @@ public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConf 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.beginTextObjectAccess(mci.tag, mci.mcid); + } else { + beginTextObject(); + } String fontName = getInternalFontNameForArea(text); int size = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue(); @@ -1178,13 +1232,22 @@ public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConf * @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 @@ public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConf 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. |