FOP-2553: Support PDF shading to PS
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop-pdf-images/trunk@1720524 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/fontbox-2.0.0-SNAPSHOT.jar b/lib/fontbox-2.0.0-SNAPSHOT.jar
index eba4f81..7245755 100644
--- a/lib/fontbox-2.0.0-SNAPSHOT.jar
+++ b/lib/fontbox-2.0.0-SNAPSHOT.jar
Binary files differ
diff --git a/lib/fop.jar b/lib/fop.jar
index 55e34ab..d1bb409 100644
--- a/lib/fop.jar
+++ b/lib/fop.jar
Binary files differ
diff --git a/lib/pdfbox-2.0.0-SNAPSHOT.jar b/lib/pdfbox-2.0.0-SNAPSHOT.jar
index cdcce15..dce403a 100644
--- a/lib/pdfbox-2.0.0-SNAPSHOT.jar
+++ b/lib/pdfbox-2.0.0-SNAPSHOT.jar
Binary files differ
diff --git a/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFSingleByteFont.java b/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFSingleByteFont.java
index 77add78..6dcd95f 100644
--- a/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFSingleByteFont.java
+++ b/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFSingleByteFont.java
@@ -38,7 +38,6 @@
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.cos.COSNumber;
import org.apache.pdfbox.encoding.Encoding;
-import org.apache.pdfbox.encoding.EncodingManager;
import org.apache.pdfbox.pdmodel.common.PDStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDFontDescriptorDictionary;
@@ -117,7 +116,7 @@
addEncoding(font);
}
- private Map<Integer, String> getCodeToName(Encoding encoding) {
+ private Map<Integer, String> getCodeToName(Encoding encoding) throws IOException {
Map<Integer, String> codeToName = new HashMap<Integer, String>();
if (encoding != null) {
COSBase cos = encoding.getCOSObject();
@@ -125,12 +124,8 @@
COSDictionary enc = (COSDictionary) cos;
COSName baseEncodingName = (COSName) enc.getDictionaryObject(COSName.BASE_ENCODING);
if (baseEncodingName != null) {
- try {
- Encoding baseEncoding = EncodingManager.INSTANCE.getEncoding(baseEncodingName);
- codeToName.putAll(baseEncoding.getCodeToNameMap());
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
+ Encoding baseEncoding = Encoding.getInstance(baseEncodingName);
+ codeToName.putAll(baseEncoding.getCodeToNameMap());
}
COSArray differences = (COSArray)enc.getDictionaryObject(COSName.DIFFERENCES);
int currentIndex = -1;
@@ -359,7 +354,7 @@
return null;
}
- private void addEncoding(PDFont fontForEnc) {
+ private void addEncoding(PDFont fontForEnc) throws IOException {
List<String> added = new ArrayList<String>(encodingMap.values());
Map<Integer, String> codeToName = getCodeToName(fontForEnc.getFontEncoding());
for (int i = fontForEnc.getFirstChar(); i <= fontForEnc.getLastChar(); i++) {
diff --git a/src/java/org/apache/fop/render/pdf/pdfbox/ImageConverterPDF2G2D.java b/src/java/org/apache/fop/render/pdf/pdfbox/ImageConverterPDF2G2D.java
index eeed02a..1c0b269 100644
--- a/src/java/org/apache/fop/render/pdf/pdfbox/ImageConverterPDF2G2D.java
+++ b/src/java/org/apache/fop/render/pdf/pdfbox/ImageConverterPDF2G2D.java
@@ -134,8 +134,8 @@
area.getHeight() / pageDimension.height);
g2d.transform(at);
- PageDrawer drawer = new PageDrawer(null);
- drawer.drawPage(g2d, page, mediaBox);
+ PageDrawer drawer = new PageDrawer(null, page);
+ drawer.drawPage(g2d, mediaBox);
} catch (IOException ioe) {
//TODO Better exception handling
throw new RuntimeException("I/O error while painting PDF page", ioe);
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 d6846b5..6ea51bc 100644
--- a/src/java/org/apache/fop/render/pdf/pdfbox/MergeFontsPDFWriter.java
+++ b/src/java/org/apache/fop/render/pdf/pdfbox/MergeFontsPDFWriter.java
@@ -48,7 +48,7 @@
import org.apache.pdfbox.pdmodel.font.PDTrueTypeFont;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
-import org.apache.pdfbox.util.operator.PDFOperator;
+import org.apache.pdfbox.util.operator.Operator;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.SingleByteFont;
@@ -85,7 +85,7 @@
return txt;
}
- protected void readPDFArguments(PDFOperator op, Collection<COSBase> arguments) throws IOException {
+ protected void readPDFArguments(Operator op, Collection<COSBase> arguments) throws IOException {
for (COSBase c : arguments) {
if (c instanceof COSName) {
COSName cn = (COSName)c;
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 a734c6d..5622ab4 100644
--- a/src/java/org/apache/fop/render/pdf/pdfbox/PDFWriter.java
+++ b/src/java/org/apache/fop/render/pdf/pdfbox/PDFWriter.java
@@ -36,7 +36,7 @@
import org.apache.pdfbox.cos.COSString;
import org.apache.pdfbox.pdfparser.PDFStreamParser;
import org.apache.pdfbox.pdmodel.common.PDStream;
-import org.apache.pdfbox.util.operator.PDFOperator;
+import org.apache.pdfbox.util.operator.Operator;
public class PDFWriter {
protected StringBuilder s = new StringBuilder();
@@ -55,8 +55,8 @@
List<COSBase> arguments = new ArrayList<COSBase>();
while (it.hasNext()) {
Object o = it.next();
- if (o instanceof PDFOperator) {
- PDFOperator op = (PDFOperator)o;
+ if (o instanceof Operator) {
+ Operator op = (Operator)o;
readPDFArguments(op, arguments);
s.append(op.getOperation() + "\n");
arguments.clear();
@@ -77,13 +77,13 @@
return s.toString();
}
- protected void readPDFArguments(PDFOperator op, Collection<COSBase> arguments) throws IOException {
+ protected void readPDFArguments(Operator op, Collection<COSBase> arguments) throws IOException {
for (COSBase c : arguments) {
processArg(op, c);
}
}
- protected void processArg(PDFOperator op, COSBase c) throws IOException {
+ protected void processArg(Operator op, COSBase c) throws IOException {
if (c instanceof COSInteger) {
s.append(((COSInteger) c).intValue());
s.append(" ");
diff --git a/src/java/org/apache/fop/render/pdf/pdfbox/PSPDFGraphics2D.java b/src/java/org/apache/fop/render/pdf/pdfbox/PSPDFGraphics2D.java
index 1934a44..068b9b3 100644
--- a/src/java/org/apache/fop/render/pdf/pdfbox/PSPDFGraphics2D.java
+++ b/src/java/org/apache/fop/render/pdf/pdfbox/PSPDFGraphics2D.java
@@ -24,7 +24,10 @@
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
+import java.awt.Paint;
+import java.awt.PaintContext;
import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.awt.image.ImageObserver;
@@ -33,7 +36,28 @@
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.URI;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSInteger;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSStream;
+import org.apache.pdfbox.pdmodel.common.function.PDFunction;
+import org.apache.pdfbox.pdmodel.common.function.PDFunctionType0;
+import org.apache.pdfbox.pdmodel.common.function.PDFunctionType2;
+import org.apache.pdfbox.pdmodel.common.function.PDFunctionType3;
+import org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace;
+import org.apache.pdfbox.pdmodel.graphics.pattern.TilingPaint;
+import org.apache.pdfbox.pdmodel.graphics.shading.AxialShadingContext;
+import org.apache.pdfbox.pdmodel.graphics.shading.AxialShadingPaint;
+import org.apache.pdfbox.pdmodel.graphics.shading.RadialShadingContext;
+import org.apache.pdfbox.pdmodel.graphics.shading.RadialShadingPaint;
+
import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageSize;
@@ -42,6 +66,13 @@
import org.apache.xmlgraphics.ps.PSGenerator;
import org.apache.xmlgraphics.ps.PSResource;
+import org.apache.fop.pdf.PDFDeviceColorSpace;
+import org.apache.fop.render.gradient.Function;
+import org.apache.fop.render.gradient.GradientMaker;
+import org.apache.fop.render.gradient.GradientMaker.DoubleFormatter;
+import org.apache.fop.render.gradient.Pattern;
+import org.apache.fop.render.gradient.Shading;
+import org.apache.fop.render.ps.Gradient;
import org.apache.fop.render.ps.PSDocumentHandler;
import org.apache.fop.render.ps.PSImageUtils;
@@ -59,6 +90,127 @@
super(textAsShapes, gen);
}
+ private final GradientMaker.DoubleFormatter doubleFormatter = new DoubleFormatter() {
+
+ public String formatDouble(double d) {
+ return getPSGenerator().formatDouble(d);
+ }
+ };
+
+ protected void applyPaint(Paint paint, boolean fill) {
+ preparePainting();
+ if (paint instanceof AxialShadingPaint || paint instanceof RadialShadingPaint) {
+ PaintContext paintContext = paint.createContext(null, null, null, new AffineTransform(),
+ getRenderingHints());
+ PDColorSpace pdcs;
+ int deviceColorSpace = PDFDeviceColorSpace.DEVICE_RGB;
+ if (paint instanceof AxialShadingPaint) {
+ try {
+ AxialShadingContext asc = (AxialShadingContext) paintContext;
+ float[] fCoords = asc.getCoords();
+ PDFunction function = asc.getFunction();
+ Function targetFT = getFunction(function);
+ if (targetFT != null) {
+ if (targetFT.getFunctions().size() == 5
+ && targetFT.getFunctions().get(0).getFunctionType() == 0) {
+ return;
+ }
+ List<Double> dCoords = floatArrayToDoubleList(fCoords);
+ PDFDeviceColorSpace colSpace = new PDFDeviceColorSpace(deviceColorSpace);
+ Shading shading = new Shading(2, colSpace, dCoords, targetFT);
+ Pattern pattern = new Pattern(2, shading, null);
+ gen.write(Gradient.outputPattern(pattern, doubleFormatter));
+ }
+ } catch (IOException ioe) {
+ handleIOException(ioe);
+ }
+ } else if (paint instanceof RadialShadingPaint) {
+ try {
+ RadialShadingContext rsc = (RadialShadingContext) paintContext;
+ float[] fCoords = rsc.getCoords();
+ PDFunction function = rsc.getFunction();
+ Function targetFT3 = getFunction(function);
+ List<Double> dCoords = floatArrayToDoubleList(fCoords);
+ PDFDeviceColorSpace colSpace = new PDFDeviceColorSpace(deviceColorSpace);
+ Shading shading = new Shading(3, colSpace, dCoords, targetFT3);
+ Pattern pattern = new Pattern(2, shading, null);
+ gen.write(Gradient.outputPattern(pattern, doubleFormatter));
+ } catch (IOException ioe) {
+ handleIOException(ioe);
+ }
+ }
+ }
+ if (paint instanceof TilingPaint) {
+ super.applyPaint(paint, fill);
+ }
+ }
+
+ private static Function getFunction(PDFunction f) throws IOException {
+ if (f instanceof PDFunctionType3) {
+ PDFunctionType3 sourceFT3 = (PDFunctionType3) f;
+ float[] bounds = sourceFT3.getBounds().toFloatArray();
+ COSArray sourceFunctions = sourceFT3.getFunctions();
+ List<Function> targetFunctions = new ArrayList<Function>();
+ for (int j = 0; j < sourceFunctions.size(); j++) {
+ targetFunctions.add(getFunction(PDFunction.create(sourceFunctions.get(j))));
+ }
+ return new Function(null, null, targetFunctions, toList(bounds), null);
+ } else if (f instanceof PDFunctionType2) {
+ PDFunctionType2 sourceFT2 = (PDFunctionType2) f;
+ double interpolation = (double)sourceFT2.getN();
+ float[] c0 = sourceFT2.getC0().toFloatArray();
+ float[] c1 = sourceFT2.getC1().toFloatArray();
+ return new Function(null, null, c0, c1, interpolation);
+ } else if (f instanceof PDFunctionType0) {
+ COSDictionary s = f.getDictionary();
+ assert s instanceof COSStream;
+ COSStream stream = (COSStream) s;
+ COSArray encode = (COSArray) s.getDictionaryObject(COSName.ENCODE);
+ COSArray domain = (COSArray) s.getDictionaryObject(COSName.DOMAIN);
+ COSArray range = (COSArray) s.getDictionaryObject(COSName.RANGE);
+ int bits = ((COSInteger)s.getDictionaryObject(COSName.BITS_PER_SAMPLE)).intValue();
+ COSArray size = (COSArray) s.getDictionaryObject(COSName.SIZE);
+ byte[] x = IOUtils.toByteArray(stream.getUnfilteredStream());
+ for (byte y : x) {
+ if (y != 0) {
+ return new Function(floatArrayToDoubleList(domain.toFloatArray()),
+ floatArrayToDoubleList(range.toFloatArray()),
+ floatArrayToDoubleList(encode.toFloatArray()),
+ x,
+ bits,
+ toList(size)
+ );
+ }
+ }
+ return null;
+ }
+ throw new IOException("Unsupported " + f.toString());
+ }
+
+ private static List<Float> toList(float[] array) {
+ List<Float> list = new ArrayList<Float>(array.length);
+ for (float f : array) {
+ list.add(f);
+ }
+ return list;
+ }
+
+ private static List<Integer> toList(COSArray array) {
+ List<Integer> list = new ArrayList<Integer>();
+ for (COSBase i : array) {
+ list.add(((COSInteger)i).intValue());
+ }
+ return list;
+ }
+
+ private static List<Double> floatArrayToDoubleList(float[] floatArray) {
+ List<Double> doubleList = new ArrayList<Double>();
+ for (float f : floatArray) {
+ doubleList.add((double) f);
+ }
+ return doubleList;
+ }
+
@Override
public boolean drawImage(Image img, int x1, int y1, ImageObserver observer) {
PSGenerator tmp = gen;