View | Details | Raw Unified | Return to bug 37236
Collapse All | Expand All

(-)src/java/org/apache/fop/svg/PDFGraphics2D.java (-16 / +187 lines)
Lines 45-50 Link Here
45
import org.apache.batik.ext.awt.g2d.GraphicContext;
45
import org.apache.batik.ext.awt.g2d.GraphicContext;
46
import org.apache.batik.ext.awt.RadialGradientPaint;
46
import org.apache.batik.ext.awt.RadialGradientPaint;
47
import org.apache.batik.ext.awt.LinearGradientPaint;
47
import org.apache.batik.ext.awt.LinearGradientPaint;
48
import org.apache.batik.ext.awt.MultipleGradientPaint;
48
import org.apache.batik.ext.awt.RenderingHintsKeyExt;
49
import org.apache.batik.ext.awt.RenderingHintsKeyExt;
49
import org.apache.batik.gvt.PatternPaint;
50
import org.apache.batik.gvt.PatternPaint;
50
import org.apache.batik.gvt.GraphicsNode;
51
import org.apache.batik.gvt.GraphicsNode;
Lines 61-77 Link Here
61
import java.awt.Shape;
62
import java.awt.Shape;
62
import java.awt.Stroke;
63
import java.awt.Stroke;
63
import java.awt.Paint;
64
import java.awt.Paint;
65
import java.awt.PaintContext;
64
import java.awt.Rectangle;
66
import java.awt.Rectangle;
67
import java.awt.Transparency;
65
import java.awt.Dimension;
68
import java.awt.Dimension;
66
import java.awt.BasicStroke;
69
import java.awt.BasicStroke;
67
import java.awt.AlphaComposite;
70
import java.awt.AlphaComposite;
68
import java.awt.geom.AffineTransform;
71
import java.awt.geom.AffineTransform;
72
import java.awt.color.ColorSpace;
69
import java.awt.image.BufferedImage;
73
import java.awt.image.BufferedImage;
74
import java.awt.image.ColorModel;
75
import java.awt.image.DirectColorModel;
70
import java.awt.image.DataBuffer;
76
import java.awt.image.DataBuffer;
71
import java.awt.image.DataBufferInt;
77
import java.awt.image.DataBufferInt;
72
import java.awt.image.ImageObserver;
78
import java.awt.image.ImageObserver;
73
import java.awt.image.RenderedImage;
79
import java.awt.image.RenderedImage;
74
import java.awt.image.Raster;
80
import java.awt.image.Raster;
81
import java.awt.image.WritableRaster;
75
import java.awt.image.renderable.RenderableImage;
82
import java.awt.image.renderable.RenderableImage;
76
import java.awt.geom.PathIterator;
83
import java.awt.geom.PathIterator;
77
import java.awt.geom.Point2D;
84
import java.awt.geom.Point2D;
Lines 129-135 Link Here
129
     * The count of JPEG images added to document so they recieve
136
     * The count of JPEG images added to document so they recieve
130
     * unique keys.
137
     * unique keys.
131
     */
138
     */
132
    protected int jpegCount = 0;
139
    protected int jpegCount[] = {0};
133
140
134
    /**
141
    /**
135
     * The current font information.
142
     * The current font information.
Lines 376-387 Link Here
376
    public void addJpegImage(JpegImage jpeg, float x, float y, 
383
    public void addJpegImage(JpegImage jpeg, float x, float y, 
377
                             float width, float height) {
384
                             float width, float height) {
378
        preparePainting();
385
        preparePainting();
379
        String key = "__AddJPEG_" + jpegCount;
386
        String key = "__AddJPEG_" + jpegCount[0];
380
        jpegCount++;
387
        jpegCount[0]++;
381
        FopPDFImage fopimage = new FopPDFImage(jpeg, key);
388
        FopPDFImage fopimage = new FopPDFImage(jpeg, key);
382
        int xObjectNum = this.pdfDoc.addImage(resourceContext, 
389
        int xObjectNum = this.pdfDoc.addImage(resourceContext, 
383
                                              fopimage).getXNumber();
390
                                              fopimage).getXNumber();
384
385
        AffineTransform at = getTransform();
391
        AffineTransform at = getTransform();
386
        double[] matrix = new double[6];
392
        double[] matrix = new double[6];
387
        at.getMatrix(matrix);
393
        at.getMatrix(matrix);
Lines 709-715 Link Here
709
715
710
        Paint paint = getPaint();
716
        Paint paint = getPaint();
711
        if (graphicsState.setPaint(paint)) {
717
        if (graphicsState.setPaint(paint)) {
712
            applyPaint(paint, false);
718
            if (!applyPaint(paint, false)) {
719
                // Stroke the shape and use it to 'clip'
720
                // the paint contents.
721
                Shape ss = getStroke().createStrokedShape(s);
722
                applyUnknownPaint(paint, ss);
723
724
                if (newClip || newTransform) {
725
                    currentStream.write("Q\n");
726
                    graphicsState.pop();
727
                }
728
                return;
729
            }
713
        }
730
        }
714
        applyStroke(getStroke());
731
        applyStroke(getStroke());
715
732
Lines 831-849 Link Here
831
     * @param paint the paint to convert to PDF
848
     * @param paint the paint to convert to PDF
832
     * @param fill true if the paint should be set for filling
849
     * @param fill true if the paint should be set for filling
833
     */
