FOP-2583: PDF xform to PDF content missing with font merge
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop-pdf-images/trunk@1732852 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/java/org/apache/fop/render/pdf/pdfbox/MergeFontsPDFWriter.java b/src/java/org/apache/fop/render/pdf/pdfbox/MergeFontsPDFWriter.java
index 5caaaa6..139131d 100644
--- a/src/java/org/apache/fop/render/pdf/pdfbox/MergeFontsPDFWriter.java
+++ b/src/java/org/apache/fop/render/pdf/pdfbox/MergeFontsPDFWriter.java
@@ -67,10 +67,12 @@
private static final Pattern SUBSET_PATTERN = Pattern.compile("[A-Z][A-Z][A-Z][A-Z][A-Z][A-Z]\\+.+");
private Collection<String> parentFonts;
- public MergeFontsPDFWriter(COSDictionary fonts, FontInfo fontInfo, String key, List<COSName> resourceNames) {
- super(key, resourceNames, 0);
+ public MergeFontsPDFWriter(COSDictionary fonts, FontInfo fontInfo, UniqueName key,
+ Collection<String> parentFonts, int mcid) {
+ super(key, mcid);
this.fonts = fonts;
this.fontInfo = fontInfo;
+ this.parentFonts = parentFonts;
}
public String writeText(PDStream pdStream) throws IOException {
@@ -95,8 +97,7 @@
internalName = getNewFont(fontData, fontInfo, fontsToRemove.values());
}
if (fontData == null || internalName == null) {
- s.append("/" + cn.getName());
- addKey(cn);
+ s.append("/" + key.getName(cn));
if (op.getOperation().equals("Tf")) {
font = null;
oldFont = null;
diff --git a/src/java/org/apache/fop/render/pdf/pdfbox/PDFBoxAdapter.java b/src/java/org/apache/fop/render/pdf/pdfbox/PDFBoxAdapter.java
index 09e0d5f..5a4f520 100644
--- a/src/java/org/apache/fop/render/pdf/pdfbox/PDFBoxAdapter.java
+++ b/src/java/org/apache/fop/render/pdf/pdfbox/PDFBoxAdapter.java
@@ -99,6 +99,7 @@
private final Map clonedVersion;
private Map<COSName, String> newXObj = new HashMap<COSName, String>();
private Map<Integer, PDFArray> pageNumbers;
+ private Collection<String> parentFonts = new ArrayList<String>();
private int currentMCID;
@@ -350,12 +351,11 @@
}
COSDictionary fonts = (COSDictionary)sourcePageResources.getCOSDictionary().getDictionaryObject(COSName.FONT);
COSDictionary fontsBackup = null;
- String uniqueName = Integer.toString(key.hashCode());
+ UniqueName uniqueName = new UniqueName(key, sourceDoc, sourcePageResources);
String newStream = null;
if (fonts != null && pdfDoc.isMergeFontsEnabled()) {
fontsBackup = new COSDictionary(fonts);
- MergeFontsPDFWriter m = new MergeFontsPDFWriter(fonts, fontinfo, uniqueName,
- getResourceNames(sourcePageResources.getCOSDictionary()));
+ MergeFontsPDFWriter m = new MergeFontsPDFWriter(fonts, fontinfo, uniqueName, parentFonts, currentMCID);
newStream = m.writeText(pdStream);
// if (newStream != null) {
// for (Object f : fonts.keySet().toArray()) {
@@ -367,8 +367,7 @@
// }
}
if (newStream == null) {
- PDFWriter writer = new PDFWriter(uniqueName, getResourceNames(sourcePageResources.getCOSDictionary()),
- currentMCID);
+ PDFWriter writer = new PDFWriter(uniqueName, currentMCID);
newStream = writer.writeText(pdStream);
currentMCID = writer.getCurrentMCID();
@@ -470,7 +469,8 @@
return boxStr.toString() + pdStream.getInputStreamAsString();
}
- private void mergeXObj(COSDictionary sourcePageResources, FontInfo fontinfo, String uniqueName) throws IOException {
+ private void mergeXObj(COSDictionary sourcePageResources, FontInfo fontinfo, UniqueName uniqueName)
+ throws IOException {
COSDictionary xobj = (COSDictionary) sourcePageResources.getDictionaryObject(COSName.XOBJECT);
if (xobj != null && pdfDoc.isMergeFontsEnabled()) {
for (Map.Entry<COSName, COSBase> i : xobj.entrySet()) {
@@ -486,19 +486,18 @@
} else {
for (Map.Entry<COSName, COSBase> entry : src.entrySet()) {
if (!target.keySet().contains(entry.getKey())) {
- target.setItem(entry.getKey(), entry.getValue());
+ target.setItem(uniqueName.getName(entry.getKey()), entry.getValue());
}
}
}
- PDFWriter writer = new MergeFontsPDFWriter(src, fontinfo, uniqueName,
- getResourceNames(sourcePageResources));
+ PDFWriter writer = new MergeFontsPDFWriter(src, fontinfo, uniqueName, parentFonts, 0);
String c = writer.writeText(PDStream.createFromCOS(stream));
if (c != null) {
stream.removeItem(COSName.FILTER);
newXObj.put(i.getKey(), c);
for (Object e : src.keySet().toArray()) {
COSName name = (COSName) e;
- src.setItem(name.getName() + uniqueName, src.getItem(name));
+ src.setItem(uniqueName.getName(name), src.getItem(name));
src.removeItem(name);
}
}
@@ -515,7 +514,7 @@
for (COSName entry : xobj.keySet()) {
if (newXObj.containsKey(entry)) {
PDFStream s = (PDFStream) target.get(entry.getName());
- s.setData(newXObj.get(entry).getBytes("UTF-8"));
+ s.setData(newXObj.get(entry).getBytes("ISO-8859-1"));
PDFDictionary xobjr = (PDFDictionary) s.get("Resources");
xobjr.put("Font", pageResources.get("Font"));
}
@@ -523,25 +522,11 @@
}
}
- private List<COSName> getResourceNames(COSDictionary sourcePageResources) {
- List<COSName> resourceNames = new ArrayList<COSName>();
- for (COSBase e : sourcePageResources.getValues()) {
- if (e instanceof COSObject) {
- e = ((COSObject) e).getObject();
- }
- if (e instanceof COSDictionary) {
- COSDictionary d = (COSDictionary) e;
- resourceNames.addAll(d.keySet());
- }
- }
- return resourceNames;
- }
-
- private void transferPageDict(COSDictionary fonts, String uniqueName, PDResources sourcePageResources)
+ private void transferPageDict(COSDictionary fonts, UniqueName uniqueName, PDResources sourcePageResources)
throws IOException {
if (fonts != null) {
for (Map.Entry<COSName, COSBase> f : fonts.entrySet()) {
- String name = f.getKey().getName() + uniqueName;
+ String name = uniqueName.getName(f.getKey());
targetPage.getPDFResources().addFont(name, (PDFDictionary)cloneForNewDocument(f.getValue()));
}
}
@@ -550,7 +535,7 @@
}
}
- private void transferDict(Map.Entry<COSName, COSBase> dict, String uniqueName) throws IOException {
+ private void transferDict(Map.Entry<COSName, COSBase> dict, UniqueName uniqueName) throws IOException {
COSBase src;
if (dict.getValue() instanceof COSObject) {
src = ((COSObject) dict.getValue()).getObject();
@@ -565,7 +550,7 @@
}
COSDictionary srcDict = (COSDictionary) src;
for (Map.Entry<COSName, COSBase> v : srcDict.entrySet()) {
- newDict.put(v.getKey().getName() + uniqueName, cloneForNewDocument(v.getValue()));
+ newDict.put(uniqueName.getName(v.getKey()), cloneForNewDocument(v.getValue()));
}
targetPage.getPDFResources().put(name, newDict);
}
diff --git a/src/java/org/apache/fop/render/pdf/pdfbox/PDFWriter.java b/src/java/org/apache/fop/render/pdf/pdfbox/PDFWriter.java
index 5622ab4..8c8c7ee 100644
--- a/src/java/org/apache/fop/render/pdf/pdfbox/PDFWriter.java
+++ b/src/java/org/apache/fop/render/pdf/pdfbox/PDFWriter.java
@@ -40,13 +40,11 @@
public class PDFWriter {
protected StringBuilder s = new StringBuilder();
- private String key;
- private List<COSName> resourceNames;
+ protected UniqueName key;
private int currentMCID;
- public PDFWriter(String key, List<COSName> resourceNames, int currentMCID) {
+ public PDFWriter(UniqueName key, int currentMCID) {
this.key = key;
- this.resourceNames = resourceNames;
this.currentMCID = currentMCID;
}
@@ -93,8 +91,7 @@
s.append(" ");
} else if (c instanceof COSName) {
COSName cn = (COSName)c;
- s.append("/" + cn.getName());
- addKey(cn);
+ s.append("/" + key.getName(cn));
s.append(" ");
} else if (c instanceof COSString) {
s.append("<" + ((COSString) c).getHexString() + ">");
@@ -138,11 +135,6 @@
dictArgs.add(updatedID);
}
- protected void addKey(COSName cn) {
- if (resourceNames.contains(cn)) {
- s.append(key);
- }
- }
protected int getCurrentMCID() {
return currentMCID;
}
diff --git a/src/java/org/apache/fop/render/pdf/pdfbox/UniqueName.java b/src/java/org/apache/fop/render/pdf/pdfbox/UniqueName.java
new file mode 100644
index 0000000..cb4e56a
--- /dev/null
+++ b/src/java/org/apache/fop/render/pdf/pdfbox/UniqueName.java
@@ -0,0 +1,73 @@
+/*
+ * 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.render.pdf.pdfbox;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSObject;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDResources;
+
+public class UniqueName {
+ private String key;
+ private List<COSName> resourceNames;
+
+ public UniqueName(String key, PDDocument sourceDoc, PDResources sourcePageResources) {
+ if (checkIfDocResourcesEqualPage(sourceDoc, sourcePageResources)) {
+ this.key = "";
+ } else {
+ this.key = Integer.toString(key.hashCode());
+ }
+ resourceNames = getResourceNames(sourcePageResources.getCOSDictionary());
+ }
+
+ private boolean checkIfDocResourcesEqualPage(PDDocument sourceDoc, PDResources sourcePageResources) {
+ PDResources srcDocResources = sourceDoc.getDocumentCatalog().getPages().getResources();
+ if (srcDocResources != null) {
+ COSDictionary srcDocResourcesDict = srcDocResources.getCOSDictionary();
+ return srcDocResourcesDict.equals(sourcePageResources.getCOSObject());
+ }
+ return false;
+ }
+
+ protected String getName(COSName cn) {
+ if (resourceNames.contains(cn)) {
+ return cn.getName() + key;
+ }
+ return cn.getName();
+ }
+
+ private List<COSName> getResourceNames(COSDictionary sourcePageResources) {
+ List<COSName> resourceNames = new ArrayList<COSName>();
+ for (COSBase e : sourcePageResources.getValues()) {
+ if (e instanceof COSObject) {
+ e = ((COSObject) e).getObject();
+ }
+ if (e instanceof COSDictionary) {
+ COSDictionary d = (COSDictionary) e;
+ resourceNames.addAll(d.keySet());
+ }
+ }
+ return resourceNames;
+ }
+}
diff --git a/test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java b/test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java
index 9860e31..0a6257a 100644
--- a/test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java
+++ b/test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java
@@ -30,6 +30,7 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@@ -76,6 +77,7 @@
import org.apache.fop.pdf.PDFAnnotList;
import org.apache.fop.pdf.PDFArray;
import org.apache.fop.pdf.PDFDocument;
+import org.apache.fop.pdf.PDFFilterList;
import org.apache.fop.pdf.PDFGState;
import org.apache.fop.pdf.PDFPage;
import org.apache.fop.pdf.PDFResources;
@@ -116,6 +118,7 @@
private static final String LINK = "test/resources/link.pdf";
private static final String IMAGE = "test/resources/image.pdf";
private static final String HELLOTagged = "test/resources/taggedWorld.pdf";
+ private static final String XFORM = "test/resources/xform.pdf";
private PDFBoxAdapter getPDFBoxAdapter() {
PDFDocument doc = new PDFDocument("");
@@ -361,6 +364,27 @@
}
@Test
+ public void testXform() throws Exception {
+ PDFDocument pdfdoc = new PDFDocument("");
+ pdfdoc.getFilterMap().put(PDFFilterList.DEFAULT_FILTER, Arrays.asList("null"));
+ pdfdoc.setMergeFontsEnabled(true);
+ PDFPage pdfpage = new PDFPage(new PDFResources(pdfdoc), 0, r, r, r, r);
+ pdfpage.setDocument(pdfdoc);
+ pdfpage.setObjectNumber(1);
+ Map<Integer, PDFArray> pageNumbers = new HashMap<Integer, PDFArray>();
+ PDFBoxAdapter adapter = new PDFBoxAdapter(pdfpage, new HashMap(), pageNumbers);
+ PDDocument doc = PDDocument.load(XFORM);
+ PDPage page = (PDPage) doc.getDocumentCatalog().getAllPages().get(0);
+ AffineTransform at = new AffineTransform();
+ Rectangle r = new Rectangle(0, 1650, 842000, 595000);
+ adapter.createStreamFromPDFBoxPage(doc, page, "key", at, new FontInfo(), r);
+ doc.close();
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ pdfdoc.output(bos);
+ Assert.assertFalse(bos.toString("UTF-8").contains("/W 5 /H 5 /BPC 8 /CS /RGB ID ÿÿÿ"));
+ }
+
+ @Test
public void testPreloaderPDF() throws Exception {
ImageSource imageSource = new ImageSource(ImageIO.createImageInputStream(new File(ROTATE)), "", true);
ImageInfo imageInfo = new PreloaderPDF().preloadImage("", imageSource, new DefaultImageContext());
diff --git a/test/resources/xform.pdf b/test/resources/xform.pdf
new file mode 100644
index 0000000..2a3134f
--- /dev/null
+++ b/test/resources/xform.pdf
Binary files differ