]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Bugzilla #37236:
authorJeremias Maerki <jeremias@apache.org>
Wed, 26 Oct 2005 21:07:47 +0000 (21:07 +0000)
committerJeremias Maerki <jeremias@apache.org>
Wed, 26 Oct 2005 21:07:47 +0000 (21:07 +0000)
Fix for gradients and patterns for SVG to PDF transcoding.
Improvement for break-out handling in PDF Renderer.
Submitted by: Thomas Deweese <deweese.at.apache.org>

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@328731 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/fop/pdf/PDFFactory.java
src/java/org/apache/fop/pdf/PDFState.java
src/java/org/apache/fop/render/pdf/PDFRenderer.java
src/java/org/apache/fop/render/ps/PSGraphics2D.java
src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java
src/java/org/apache/fop/svg/PDFGraphics2D.java

index bacb3251c1dd41a90b692489931d30771c859160..5ef2a72a194164c4f5c7f00346a8e571f36ccfdd 100644 (file)
@@ -688,7 +688,7 @@ public class PDFFactory {
     public PDFPattern makeGradient(PDFResourceContext res, boolean radial,
                                    PDFColorSpace theColorspace,
                                    List theColors, List theBounds,
-                                   List theCoords) {
+                                   List theCoords, List theMatrix) {
         PDFShading myShad;
         PDFFunction myfunky;
         PDFFunction myfunc;
@@ -770,7 +770,7 @@ public class PDFFactory {
 
         }
 
-        myPattern = makePattern(res, 2, myShad, null, null, null);
+        myPattern = makePattern(res, 2, myShad, null, null, theMatrix);
 
         return (myPattern);
     }
index f2ebe6ea9893fa591dfe459d90839787bcd4d1fc..15f4527c2c129cad4ee64c5ae8fc0d3194e4457c 100644 (file)
@@ -68,11 +68,11 @@ public class PDFState {
         Data copy;
         try {
             copy = (Data)getData().clone();
+            getData().resetTransform();
         } catch (CloneNotSupportedException e) {
             throw new RuntimeException(e.getMessage());
         }
         stateStack.add(copy);
-        data.resetConcatenations();
     }
 
     /**
@@ -280,16 +280,15 @@ public class PDFState {
      * @return the calculate combined transform for the current state
      */
     public AffineTransform getTransform() {
-        AffineTransform tf;
-        AffineTransform at = new AffineTransform();
-        for (Iterator iter = stateStack.iterator(); iter.hasNext();) {
-            Data d = (Data)iter.next();
-            tf = d.transform;
-            at.concatenate(tf);
-        }
-        at.concatenate(getData().transform);
-
-        return at;
+       AffineTransform tf;
+       AffineTransform at = new AffineTransform();
+       for (Iterator iter = stateStack.iterator(); iter.hasNext();) {
+           Data d = (Data)iter.next();
+           tf = d.transform;
+           at.concatenate(tf);
+       }
+       at.concatenate(getData().transform);
+       return at;
     }
 
     /**
@@ -339,8 +338,6 @@ public class PDFState {
         public String fontName = "";
         public Shape clip = null;
         public PDFGState gstate = null;
-        /** Log of all concatenation operations */
-        public List concatenations = null;
 
         
         /** @see java.lang.Object#clone() */
@@ -362,19 +359,20 @@ public class PDFState {
             obj.fontName = this.fontName;
             obj.clip = this.clip;
             obj.gstate = this.gstate;
-            if (this.concatenations != null) {
-                obj.concatenations = new java.util.ArrayList(this.concatenations);
-            }
             return obj;
         }
         
         /**
-         * Forgets the previously made AffineTransform concatenations.
+         * Get the current Transform.
          */
-        public void resetConcatenations() {
-            this.concatenations = null;
+        public AffineTransform getTransform() {
+            return transform;
         }
-        
+
+        public void resetTransform() {
+            transform = new AffineTransform();
+        }
+
         /**
          * Concatenate the given AffineTransform with the current thus creating
          * a new viewport. Note that all concatenation operations are logged
@@ -383,16 +381,12 @@ public class PDFState {
          * @param at Transformation to perform
          */
         public void concatenate(AffineTransform at) {
-            if (this.concatenations == null) {
-                this.concatenations = new java.util.ArrayList();
-            }
-            concatenations.add(at);
             transform.concatenate(at);
         }
         
         /** @see java.lang.Object#toString() */
         public String toString() {
-            return super.toString() + ", " + this.transform + " | " + this.concatenations;
+            return super.toString() + ", " + this.transform;
         }
     }
 }