850
     */
834
    protected void applyPaint(Paint paint, boolean fill) {
851
    protected boolean applyPaint(Paint paint, boolean fill) {
835
        preparePainting();
852
        preparePainting();
836
853
854
        if (paint instanceof Color) {
855
            return true;
856
        }
837
        if (paint instanceof LinearGradientPaint) {
857
        if (paint instanceof LinearGradientPaint) {
838
            LinearGradientPaint gp = (LinearGradientPaint)paint;
858
            LinearGradientPaint gp = (LinearGradientPaint)paint;
859
860
            // This code currently doesn't support 'repeat'.
861
            // For linear gradients it is possible to construct
862
            // a 'tile' that is repeated with a PDF pattern, but
863
            // it would be very tricky as you would have to rotate
864
            // the coordinate system so the repeate was axially
865
            // aligned.  At this point I'm just going to rasterize it.
866
            MultipleGradientPaint.CycleMethodEnum cycle = gp.getCycleMethod();
867
            if (cycle != MultipleGradientPaint.NO_CYCLE)
868
                return false;
869
839
            Color[] cols = gp.getColors();
870
            Color[] cols = gp.getColors();
840
            float[] fractions = gp.getFractions();
871
            float[] fractions = gp.getFractions();
841
872
842
            //MultipleGradientPaint.CycleMethodEnum cycenum = gp.getCycleMethod();
843
            //boolean cyclic = (cycenum == MultipleGradientPaint.REPEAT);
844
            // This code currently doesn't support 'repeat' as PDF has
845
            // no way to support this (we need to rasterize).
846
847
            // Build proper transform from gradient space to page space
873
            // Build proper transform from gradient space to page space
848
            // ('Patterns' don't get userspace transform).
874
            // ('Patterns' don't get userspace transform).
849
            AffineTransform transform;
875
            AffineTransform transform;
Lines 885-890 Link Here
885
911
886
            for (int count = 0; count < cols.length; count++) {
912
            for (int count = 0; count < cols.length; count++) {
887
                Color c1 = cols[count];
913
                Color c1 = cols[count];
914
                if (c1.getAlpha() != 255) return false;  // PDF can't do alpha
915
888
                PDFColor color1 = new PDFColor(c1.getRed(), c1.getGreen(),
916
                PDFColor color1 = new PDFColor(c1.getRed(), c1.getGreen(),
889
                                               c1.getBlue());
917
                                               c1.getBlue());
890
                someColors.add(color1);
918
                someColors.add(color1);
Lines 900-908 Link Here
900
                    someColors, theBounds, theCoords, theMatrix);
928
                    someColors, theBounds, theCoords, theMatrix);
901
            currentStream.write(myPat.getColorSpaceOut(fill));
929
            currentStream.write(myPat.getColorSpaceOut(fill));
902
930
903
        } else if (paint instanceof RadialGradientPaint) {
931
            return true;
932
        }
933
        if (paint instanceof RadialGradientPaint) {
904
            RadialGradientPaint rgp = (RadialGradientPaint)paint;
934
            RadialGradientPaint rgp = (RadialGradientPaint)paint;
905
935
936
            // There is essentially no way to support repeate
937
            // in PDF for radial gradients (the one option would
938
            // be to 'grow' the outer circle until it fully covered
939
            // the bounds and then grow the stops accordingly, the
940
            // problem is that this may require an extremely large
941
            // number of stops for cases where the focus is near
942
            // the edge of the outer circle).  so we rasterize.
943
            MultipleGradientPaint.CycleMethodEnum cycle = rgp.getCycleMethod();
944
            if (cycle != MultipleGradientPaint.NO_CYCLE)
945
                return false;
946
906
            AffineTransform transform;
947
            AffineTransform transform;
907
            transform = new AffineTransform(graphicsState.getTransform());
948
            transform = new AffineTransform(graphicsState.getTransform());
908
            transform.concatenate(getTransform());
949
            transform.concatenate(getTransform());
Lines 941-946 Link Here
941
            List someColors = new java.util.ArrayList();
982
            List someColors = new java.util.ArrayList();
942
            for (int count = 0; count < cols.length; count++) {
983
            for (int count = 0; count < cols.length; count++) {
943
                Color cc = cols[count];
984
                Color cc = cols[count];
985
                if (cc.getAlpha() != 255) return false;  // PDF can't do alpha
986
944
                someColors.add(new PDFColor(cc.getRed(), cc.getGreen(), 
987
                someColors.add(new PDFColor(cc.getRed(), cc.getGreen(), 
945
                                            cc.getBlue()));
988
                                            cc.getBlue()));
946
            }
989
            }
Lines 960-972 Link Here
960
1003
961
            currentStream.write(myPat.getColorSpaceOut(fill));
1004
            currentStream.write(myPat.getColorSpaceOut(fill));
962
1005
963
        } else if (paint instanceof PatternPaint) {
1006
            return true;
1007
        } 
1008
        if (paint instanceof PatternPaint) {
964
            PatternPaint pp = (PatternPaint)paint;
1009
            PatternPaint pp = (PatternPaint)paint;
965
            createPattern(pp, fill);
1010
            return createPattern(pp, fill);
966
        }
1011
        }
1012
        return false; // unknown paint
967
    }
1013
    }
