private void addStructTreeBBox(Rectangle rect) {
if (accessEnabled && getDocumentHandler().getPDFDocument().getProfile().getPDFUAMode().isEnabled()) {
PDFStructElem structElem = (PDFStructElem) getContext().getStructureTreeElement();
- PDFDictionary d = new PDFDictionary();
- int x = rect.x / 1000;
- int y = rect.y / 1000;
- int w = rect.width / 1000;
- int h = rect.height / 1000;
- d.put("BBox", new PDFArray(x, y, w, h));
- d.put("O", new PDFName("Layout"));
- structElem.put("A", d);
+ if (structElem != null) { //structElem is null if the image is marked as an artifact
+ PDFDictionary d = new PDFDictionary();
+ int x = rect.x / 1000;
+ int y = rect.y / 1000;
+ int w = rect.width / 1000;
+ int h = rect.height / 1000;
+ d.put("BBox", new PDFArray(x, y, w, h));
+ d.put("O", new PDFName("Layout"));
+ structElem.put("A", d);
+ }
}
}
--- /dev/null
+/*
+ * 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.accessibility.fo;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.MissingResourceException;
+
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.junit.Test;
+
+import org.xml.sax.SAXException;
+
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.apps.Fop;
+import org.apache.fop.apps.FopFactory;
+import org.apache.fop.apps.MimeConstants;
+import org.apache.fop.render.intermediate.IFContext;
+import org.apache.fop.render.intermediate.IFDocumentHandler;
+import org.apache.fop.render.intermediate.IFSerializer;
+
+/**
+ * Test for reproducing a NullPointerException occurring with activated PDF/UA and when an image
+ * is marked as an artifact.
+ * @see FOP-2646
+ */
+public class ArtifactImageBugTestCase {
+
+ @Test
+ public void testMarkerStateTrackingBug() throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ formatFO(needResource("artifact-image-npe.fo"), out, MimeConstants.MIME_PDF);
+ //checkPDF(out);
+ }
+
+ private void formatFO(URL foFile, ByteArrayOutputStream out, String mimeFopIf)
+ throws IOException, SAXException, TransformerException {
+ FopFactory fopFactory = getFopFactory();
+ FOUserAgent userAgent = fopFactory.newFOUserAgent();
+
+ if (mimeFopIf.equals(MimeConstants.MIME_FOP_IF)) {
+ IFSerializer serializer = new IFSerializer(new IFContext(userAgent));
+ IFDocumentHandler targetHandler
+ = userAgent.getRendererFactory().createDocumentHandler(userAgent, MimeConstants.MIME_PDF);
+ serializer.mimicDocumentHandler(targetHandler);
+ userAgent.setDocumentHandlerOverride(serializer);
+ }
+
+ Fop fop = fopFactory.newFop(mimeFopIf, userAgent, out);
+ Transformer transformer = TransformerFactory.newInstance().newTransformer();
+ Source src = new StreamSource(foFile.openStream());
+ Result res = new SAXResult(fop.getDefaultHandler());
+ transformer.transform(src, res);
+ }
+
+ private FopFactory getFopFactory() throws IOException, SAXException {
+ return FopFactory.newInstance(new File(".").toURI(),
+ needResource("/org/apache/fop/pdf/PDFUA.xconf").openStream());
+ }
+
+ private URL needResource(String resourceName) {
+ return needResource(getClass(), resourceName);
+ }
+
+ private URL needResource(Class contextClass, String resourceName) {
+ URL url = contextClass.getResource(resourceName);
+ if (url == null) {
+ throw new MissingResourceException("Resource not found: " + resourceName,
+ contextClass.getName(), resourceName);
+ }
+ return url;
+ }
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
+ xmlns:fox="http://xmlgraphics.apache.org/fop/extensions"
+ language="en" font-family="DejaVu LGC Serif">
+
+ <fo:layout-master-set>
+
+ <fo:simple-page-master master-name="normal" page-height="29.7cm" page-width="21cm" margin="2cm">
+ <fo:region-body/>
+ </fo:simple-page-master>
+
+ <fo:simple-page-master master-name="with-header" page-height="29.7cm" page-width="21cm" margin="2cm">
+ <fo:region-body margin-top="2.5cm"/>
+ <fo:region-before extent="2cm"/>
+ </fo:simple-page-master>
+
+ </fo:layout-master-set>
+
+ <fo:declarations>
+ <x:xmpmeta xmlns:x="adobe:ns:meta/">
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <rdf:Description xmlns:dc="http://purl.org/dc/elements/1.1/" rdf:about="">
+ <dc:title>PDF/UA test case provoking an NPE with artifact images.</dc:title>
+ <dc:creator>The Apache Software Foundation</dc:creator>
+ <dc:description>Demonstrates a NullPointerException a NullPointerException occurring with activated PDF/UA and when an image is marked as an artifact. See FOP-2646</dc:description>
+ </rdf:Description>
+ </rdf:RDF>
+ </x:xmpmeta>
+ </fo:declarations>
+
+ <fo:page-sequence id="ps1" master-reference="with-header">
+
+ <fo:static-content flow-name="xsl-region-before"> <!-- Don't do role="artifact" here! -->
+ <fo:block><fo:retrieve-marker retrieve-class-name="running-header" retrieve-position="last-ending-within-page" retrieve-boundary="page-sequence"/></fo:block>
+ </fo:static-content>
+
+ <fo:flow flow-name="xsl-region-body">
+ <fo:block><fo:marker marker-class-name="running-header"><fo:wrapper role="artifact">Chapter 1</fo:wrapper></fo:marker>Chapter 1</fo:block>
+ <fo:block>Some text and an image wrapped in an fo:wrapper that is marked as an artifact:</fo:block>
+ <fo:block><fo:wrapper role="artifact"><fo:external-graphic fox:alt-text="A red dot" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9YGARc5KB0XV+IAAAAddEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIFRoZSBHSU1Q72QlbgAAAF1JREFUGNO9zL0NglAAxPEfdLTs4BZM4DIO4C7OwQg2JoQ9LE1exdlYvBBeZ7jqch9//q1uH4TLzw4d6+ErXMMcXuHWxId3KOETnnXXV6MJpcq2MLaI97CER3N0vr4MkhoXe0rZigAAAABJRU5ErkJggg=="/></fo:wrapper></fo:block>
+ <fo:block>Some text.</fo:block>
+ <fo:block><fo:marker marker-class-name="running-header"><fo:wrapper role="artifact">Chapter 2</fo:wrapper></fo:marker>Chapter 2</fo:block>
+ <fo:block>Some text.</fo:block>
+
+ <fo:block break-before="page"/>
+
+ <fo:block><fo:marker marker-class-name="running-header"><fo:wrapper role="artifact">Chapter 3</fo:wrapper></fo:marker>Chapter 3</fo:block>
+ <fo:block>Some text.</fo:block>
+
+ </fo:flow>
+ </fo:page-sequence>
+
+ <fo:page-sequence id="ps2" master-reference="normal">
+ <fo:flow flow-name="xsl-region-body">
+ <fo:block>Next Page Sequence. Does accessibility still work?<fo:wrapper role="artifact">Artifact</fo:wrapper></fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+</fo:root>