index 69a96f432ba43cb630e6df14e91924f9553e8b9c..ed129317b85c8ec69bb453fe2fd1a4bf6658b9a5 100644 (file)
@@ -928,21 +928,18 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
         comment("------ restoring context after break-out...");
         PDFState.Data data;
         Iterator i = breakOutList.iterator();
+        double[] matrix = new double[6];
         while (i.hasNext()) {
             data = (PDFState.Data)i.next();
             currentState.push();
             saveGraphicsState();
-            if (data.concatenations != null) {
-                Iterator tr = data.concatenations.iterator();
-                while (tr.hasNext()) {
-                    AffineTransform at = (AffineTransform)tr.next();
-                    currentState.setTransform(at);
-                    double[] matrix = new double[6];
-                    at.getMatrix(matrix);
-                    tempctm = new CTM(matrix[0], matrix[1], matrix[2], matrix[3], 
-                            matrix[4] * 1000, matrix[5] * 1000);
-                    currentStream.add(CTMHelper.toPDFString(tempctm) + " cm\n");
-                }
+            AffineTransform at = data.getTransform();
+            if (!at.isIdentity()) {
+                currentState.setTransform(at);
+                at.getMatrix(matrix);
+                tempctm = new CTM(matrix[0], matrix[1], matrix[2], matrix[3], 
+                                  matrix[4] * 1000, matrix[5] * 1000);
+                currentStream.add(CTMHelper.toPDFString(tempctm) + " cm\n");
             }
             //TODO Break-out: Also restore items such as line width and color
             //Left out for now because all this painting stuff is very
index 4bfea700a8bbc12c0b7f6415af06f70a36bee96a..4648400315c2ae0f32f1b36a9ab645c821623160 100644 (file)
@@ -134,6 +134,15 @@ public class PSGraphics2D extends AbstractGraphics2D {
      */
     public PSGraphics2D(PSGraphics2D g) {
         super(g);
+
+        setPSGenerator(g.gen);
+        this.clippingDisabled = g.clippingDisabled;
+        this.font             = g.font;
+        this.overrideFont     = g.overrideFont;
+        this.currentFontName  = g.currentFontName;
+        this.currentFontSize  = g.currentFontSize;
+        this.currentColour    = g.currentColour;
+        this.fontInfo         = g.fontInfo;
     }
 
     /**
index d9085774345c0c62138850382f633a3997ab71b3..85e5f667f4084f2290071a3e3c0e6707f2092b40 100644 (file)
@@ -305,12 +305,19 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D
         resourceContext = page;
         pdfContext.setCurrentPage(page);
         pageRef = page.referencePDF();
-        graphicsState.setTransform(new AffineTransform(1.0, 0.0, 0.0, -1.0, 0.0, (double)height));
+
+        AffineTransform at = new AffineTransform(1.0, 0.0, 0.0, -1.0, 
+                                                 0.0, (double)height);
         currentStream.write("1 0 0 -1 0 " + height + " cm\n");
         if (svgWidth != 0) {
-            currentStream.write("" + PDFNumber.doubleOut(width / svgWidth) + " 0 0 "
-                    + PDFNumber.doubleOut(height / svgHeight) + " 0 0 cm\n");
+            double scaleX = width / svgWidth;
+            double scaleY = height / svgHeight;
+            at.scale(scaleX, scaleY);
+            currentStream.write("" + PDFNumber.doubleOut(scaleX) + " 0 0 "
+                                + PDFNumber.doubleOut(scaleY) + " 0 0 cm\n");
         }
+        // Remember the transform we installed.
+        graphicsState.setTransform(at);
 
         pdfContext.increasePageCount();
     }
index 4d91422d3bd281601ead1773f55f8b89c8582f44..b3a49da375e80b7ea3660d7c57b1c2c8295ed144 100644 (file)
@@ -278,6 +278,15 @@ public class PDFGraphics2D extends AbstractGraphics2D {
         return currentStream.toString();
     }
 
+    /**
+     * Get the string buffer from the currentStream, containing all
+     * the commands written into this Grpahics so far.
+     * @return the StringBuffer containing the PDF markup
+     */
+    public StringBuffer getBuffer() {
+        return currentStream.getBuffer();
+    }
+
     /**
      * Set the Grpahics context.
      * @param c the graphics context to use
@@ -829,17 +838,27 @@ public class PDFGraphics2D extends AbstractGraphics2D {
             LinearGradientPaint gp = (LinearGradientPaint)paint;
             Color[] cols = gp.getColors();
             float[] fractions = gp.getFractions();
-            Point2D p1 = gp.getStartPoint();
-            Point2D p2 = gp.getEndPoint();
+
             //MultipleGradientPaint.CycleMethodEnum cycenum = gp.getCycleMethod();
             //boolean cyclic = (cycenum == MultipleGradientPaint.REPEAT);
-            AffineTransform transform = graphicsState.getTransform();
-            transform.concatenate(gp.getTransform());
+            // This code currently doesn't support 'repeat' as PDF has
+            // no way to support this (we need to rasterize).
+
+            // Build proper transform from gradient space to page space
+            // ('Patterns' don't get userspace transform).
+            AffineTransform transform;
+            transform = new AffineTransform(graphicsState.getTransform());
             transform.concatenate(getTransform());
+            transform.concatenate(gp.getTransform());
 
-            p1 = transform.transform(p1, null);
-            p2 = transform.transform(p2, null);
+            List theMatrix = new java.util.ArrayList();
+            double [] mat = new double[6];
+            transform.getMatrix(mat);
+            for (int idx=0; idx<mat.length; idx++) 
+                theMatrix.add(new Double(mat[idx]));
 
+            Point2D p1 = gp.getStartPoint();
+            Point2D p2 = gp.getEndPoint();
             List theCoords = new java.util.ArrayList();
             theCoords.add(new Double(p1.getX()));
             theCoords.add(new Double(p1.getY()));
@@ -874,46 +893,56 @@ public class PDFGraphics2D extends AbstractGraphics2D {
                 }
             }
 
-            PDFColorSpace aColorSpace = new PDFColorSpace(PDFColorSpace.DEVICE_RGB);
+            PDFColorSpace aColorSpace;
+            aColorSpace = new PDFColorSpace(PDFColorSpace.DEVICE_RGB);
             PDFPattern myPat = pdfDoc.getFactory().makeGradient(
                     resourceContext, false, aColorSpace,
-                    someColors, theBounds, theCoords);
+                    someColors, theBounds, theCoords, theMatrix);
             currentStream.write(myPat.getColorSpaceOut(fill));
 
         } else if (paint instanceof RadialGradientPaint) {
             RadialGradientPaint rgp = (RadialGradientPaint)paint;
 
+            AffineTransform transform;
+            transform = new AffineTransform(graphicsState.getTransform());
+            transform.concatenate(getTransform());
+            transform.concatenate(rgp.getTransform());
+
+            List theMatrix = new java.util.ArrayList();
+            double [] mat = new double[6];
+            transform.getMatrix(mat);
+            for (int idx=0; idx<mat.length; idx++) 
+                theMatrix.add(new Double(mat[idx]));
+
             double ar = rgp.getRadius();
             Point2D ac = rgp.getCenterPoint();
             Point2D af = rgp.getFocusPoint();
-            AffineTransform transform = graphicsState.getTransform();
-            AffineTransform gradt = rgp.getTransform();
-            transform.concatenate(gradt);
-
-            // find largest scaling for the radius
-            double scale = gradt.getScaleX();
-            if (gradt.getScaleY() > scale) {
-                scale = gradt.getScaleY();
-            }
-            ar = ar * scale;
-            ac = transform.transform(ac, null);
-            af = transform.transform(af, null);
 
             List theCoords = new java.util.ArrayList();
-            // the center point af must be within the circle with
-            // radius ar centered at ac
-            theCoords.add(new Double(af.getX()));
-            theCoords.add(new Double(af.getY()));
+            double dx = af.getX()-ac.getX();
+            double dy = af.getY()-ac.getY();
+            double d = Math.sqrt(dx*dx+dy*dy);
+            if (d > ar) {
+                // the center point af must be within the circle with
+                // radius ar centered at ac so limit it to that.
+                double scale = (ar*.9999)/d;
+                dx = dx*scale;
+                dy = dy*scale;
+            }
+
+            theCoords.add(new Double(ac.getX()+dx)); // Fx
+            theCoords.add(new Double(ac.getY()+dy)); // Fy
             theCoords.add(new Double(0));
-            theCoords.add(new Double(ac.getX())); // Fx
-            theCoords.add(new Double(ac.getY())); // Fy
+            theCoords.add(new Double(ac.getX()));
+            theCoords.add(new Double(ac.getY()));
             theCoords.add(new Double(ar));
 
             Color[] cols = rgp.getColors();
             List someColors = new java.util.ArrayList();
             for (int count = 0; count < cols.length; count++) {
                 Color cc = cols[count];
-                someColors.add(new PDFColor(cc.getRed(), cc.getGreen(), cc.getBlue()));
+                someColors.add(new PDFColor(cc.getRed(), cc.getGreen(), 
+                                            cc.getBlue()));
             }
 
             float[] fractions = rgp.getFractions();
@@ -922,10 +951,12 @@ public class PDFGraphics2D extends AbstractGraphics2D {
                 float offset = fractions[count];
                 theBounds.add(new Double(offset));
             }
-            PDFColorSpace colSpace = new PDFColorSpace(PDFColorSpace.DEVICE_RGB);
-            PDFPattern myPat = pdfDoc.getFactory().makeGradient(
-                                    resourceContext, true, colSpace,
-                                    someColors, theBounds, theCoords);
+            PDFColorSpace colSpace;
+            colSpace = new PDFColorSpace(PDFColorSpace.DEVICE_RGB);
+
+            PDFPattern myPat = pdfDoc.getFactory().makeGradient
+                (resourceContext, true, colSpace,
+                 someColors, theBounds, theCoords, theMatrix);
 
             currentStream.write(myPat.getColorSpaceOut(fill));
 
@@ -937,7 +968,6 @@ public class PDFGraphics2D extends AbstractGraphics2D {
 
     private void createPattern(PatternPaint pp, boolean fill) {
         preparePainting();
-        Rectangle2D rect = pp.getPatternRect();
 
         FontInfo fontInfo = new FontInfo();
         FontSetup.setup(fontInfo, null);
@@ -947,41 +977,64 @@ public class PDFGraphics2D extends AbstractGraphics2D {
         PDFGraphics2D pattGraphic = new PDFGraphics2D(textAsShapes, fontInfo,
                                         pdfDoc, context, pageRef,
                                         "", 0);
-        pattGraphic.gc = (GraphicContext)this.gc.clone();
+        pattGraphic.setGraphicContext(new GraphicContext());
         pattGraphic.gc.validateTransformStack();
+        pattGraphic.setRenderingHints(this.getRenderingHints());
         pattGraphic.setOutputStream(outputStream);
 
         GraphicsNode gn = pp.getGraphicsNode();
-        gn.paint(pattGraphic);
-
-        StringWriter pattStream = new StringWriter();
-        pattStream.write("q\n");
-
-        // this makes the pattern the right way up, since
-        // it is outside the original transform around the
-        // whole svg document
-        pattStream.write("1 0 0 -1 0 " + (rect.getHeight() + rect.getY()) + " cm\n");
+        Rectangle2D gnBBox = gn.getBounds();
+        Rectangle2D rect = pp.getPatternRect();
 
-        pattStream.write(pattGraphic.getString());
-        pattStream.write("Q");
+        // if (!pp.getOverflow()) {
+            gn.paint(pattGraphic);
+        // } else {
+        // /* Commented out until SVN version of Batik is included */
+        //     // For overflow we need to paint the content from
+        //     // all the tiles who's overflow will intersect one
+        //     // tile (left->right, top->bottom).  Then we can
+        //     // simply replicate that tile as normal.
+        //     double gnMinX = gnBBox.getX();
+        //     double gnMaxX = gnBBox.getX() + gnBBox.getWidth();
+        //     double gnMinY = gnBBox.getY();
+        //     double gnMaxY = gnBBox.getY() + gnBBox.getHeight();
+        //     double patMaxX = rect.getX() + rect.getWidth();
+        //     double patMaxY = rect.getY() + rect.getHeight();
+        //     double stepX = rect.getWidth();
+        //     double stepY = rect.getHeight();            
+        // 
+        //     int startX = (int)((rect.getX() - gnMaxX)/stepX);
+        //     int startY = (int)((rect.getY() - gnMaxY)/stepY);
+        // 
+        //     int endX   = (int)((patMaxX - gnMinX)/stepX);
+        //     int endY   = (int)((patMaxY - gnMinY)/stepY);
+        // 
+        //     pattGraphic.translate(startX*stepX, startY*stepY);
+        //     for (int yIdx=startY; yIdx<=endY; yIdx++) {
+        //         for (int xIdx=startX; xIdx<=endX; xIdx++) {
+        //             gn.paint(pattGraphic);
+        //             pattGraphic.translate(stepX,0);
+        //         }
+        //         pattGraphic.translate(-(endX-startX+1)*stepX, stepY);
+        //     }
+        // }
 
         List bbox = new java.util.ArrayList();
-        bbox.add(new Double(0));
-        bbox.add(new Double(0));
-        bbox.add(new Double(rect.getWidth() + rect.getX()));
-        bbox.add(new Double(rect.getHeight() + rect.getY()));
-
-        List translate = new java.util.ArrayList();
-        AffineTransform pattt = pp.getPatternTransform();
-        pattt.translate(rect.getWidth() + rect.getX(), rect.getHeight() + rect.getY());
-        double[] flatmatrix = new double[6];
-        pattt.getMatrix(flatmatrix);
-        translate.add(new Double(flatmatrix[0]));
-        translate.add(new Double(flatmatrix[1]));
-        translate.add(new Double(flatmatrix[2]));
-        translate.add(new Double(flatmatrix[3]));
-        translate.add(new Double(flatmatrix[4]));
-        translate.add(new Double(flatmatrix[5]));
+        bbox.add(new Double(rect.getX()));
+        bbox.add(new Double(rect.getHeight()+rect.getY()));
+        bbox.add(new Double(rect.getWidth() +rect.getX()));
+        bbox.add(new Double(rect.getY()));
+
+        AffineTransform transform;
+        transform = new AffineTransform(graphicsState.getTransform());
+        transform.concatenate(getTransform());
+        transform.concatenate(pp.getPatternTransform());
+
+        List theMatrix = new java.util.ArrayList();
+        double [] mat = new double[6];
+        transform.getMatrix(mat);
+        for (int idx=0; idx<mat.length; idx++) 
+            theMatrix.add(new Double(mat[idx]));
 
         /** @todo see if pdfDoc and res can be linked here,
         (currently res <> PDFDocument's resources) so addFonts() 
@@ -991,7 +1044,8 @@ public class PDFGraphics2D extends AbstractGraphics2D {
         PDFPattern myPat = pdfDoc.getFactory().makePattern(
                                 resourceContext, 1, res, 1, 1, bbox,
                                 rect.getWidth(), rect.getHeight(),
-                                translate, null, pattStream.getBuffer());
+                                theMatrix, null, 
+                                pattGraphic.getBuffer());
 
         currentStream.write(myPat.getColorSpaceOut(fill));