968
1014
969
    private void createPattern(PatternPaint pp, boolean fill) {
1015
    private boolean createPattern(PatternPaint pp, boolean fill) {
970
        preparePainting();
1016
        preparePainting();
971
1017
972
        FontInfo fontInfo = new FontInfo();
1018
        FontInfo fontInfo = new FontInfo();
Lines 1061-1068 Link Here
1061
                // ignore exception, will be thrown again later
1107
                // ignore exception, will be thrown again later
1062
            }
1108
            }
1063
        }
1109
        }
1110
        return true;
1064
    }
1111
    }
1065
1112
1113
    protected boolean applyUnknownPaint(Paint paint, Shape shape) {
1114
        preparePainting();
1115
1116
        Shape clip = getClip();
1117
        Rectangle2D usrClipBounds, usrBounds;
1118
        usrBounds = shape.getBounds2D();
1119
        usrClipBounds  = clip.getBounds2D();
1120
        if (!usrClipBounds.intersects(usrBounds))
1121
            return true;
1122
        Rectangle2D.intersect(usrBounds, usrClipBounds, usrBounds);
1123
        double usrX = usrBounds.getX();
1124
        double usrY = usrBounds.getY();
1125
        double usrW = usrBounds.getWidth();
1126
        double usrH = usrBounds.getHeight();
1127
1128
        Rectangle devShapeBounds, devClipBounds, devBounds;
1129
        AffineTransform at = getTransform();
1130
        devShapeBounds = at.createTransformedShape(shape).getBounds();
1131
        devClipBounds  = at.createTransformedShape(clip).getBounds();
1132
        if (!devClipBounds.intersects(devShapeBounds)) 
1133
            return true;
1134
        devBounds = devShapeBounds.intersection(devClipBounds);
1135
        int devX = devBounds.x;
1136
        int devY = devBounds.y;
1137
        int devW = devBounds.width;
1138
        int devH = devBounds.height;
1139
1140
        ColorSpace rgbCS = ColorSpace.getInstance(ColorSpace.CS_sRGB);
1141
        ColorModel rgbCM = new DirectColorModel
1142
            (rgbCS, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000,
1143
             false, DataBuffer.TYPE_BYTE);
1144
1145
        PaintContext pctx = paint.createContext(rgbCM, devBounds, usrBounds, 
1146
                                                at, getRenderingHints());
1147
        PDFXObject imageInfo = pdfDoc.getImage
1148
            ("TempImage:" + pctx.toString());
1149
        if (imageInfo != null) {
1150
            resourceContext.getPDFResources().addXObject(imageInfo);
1151
        } else {
1152
            Raster r = pctx.getRaster(devX, devY, devW, devH);
1153
            WritableRaster wr = (WritableRaster)r;
1154
            wr = wr.createWritableTranslatedChild(0, 0);
1155
1156
            ColorModel pcm = pctx.getColorModel();
1157
            BufferedImage bi = new BufferedImage
1158
                (pcm, wr, pcm.isAlphaPremultiplied(), null);
1159
            final byte [] rgb  = new byte[devW*devH*3];
1160
            final int  [] line = new int[devW];
1161
            final byte [] mask;
1162
            int x, y, val, rgbIdx=0;
1163
        
1164
            if (pcm.hasAlpha()) {
1165
                mask = new byte[devW*devH];
1166
                int maskIdx=0;
1167
                for (y=0; y<devH; y++) {
1168
                    bi.getRGB(0, y, devW, 1, line, 0, devW);
1169
                    for (x=0; x< devW; x++) {
1170
                        val = line[x];
1171
                        mask[maskIdx++] = (byte)(val>>>24);
1172
                        rgb [rgbIdx++]  = (byte)((val>>16)&0x0FF);
1173
                        rgb [rgbIdx++]  = (byte)((val>> 8)&0x0FF);
1174
                        rgb [rgbIdx++]  = (byte)((val    )&0x0FF);
1175
                    }
1176
                }
1177
            } else {
1178
                mask = null;
1179
                for (y=0; y<devH; y++) {
1180
                    bi.getRGB(0, y, devW, 1, line, 0, devW);
1181
                    for (x=0; x< devW; x++) {
1182
                        val = line[x];
1183
                        rgb [rgbIdx++]  = (byte)((val>>16)&0x0FF);
1184
                        rgb [rgbIdx++]  = (byte)((val>> 8)&0x0FF);
1185
                        rgb [rgbIdx++]  = (byte)((val    )&0x0FF);
1186
                    }
1187
                }
1188
            }
1189
1190
            String maskRef = null;
1191
            if (mask != null) {
1192
                BitmapImage fopimg = new BitmapImage
1193
                    ("TempImageMask:"+pctx.toString(), devW, devH, mask, null);
1194
                fopimg.setColorSpace(new PDFColorSpace(PDFColorSpace.DEVICE_GRAY));
1195
                PDFXObject xobj = pdfDoc.addImage(resourceContext, fopimg);
1196
                maskRef = xobj.referencePDF();
1197
1198
                if (outputStream != null) {
1199
                    try {
1200
                        this.pdfDoc.output(outputStream);
1201
                    } catch (IOException ioe) {
1202
                        // ignore exception, will be thrown again later
1203
                    }
1204
                }
1205
            }
1206
            BitmapImage fopimg;
1207
            fopimg = new BitmapImage("TempImage:" + pctx.toString(),
1208
                                     devW, devH, rgb, maskRef);
1209
            fopimg.setTransparent(new PDFColor(255, 255, 255));
1210
            imageInfo = pdfDoc.addImage(resourceContext, fopimg);
1211
            if (outputStream != null) {
1212
                try {
1213
                    this.pdfDoc.output(outputStream);
1214
                } catch (IOException ioe) {
1215
                    // ignore exception, will be thrown again later
1216
                }
1217
            }
1218
        }
1219
1220
        currentStream.write("q\n");
1221
        writeClip(shape);
1222
        currentStream.write("" + usrW + " 0 0 " + (-usrH) + " " + usrX
1223
                            + " " + (usrY + usrH) + " cm\n" + "/Im"
1224
                            + imageInfo.getXNumber() + " Do\nQ\n");
1225
        return true;
1226
    }
1227
1066
    /**
1228
    /**
1067
     * Apply the stroke to the PDF.
1229
     * Apply the stroke to the PDF.
1068
     * This takes the java stroke and outputs the appropriate settings
1230
     * This takes the java stroke and outputs the appropriate settings
Lines 1512-1518 Link Here
1512
1674
1513
        Paint paint = getPaint();
1675
        Paint paint = getPaint();
1514
        if (graphicsState.setPaint(paint)) {
1676
        if (graphicsState.setPaint(paint)) {
1515
            applyPaint(paint, true);
1677
            if (!applyPaint(paint, true)) {
1678
                // Use the shape to 'clip' the paint contents.
1679
                applyUnknownPaint(paint, s);
1680
1681
                if (newClip || newTransform) {
1682
                    currentStream.write("Q\n");
1683
                    graphicsState.pop();
1684
                }
1685
                return;
1686
            }
1516
        }
1687
        }
1517
1688
1518
        //PathIterator iter = s.getPathIterator(getTransform());
1689
        //PathIterator iter = s.getPathIterator(getTransform());

Return to bug 37236