You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by lb...@apache.org on 2013/11/13 16:24:27 UTC

svn commit: r1541551 [1/3] - in /xmlgraphics/fop/trunk: ./ lib/ src/java/org/apache/fop/pdf/ src/java/org/apache/fop/render/ps/ src/java/org/apache/fop/render/ps/svg/ src/java/org/apache/fop/render/shading/ src/java/org/apache/fop/svg/ test/java/org/ap...

Author: lbernardo
Date: Wed Nov 13 15:24:26 2013
New Revision: 1541551

URL: http://svn.apache.org/r1541551
Log:
FOP-2313: add support for svg gradients when generating PostScript; most code authored by Robert Meyer with a small contribution by Athanasios Giannimaras.

Added:
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSFunction.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSPattern.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSSVGGraphics2D.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSShading.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/shading/
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/shading/Function.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/shading/FunctionDelegate.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/shading/FunctionPattern.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/shading/GradientFactory.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/shading/GradientRegistrar.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/shading/PDFGradientFactory.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/shading/PSGradientFactory.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/shading/Pattern.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/shading/Shading.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/shading/ShadingPattern.java   (with props)
    xmlgraphics/fop/trunk/test/java/org/apache/fop/render/ps/svg/
    xmlgraphics/fop/trunk/test/java/org/apache/fop/render/ps/svg/PSSVGGraphics2DTestCase.java   (with props)
    xmlgraphics/fop/trunk/test/java/org/apache/fop/render/ps/svg/PSSVGLinearGraphics2DTestCase.java   (with props)
    xmlgraphics/fop/trunk/test/java/org/apache/fop/render/ps/svg/axial-shading-expected.dat
    xmlgraphics/fop/trunk/test/java/org/apache/fop/render/ps/svg/expected.ps
Modified:
    xmlgraphics/fop/trunk/build.xml
    xmlgraphics/fop/trunk/lib/xmlgraphics-commons-svn-trunk.jar
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFactory.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFunction.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFPattern.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFShading.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSImageHandlerSVG.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFGraphics2D.java

Modified: xmlgraphics/fop/trunk/build.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/build.xml?rev=1541551&r1=1541550&r2=1541551&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/build.xml (original)
+++ xmlgraphics/fop/trunk/build.xml Wed Nov 13 15:24:26 2013
@@ -579,6 +579,7 @@ list of possible build targets.
       <include name="org/apache/fop/util/Finalizable.class"/>
       <include name="org/apache/fop/util/CharUtilities.class"/>
       <include name="org/apache/fop/util/DecimalFormatCache*.class"/>
+      <include name="org/apache/fop/render/shading/**"/>
     </patternset>
 <!-- PDF transcoder -->
     <patternset>

Modified: xmlgraphics/fop/trunk/lib/xmlgraphics-commons-svn-trunk.jar
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/lib/xmlgraphics-commons-svn-trunk.jar?rev=1541551&r1=1541550&r2=1541551&view=diff
==============================================================================
Binary files - no diff available.

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFactory.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFactory.java?rev=1541551&r1=1541550&r2=1541551&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFactory.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFactory.java Wed Nov 13 15:24:26 2013
@@ -310,12 +310,7 @@ public class PDFFactory {
                                                theFunctionDataStream,
                                                theFilter);
 
-        PDFFunction oldfunc = getDocument().findFunction(function);
-        if (oldfunc == null) {
-            getDocument().registerObject(function);
-        } else {
-            function = oldfunc;
-        }
+        function = registerFunction(function);
         return (function);
     }
 
@@ -352,12 +347,7 @@ public class PDFFactory {
         PDFFunction function = new PDFFunction(theFunctionType, theDomain,
                                                theRange, theCZero, theCOne,
                                                theInterpolationExponentN);
-        PDFFunction oldfunc = getDocument().findFunction(function);
-        if (oldfunc == null) {
-            getDocument().registerObject(function);
-        } else {
-            function = oldfunc;
-        }
+        function = registerFunction(function);
         return (function);
     }
 
@@ -407,12 +397,7 @@ public class PDFFactory {
                                                theRange, theFunctions,
                                                theBounds, theEncode);
 
-        PDFFunction oldfunc = getDocument().findFunction(function);
-        if (oldfunc == null) {
-            getDocument().registerObject(function);
-        } else {
-            function = oldfunc;
-        }
+        function = registerFunction(function);
         return (function);
     }
 
@@ -434,14 +419,23 @@ public class PDFFactory {
                                                theRange,
                                                theFunctionDataStream);
 
+        function = registerFunction(function);
+        return (function);
+
+    }
+
+    /**
+     * Registers a function against the document
+     * @param function The function to register
+     */
+    public PDFFunction registerFunction(PDFFunction function) {
         PDFFunction oldfunc = getDocument().findFunction(function);
         if (oldfunc == null) {
             getDocument().registerObject(function);
         } else {
             function = oldfunc;
         }
-        return (function);
-
+        return function;
     }
 
     /* ========================= shadings ================================== */
@@ -481,20 +475,7 @@ public class PDFFactory {
                                             theBBox, theAntiAlias, theDomain,
                                             theMatrix, theFunction);
 
-        PDFShading oldshad = getDocument().findShading(shading);
-        if (oldshad == null) {
-            getDocument().registerObject(shading);
-        } else {
-            shading = oldshad;
-        }
-
-        // add this shading to resources
-        if (res != null) {
-            res.getPDFResources().addShading(shading);
-        } else {
-            getDocument().getResources().addShading(shading);
-        }
-
+        shading = registerShading(res, shading);
         return (shading);
     }
 
@@ -534,18 +515,7 @@ public class PDFFactory {
                                             theDomain, theFunction,
                                             theExtend);
 
-        PDFShading oldshad = getDocument().findShading(shading);
-        if (oldshad == null) {
-            getDocument().registerObject(shading);
-        } else {
-            shading = oldshad;
-        }
-
-        if (res != null) {
-            res.getPDFResources().addShading(shading);
-        } else {
-            getDocument().getResources().addShading(shading);
-        }
+        shading = registerShading(res, shading);
 
         return (shading);
     }
@@ -591,18 +561,7 @@ public class PDFFactory {
                                             theBitsPerFlag, theDecode,
                                             theFunction);
 
-        PDFShading oldshad = getDocument().findShading(shading);
-        if (oldshad == null) {
-            getDocument().registerObject(shading);
-        } else {
-            shading = oldshad;
-        }
-
-        if (res != null) {
-            res.getPDFResources().addShading(shading);
-        } else {
-            getDocument().getResources().addShading(shading);
-        }
+        shading = registerShading(res, shading);
 
         return (shading);
     }
@@ -645,6 +604,17 @@ public class PDFFactory {
                                             theBitsPerComponent, theDecode,
                                             theVerticesPerRow, theFunction);
 
+        shading = registerShading(res, shading);
+
+        return (shading);
+    }
+
+    /**
+     * Registers a shading object against the document
+     * @param res The PDF resource context
+     * @param shading The shading object to be registered
+     */
+    public PDFShading registerShading(PDFResourceContext res, PDFShading shading) {
         PDFShading oldshad = getDocument().findShading(shading);
         if (oldshad == null) {
             getDocument().registerObject(shading);
@@ -652,13 +622,13 @@ public class PDFFactory {
             shading = oldshad;
         }
 
+        // add this shading to resources
         if (res != null) {
             res.getPDFResources().addShading(shading);
         } else {
             getDocument().getResources().addShading(shading);
         }
-
-        return (shading);
+        return shading;
     }
 
     /* ========================= patterns ================================== */
@@ -707,6 +677,22 @@ public class PDFFactory {
         return (pattern);
     }
 
+    public PDFPattern registerPattern(PDFResourceContext res, PDFPattern pattern) {
+        PDFPattern oldpatt = getDocument().findPattern(pattern);
+        if (oldpatt == null) {
+            getDocument().registerObject(pattern);
+        } else {
+            pattern = oldpatt;
+        }
+
+        if (res != null) {
+            res.getPDFResources().addPattern(pattern);
+        } else {
+            getDocument().getResources().addPattern(pattern);
+        }
+        return pattern;
+    }
+
     /**
      * Make a smooth shading pattern
      *

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFunction.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFunction.java?rev=1541551&r1=1541550&r2=1541551&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFunction.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFFunction.java Wed Nov 13 15:24:26 2013
@@ -22,6 +22,10 @@ package org.apache.fop.pdf;
 // Java...
 import java.util.List;
 
+import org.apache.fop.render.shading.Function;
+import org.apache.fop.render.shading.FunctionDelegate;
+import org.apache.fop.render.shading.FunctionPattern;
+
 /**
  * class representing a PDF Function.
  *
@@ -33,126 +37,9 @@ import java.util.List;
  *
  * All PDF Functions have a FunctionType (0,2,3, or 4), a Domain, and a Range.
  */
-public class PDFFunction extends PDFObject {
-    // Guts common to all function types
-
-    /**
-     * Required: The Type of function (0,2,3,4) default is 0.
-     */
-    protected int functionType = 0;    // Default
-
-    /**
-     * Required: 2 * m Array of Double numbers which are possible inputs to the function
-     */
-    protected List domain = null;
-
-    /**
-     * Required: 2 * n Array of Double numbers which are possible outputs to the function
-     */
-    protected List range = null;
-
-    /* ********************TYPE 0***************************** */
-    // FunctionType 0 specific function guts
-
-    /**
-     * Required: Array containing the Integer size of the Domain and Range, respectively.
-     * Note: This is really more like two seperate integers, sizeDomain, and sizeRange,
-     * but since they're expressed as an array in PDF, my implementation reflects that.
-     */
-    protected List size = null;
-
-    /**
-     * Required for Type 0: Number of Bits used to represent each sample value.
-     * Limited to 1,2,4,8,12,16,24, or 32
-     */
-    protected int bitsPerSample = 1;
-
-    /**
-     * Optional for Type 0: order of interpolation between samples.
-     * Limited to linear (1) or cubic (3). Default is 1
-     */
-    protected int order = 1;
-
-    /**
-     * Optional for Type 0: A 2 * m array of Doubles which provides a
-     * linear mapping of input values to the domain.
-     *
-     * Required for Type 3: A 2 * k array of Doubles that, taken
-     * in pairs, map each subset of the domain defined by Domain
-     * and the Bounds array to the domain of the corresponding function.
-     * Should be two values per function, usually (0,1),
-     * as in [0 1 0 1] for 2 functions.
-     */
-    protected List encode = null;
+public class PDFFunction extends PDFObject implements Function {
 
-    /**
-     * Optional for Type 0: A 2 * n array of Doubles which provides
-     * a linear mapping of sample values to the range. Defaults to Range.
-     */
-    protected List decode = null;
-
-    /**
-     * Optional For Type 0: A stream of sample values
-     */
-
-    /**
-     * Required For Type 4: Postscript Calculator function
-     * composed of arithmetic, boolean, and stack operators + boolean constants
-     */
-    protected StringBuffer functionDataStream = null;
-
-    /**
-     * Required (possibly) For Type 0: A vector of Strings for the
-     * various filters to be used to decode the stream.
-     * These are how the string is compressed. Flate, LZW, etc.
-     */
-    protected List filter = null;
-    /* *************************TYPE 2************************** */
-
-    /**
-     * Required For Type 2: An Array of n Doubles defining
-     * the function result when x=0. Default is [0].
-     */
-    protected List cZero = null;
-
-    /**
-     * Required For Type 2: An Array of n Doubles defining
-     * the function result when x=1. Default is [1].
-     */
-    protected List cOne = null;
-
-    /**
-     * Required for Type 2: The interpolation exponent.
-     * Each value x will return n results.
-     * Must be greater than 0.
-     */
-    protected double interpolationExponentN = 1;
-
-    /* *************************TYPE 3************************** */
-
-    /**
-     * Required for Type 3: An vector of PDFFunctions which
-     * form an array of k single input functions making up
-     * the stitching function.
-     */
-    protected List functions = null;
-
-    /**
-     * Optional for Type 3: An array of (k-1) Doubles that,
-     * in combination with Domain, define the intervals to which
-     * each function from the Functions array apply. Bounds
-     * elements must be in order of increasing magnitude,
-     * and each value must be within the value of Domain.
-     * k is the number of functions.
-     * If you pass null, it will output (1/k) in an array of k-1 elements.
-     * This makes each function responsible for an equal amount of the stitching function.
-     * It makes the gradient even.
-     */
-    protected List bounds = null;
-    // See encode above, as it's also part of Type 3 Functions.
-
-    /* *************************TYPE 4************************** */
-    // See 'data' above.
+    private FunctionDelegate delegate;
 
     /**
      * create an complete Function object of Type 0, A Sampled function.
@@ -211,26 +98,13 @@ public class PDFFunction extends PDFObje
      * @param theFunctionType This is the type of function (0,2,3, or 4).
      * It should be 0 as this is the constructor for sampled functions.
      */
-    public PDFFunction(int theFunctionType, List theDomain,
-            List theRange, List theSize, int theBitsPerSample,
-            int theOrder, List theEncode, List theDecode,
-            StringBuffer theFunctionDataStream, List theFilter) {
-        super();
-
-        this.functionType = 0;      // dang well better be 0;
-        this.size = theSize;
-        this.bitsPerSample = theBitsPerSample;
-        this.order = theOrder;      // int
-        this.encode = theEncode;    // vector of int
-        this.decode = theDecode;    // vector of int
-        this.functionDataStream = theFunctionDataStream;
-        this.filter = theFilter;    // vector of Strings
-
-        // the domain and range are actually two dimensional arrays.
-        // so if there's not an even number of items, bad stuff
-        // happens.
-        this.domain = theDomain;
-        this.range = theRange;
+    public PDFFunction(int theFunctionType, List<Double> theDomain,
+                       List<Double> theRange, List<Double> theSize, int theBitsPerSample,
+                       int theOrder, List<Double> theEncode, List<Double> theDecode,
+                       StringBuffer theFunctionDataStream, List<String> theFilter) {
+        delegate = new FunctionDelegate(this, theFunctionType, theDomain, theRange,
+                theSize, theBitsPerSample, theOrder, theEncode, theDecode,
+                theFunctionDataStream, theFilter);
     }
 
     /**
@@ -260,20 +134,11 @@ public class PDFFunction extends PDFObje
      * PDF Spec page 268
      * @param theFunctionType The type of the function, which should be 2.
      */
-    public PDFFunction(int theFunctionType, List theDomain,
-                       List theRange, List theCZero, List theCOne,
+    public PDFFunction(int theFunctionType, List<Double> theDomain,
+                       List<Double> theRange, List<Double> theCZero, List<Double> theCOne,
                        double theInterpolationExponentN) {
-        super();
-
-        this.functionType = 2;    // dang well better be 2;
-
-        this.cZero = theCZero;
-        this.cOne = theCOne;
-        this.interpolationExponentN = theInterpolationExponentN;
-
-
-        this.domain = theDomain;
-        this.range = theRange;
+        delegate = new FunctionDelegate(this, theFunctionType, theDomain, theRange,
+                theCZero, theCOne, theInterpolationExponentN);
 
     }
 
@@ -312,18 +177,11 @@ public class PDFFunction extends PDFObje
      * @param theFunctionType This is the function type. It should be 3,
      * for a stitching function.
      */
-    public PDFFunction(int theFunctionType, List theDomain,
-                       List theRange, List theFunctions,
-                       List theBounds, List theEncode) {
-        super();
-
-        this.functionType = 3;    // dang well better be 3;
-
-        this.functions = theFunctions;
-        this.bounds = theBounds;
-        this.encode = theEncode;
-        this.domain = theDomain;
-        this.range = theRange;
+    public PDFFunction(int theFunctionType, List<Double> theDomain,
+                       List<Double> theRange, List<Function> theFunctions,
+                       List<Double> theBounds, List<Double> theEncode) {
+        delegate = new FunctionDelegate(this, theFunctionType, theDomain, theRange,
+                theFunctions, theBounds, theEncode);
 
     }
 
@@ -349,20 +207,12 @@ public class PDFFunction extends PDFObje
      * @param theFunctionType The type of function which should be 4, as this is
      * a Postscript calculator function
      */
-    public PDFFunction(int theFunctionType, List theDomain,
-                       List theRange, StringBuffer theFunctionDataStream) {
-        super();
-
-        this.functionType = 4;    // dang well better be 4;
-        this.functionDataStream = theFunctionDataStream;
-
-        this.domain = theDomain;
-
-        this.range = theRange;
-
+    public PDFFunction(int theFunctionType, List<Double> theDomain,
+                       List<Double> theRange, StringBuffer theFunctionDataStream) {
+        delegate = new FunctionDelegate(this, theFunctionType, theDomain, theRange,
+                theFunctionDataStream);
     }
 
-
     /**
      * represent as PDF. Whatever the FunctionType is, the correct
      * representation spits out. The sets of required and optional
@@ -375,319 +225,13 @@ public class PDFFunction extends PDFObje
      * @return the PDF string.
      */
     public byte[] toPDF() {
-        int vectorSize = 0;
-        int numberOfFunctions = 0;
-        int tempInt = 0;
-        StringBuffer p = new StringBuffer(256);
-        p.append("<< \n/FunctionType " + this.functionType + " \n");
-
-        // FunctionType 0
-        if (this.functionType == 0) {
-            if (this.domain != null) {
-                // DOMAIN
-                p.append("/Domain [ ");
-                vectorSize = this.domain.size();
-                for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                    p.append(PDFNumber.doubleOut((Double)this.domain.get(tempInt))
-                             + " ");
-                }
-
-                p.append("] \n");
-            } else {
-                p.append("/Domain [ 0 1 ] \n");
-            }
-
-            // SIZE
-            if (this.size != null) {
-                p.append("/Size [ ");
-                vectorSize = this.size.size();
-                for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                    p.append(PDFNumber.doubleOut((Double)this.size.get(tempInt))
-                             + " ");
-                }
-                p.append("] \n");
-            }
-            // ENCODE
-            if (this.encode != null) {
-                p.append("/Encode [ ");
-                vectorSize = this.encode.size();
-                for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                    p.append(PDFNumber.doubleOut((Double)this.encode.get(tempInt))
-                             + " ");
-                }
-                p.append("] \n");
-            } else {
-                p.append("/Encode [ ");
-                vectorSize = this.functions.size();
-                for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                    p.append("0 1 ");
-                }
-                p.append("] \n");
-
-            }
-
-            // BITSPERSAMPLE
-            p.append("/BitsPerSample " + this.bitsPerSample);
-
-            // ORDER (optional)
-            if (this.order == 1 || this.order == 3) {
-                p.append(" \n/Order " + this.order + " \n");
-            }
-
-            // RANGE
-            if (this.range != null) {
-                p.append("/Range [ ");
-                vectorSize = this.range.size();
-                for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                    p.append(PDFNumber.doubleOut((Double)this.range.get(tempInt))
-                             + " ");
-                }
-
-                p.append("] \n");
-            }
-
-            // DECODE
-            if (this.decode != null) {
-                p.append("/Decode [ ");
-                vectorSize = this.decode.size();
-                for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                    p.append(PDFNumber.doubleOut((Double)this.decode.get(tempInt))
-                             + " ");
-                }
-
-                p.append("] \n");
-            }
-
-            // LENGTH
-            if (this.functionDataStream != null) {
-                p.append("/Length " + (this.functionDataStream.length() + 1)
-                         + " \n");
-            }
-
-            // FILTER?
-            if (this.filter != null) {           // if there's a filter
-                vectorSize = this.filter.size();
-                p.append("/Filter ");
-                if (vectorSize == 1) {
-                    p.append("/" + ((String)this.filter.get(0))
-                             + " \n");
-                } else {
-                    p.append("[ ");
-                    for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                        p.append("/" + ((String)this.filter.get(0))
-                                 + " ");
-                    }
-                    p.append("] \n");
-                }
-            }
-            p.append(">>");
-
-            // stream representing the function
-            if (this.functionDataStream != null) {
-                p.append("\nstream\n" + this.functionDataStream
-                         + "\nendstream");
-            }
-
-            // end of if FunctionType 0
-
-        } else if (this.functionType == 2) {
-            // DOMAIN
-            if (this.domain != null) {
-                p.append("/Domain [ ");
-                vectorSize = this.domain.size();
-                for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                    p.append(PDFNumber.doubleOut((Double)this.domain.get(tempInt))
-                             + " ");
-                }
-
-                p.append("] \n");
-            } else {
-                p.append("/Domain [ 0 1 ] \n");
-            }
-
-
-            // RANGE
-            if (this.range != null) {
-                p.append("/Range [ ");
-                vectorSize = this.range.size();
-                for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                    p.append(PDFNumber.doubleOut((Double)this.range.get(tempInt))
-                             + " ");
-                }
-
-                p.append("] \n");
-            }
-
-            // FunctionType, C0, C1, N are required in PDF
-
-            // C0
-            if (this.cZero != null) {
-                p.append("/C0 [ ");
-                vectorSize = this.cZero.size();
-                for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                    p.append(PDFNumber.doubleOut((Double)this.cZero.get(tempInt))
-                             + " ");
-                }
-                p.append("] \n");
-            }
-
-            // C1
-            if (this.cOne != null) {
-                p.append("/C1 [ ");
-                vectorSize = this.cOne.size();
-                for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                    p.append(PDFNumber.doubleOut((Double)this.cOne.get(tempInt))
-                             + " ");
-                }
-                p.append("] \n");
-            }
-
-            // N: The interpolation Exponent
-            p.append("/N "
-                     + PDFNumber.doubleOut(new Double(this.interpolationExponentN))
-                     + " \n");
-
-            p.append(">>");
-
-        } else if (this.functionType
-                   == 3) {                       // fix this up when my eyes uncross
-            // DOMAIN
-            if (this.domain != null) {
-                p.append("/Domain [ ");
-                vectorSize = this.domain.size();
-                for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                    p.append(PDFNumber.doubleOut((Double)this.domain.get(tempInt))
-                             + " ");
-                }
-                p.append("] \n");
-            } else {
-                p.append("/Domain [ 0 1 ] \n");
-            }
-
-            // RANGE
-            if (this.range != null) {
-                p.append("/Range [ ");
-                vectorSize = this.range.size();
-                for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                    p.append(PDFNumber.doubleOut((Double)this.range.get(tempInt))
-                             + " ");
-                }
-
-                p.append("] \n");
-            }
-
-            // FUNCTIONS
-            if (this.functions != null) {
-                p.append("/Functions [ ");
-                numberOfFunctions = this.functions.size();
-                for (tempInt = 0; tempInt < numberOfFunctions; tempInt++) {
-                    p.append(((PDFFunction)this.functions.get(tempInt)).referencePDF()
-                             + " ");
-
-                }
-                p.append("] \n");
-            }
-
-
-            // ENCODE
-            if (this.encode != null) {
-                p.append("/Encode [ ");
-                vectorSize = this.encode.size();
-                for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                    p.append(PDFNumber.doubleOut((Double)this.encode.get(tempInt))
-                             + " ");
-                }
-
-                p.append("] \n");
-            } else {
-                p.append("/Encode [ ");
-                vectorSize = this.functions.size();
-                for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                    p.append("0 1 ");
-                }
-                p.append("] \n");
-
-            }
-
-
-            // BOUNDS, required, but can be empty
-            p.append("/Bounds [ ");
-            if (this.bounds != null) {
-
-                vectorSize = this.bounds.size();
-                for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                    p.append(PDFNumber.doubleOut((Double)this.bounds.get(tempInt))
-                             + " ");
-                }
-
-            } else {
-                if (this.functions != null) {
-                    // if there are n functions,
-                    // there must be n-1 bounds.
-                    // so let each function handle an equal portion
-                    // of the whole. e.g. if there are 4, then [ 0.25 0.25 0.25 ]
-
-                    String functionsFraction = PDFNumber.doubleOut(new Double(1.0
-                            / ((double)numberOfFunctions)));
-
-                    for (tempInt = 0; tempInt + 1 < numberOfFunctions;
-                            tempInt++) {
-
-                        p.append(functionsFraction + " ");
-                    }
-                    functionsFraction = null;    // clean reference.
-
-                }
-
-            }
-            p.append("]\n>>");
-        } else if (this.functionType
-                   == 4) {                       // fix this up when my eyes uncross
-            // DOMAIN
-            if (this.domain != null) {
-                p.append("/Domain [ ");
-                vectorSize = this.domain.size();
-                for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                    p.append(PDFNumber.doubleOut((Double)this.domain.get(tempInt))
-                             + " ");
-                }
-
-                p.append("] \n");
-            } else {
-                p.append("/Domain [ 0 1 ] \n");
-            }
-
-            // RANGE
-            if (this.range != null) {
-                p.append("/Range [ ");
-                vectorSize = this.range.size();
-                for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                    p.append(PDFNumber.doubleOut((Double)this.range.get(tempInt))
-                             + " ");
-                }
-
-                p.append("] \n");
-            }
-
-            // LENGTH
-            if (this.functionDataStream != null) {
-                p.append("/Length " + (this.functionDataStream.length() + 1)
-                         + " \n");
-            }
-
-            p.append(">>");
-
-            // stream representing the function
-            if (this.functionDataStream != null) {
-                p.append("\nstream\n{ " + this.functionDataStream
-                         + " }\nendstream");
-            }
-
-
-        }
+        return toByteString();
+    }
 
-        return encode(p.toString());
 
+    public byte[] toByteString() {
+        FunctionPattern pattern = new FunctionPattern(this);
+        return encode(pattern.toWriteableString());
     }
 
     /** {@inheritDoc} */
@@ -702,96 +246,155 @@ public class PDFFunction extends PDFObje
             return false;
         }
         PDFFunction func = (PDFFunction)obj;
-        if (functionType != func.functionType) {
+        if (delegate.getFunctionType() != func.getFunctionType()) {
             return false;
         }
-        if (bitsPerSample != func.bitsPerSample) {
+        if (delegate.getBitsPerSample() != func.getBitsPerSample()) {
             return false;
         }
-        if (order != func.order) {
+        if (delegate.getOrder() != func.getOrder()) {
             return false;
         }
-        if (interpolationExponentN != func.interpolationExponentN) {
+        if (delegate.getInterpolationExponentN() != func.getInterpolationExponentN()) {
             return false;
         }
-        if (domain != null) {
-            if (!domain.equals(func.domain)) {
+        if (delegate.getDomain() != null) {
+            if (!delegate.getDomain().equals(func.getDomain())) {
                 return false;
             }
-        } else if (func.domain != null) {
+        } else if (func.getDomain() != null) {
             return false;
         }
-        if (range != null) {
-            if (!range.equals(func.range)) {
+        if (delegate.getRange() != null) {
+            if (!delegate.getRange().equals(func.getRange())) {
                 return false;
             }
-        } else if (func.range != null) {
+        } else if (func.getRange() != null) {
             return false;
         }
-        if (size != null) {
-            if (!size.equals(func.size)) {
+        if (delegate.getSize() != null) {
+            if (!delegate.getSize().equals(func.getSize())) {
                 return false;
             }
-        } else if (func.size != null) {
+        } else if (func.getSize() != null) {
             return false;
         }
-        if (encode != null) {
-            if (!encode.equals(func.encode)) {
+        if (delegate.getEncode() != null) {
+            if (!delegate.getEncode().equals(func.getEncode())) {
                 return false;
             }
-        } else if (func.encode != null) {
+        } else if (func.getEncode() != null) {
             return false;
         }
-        if (decode != null) {
-            if (!decode.equals(func.decode)) {
+        if (delegate.getDecode() != null) {
+            if (!delegate.getDecode().equals(func.getDecode())) {
                 return false;
             }
-        } else if (func.decode != null) {
+        } else if (func.getDecode() != null) {
             return false;
         }
-        if (functionDataStream != null) {
-            if (!functionDataStream.equals(func.functionDataStream)) {
+        if (delegate.getDataStream() != null) {
+            if (!delegate.getDataStream().equals(func.getDataStream())) {
                 return false;
             }
-        } else if (func.functionDataStream != null) {
+        } else if (func.getDataStream() != null) {
             return false;
         }
-        if (filter != null) {
-            if (!filter.equals(func.filter)) {
+        if (delegate.getFilter() != null) {
+            if (!delegate.getFilter().equals(func.getFilter())) {
                 return false;
             }
-        } else if (func.filter != null) {
+        } else if (func.getFilter() != null) {
             return false;
         }
-        if (cZero != null) {
-            if (!cZero.equals(func.cZero)) {
+        if (delegate.getCZero() != null) {
+            if (!delegate.getCZero().equals(func.getCZero())) {
                 return false;
             }
-        } else if (func.cZero != null) {
+        } else if (func.getCZero() != null) {
             return false;
         }
-        if (cOne != null) {
-            if (!cOne.equals(func.cOne)) {
+        if (delegate.getCOne() != null) {
+            if (!delegate.getCOne().equals(func.getCOne())) {
                 return false;
             }
-        } else if (func.cOne != null) {
+        } else if (func.getCOne() != null) {
             return false;
         }
-        if (functions != null) {
-            if (!functions.equals(func.functions)) {
+        if (delegate.getFunctions() != null) {
+            if (!delegate.getFunctions().equals(func.getFunctions())) {
                 return false;
             }
-        } else if (func.functions != null) {
+        } else if (func.getFunctions() != null) {
             return false;
         }
-        if (bounds != null) {
-            if (!bounds.equals(func.bounds)) {
+        if (delegate.getBounds() != null) {
+            if (!delegate.getBounds().equals(func.getBounds())) {
                 return false;
             }
-        } else if (func.bounds != null) {
+        } else if (func.getBounds() != null) {
             return false;
         }
         return true;
     }
 
+    public int getFunctionType() {
+        return delegate.getFunctionType();
+    }
+
+    public List<Double> getBounds() {
+        return delegate.getBounds();
+    }
+
+    public List<Double> getDomain() {
+        return delegate.getDomain();
+    }
+
+    public List<Double> getSize() {
+        return delegate.getSize();
+    }
+
+    public List<String> getFilter() {
+        return delegate.getFilter();
+    }
+
+    public List<Double> getEncode() {
+        return delegate.getEncode();
+    }
+
+    public List<Function> getFunctions() {
+        return delegate.getFunctions();
+    }
+
+    public int getBitsPerSample() {
+        return delegate.getBitsPerSample();
+    }
+
+    public double getInterpolationExponentN() {
+        return delegate.getInterpolationExponentN();
+    }
+
+    public int getOrder() {
+        return delegate.getOrder();
+    }
+
+    public List<Double> getRange() {
+        return delegate.getRange();
+    }
+
+    public List<Double> getDecode() {
+        return delegate.getDecode();
+    }
+
+    public StringBuffer getDataStream() {
+        return delegate.getDataStream();
+    }
+
+    public List<Double> getCZero() {
+        return delegate.getCZero();
+    }
+
+    public List<Double> getCOne() {
+        return delegate.getCOne();
+    }
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFPattern.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFPattern.java?rev=1541551&r1=1541550&r2=1541551&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFPattern.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFPattern.java Wed Nov 13 15:24:26 2013
@@ -23,6 +23,9 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.util.List;
 
+import org.apache.fop.render.shading.Pattern;
+import org.apache.fop.render.shading.Shading;
+
 /**
  * class representing a PDF Function.
  *
@@ -33,7 +36,7 @@ import java.util.List;
  *
  * All PDF Functions have a FunctionType (0,2,3, or 4), a Domain, and a Range.
  */
-public class PDFPattern extends PDFPathPaint {
+public class PDFPattern extends PDFPathPaint implements Pattern {
 
     /**
      * The resources associated with this pattern
@@ -146,13 +149,14 @@ public class PDFPattern extends PDFPathP
      * @param theExtGState optional: the extended graphics state, if used.
      * @param theMatrix Optional:List of Doubles that specify the matrix.
      */
-    public PDFPattern(int thePatternType, PDFShading theShading,
+    public PDFPattern(int thePatternType, Shading theShading,
                       List theXUID, StringBuffer theExtGState,
                       List theMatrix) {
         super();
 
         this.patternType = 2;             // thePatternType;
-        this.shading = theShading;
+        assert theShading instanceof PDFShading;
+        this.shading = (PDFShading)theShading;
         this.xUID = theXUID;
         // this isn't really implemented, so it should always be null.
         // I just don't want to have to add a new parameter once it is implemented.
@@ -259,7 +263,7 @@ public class PDFPattern extends PDFPathP
                 vectorSize = this.xUID.size();
                 p.append("/XUID [ ");
                 for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                    p.append(((Integer)this.xUID.get(tempInt)) + " ");
+                    p.append((this.xUID.get(tempInt)) + " ");
                 }
                 p.append("] \n");
             }
@@ -290,7 +294,7 @@ public class PDFPattern extends PDFPathP
                 vectorSize = this.xUID.size();
                 p.append("/XUID [ ");
                 for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                    p.append(((Integer)this.xUID.get(tempInt)) + " ");
+                    p.append((this.xUID.get(tempInt)) + " ");
                 }
                 p.append("] \n");
             }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFShading.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFShading.java?rev=1541551&r1=1541550&r2=1541551&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFShading.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFShading.java Wed Nov 13 15:24:26 2013
@@ -22,6 +22,10 @@ package org.apache.fop.pdf;
 // Java...
 import java.util.List;
 
+import org.apache.fop.render.shading.Function;
+import org.apache.fop.render.shading.Shading;
+import org.apache.fop.render.shading.ShadingPattern;
+
 /**
  * class representing a PDF Smooth Shading object.
  *
@@ -32,7 +36,7 @@ import java.util.List;
  *
  * All PDF Functions have a shadingType (0,2,3, or 4), a Domain, and a Range.
  */
-public class PDFShading extends PDFObject {
+public class PDFShading extends PDFObject implements Shading {
     // Guts common to all function types
 
     /**
@@ -205,7 +209,7 @@ public class PDFShading extends PDFObjec
     public PDFShading(int theShadingType, PDFDeviceColorSpace theColorSpace,
             List theBackground, List theBBox,
             boolean theAntiAlias, List theCoords,
-            List theDomain, PDFFunction theFunction,
+            List theDomain, Function theFunction,
             List theExtend) {
         super();
         this.shadingType = theShadingType;    // 2 or 3
@@ -216,7 +220,8 @@ public class PDFShading extends PDFObjec
 
         this.coords = theCoords;
         this.domain = theDomain;
-        this.function = theFunction;
+        assert theFunction instanceof PDFFunction;
+        this.function = (PDFFunction)theFunction;
         this.extend = theExtend;
 
     }
@@ -335,197 +340,8 @@ public class PDFShading extends PDFObjec
      * @return the PDF string.
      */
     public String toPDFString() {
-        int vectorSize;
-        int tempInt;
-        StringBuffer p = new StringBuffer(128);
-        p.append("<<\n/ShadingType " + this.shadingType + " \n");
-        if (this.colorSpace != null) {
-            p.append("/ColorSpace /"
-                     + this.colorSpace.getName() + " \n");
-        }
-
-        if (this.background != null) {
-            p.append("/Background [ ");
-            vectorSize = this.background.size();
-            for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                p.append(PDFNumber.doubleOut((Double)this.background.get(tempInt))
-                         + " ");
-            }
-            p.append("] \n");
-        }
-
-        if (this.bBox
-                != null) {    // I've never seen an example, so I guess this is right.
-            p.append("/BBox [ ");
-            vectorSize = this.bBox.size();
-            for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                p.append(PDFNumber.doubleOut((Double)this.bBox.get(tempInt))
-                         + " ");
-            }
-            p.append("] \n");
-        }
-
-        if (this.antiAlias) {
-            p.append("/AntiAlias " + this.antiAlias + " \n");
-        }
-
-        // Here's where we differentiate based on what type it is.
-        if (this.shadingType == 1) {    // function based shading
-            if (this.domain != null) {
-                p.append("/Domain [ ");
-                vectorSize = this.domain.size();
-                for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                    p.append(PDFNumber.doubleOut((Double)this.domain.get(tempInt))
-                             + " ");
-                }
-                p.append("] \n");
-            } else {
-                p.append("/Domain [ 0 1 ] \n");
-            }
-
-            if (this.matrix != null) {
-                p.append("/Matrix [ ");
-                vectorSize = this.matrix.size();
-                for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                    p.append(PDFNumber.doubleOut((Double)this.matrix.get(tempInt))
-                             + " ");
-                }
-                p.append("] \n");
-            }
-
-            if (this.function != null) {
-                p.append("/Function ");
-                p.append(this.function.referencePDF() + " \n");
-            }
-        } else if ((this.shadingType == 2)
-                   || (this.shadingType
-                       == 3)) {         // 2 is axial shading (linear gradient)
-            // 3 is radial shading (circular gradient)
-            if (this.coords != null) {
-                p.append("/Coords [ ");
-                vectorSize = this.coords.size();
-                for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                    p.append(PDFNumber.doubleOut((Double)this.coords.get(tempInt))
-                             + " ");
-                }
-                p.append("] \n");
-            }
-
-            // DOMAIN
-            if (this.domain != null) {
-                p.append("/Domain [ ");
-                vectorSize = this.domain.size();
-                for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                    p.append(PDFNumber.doubleOut((Double)this.domain.get(tempInt))
-                             + " ");
-                }
-                p.append("] \n");
-            } else {
-                p.append("/Domain [ 0 1 ] \n");
-            }
-
-            if (this.extend != null) {
-                p.append("/Extend [ ");
-                vectorSize = this.extend.size();
-                for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                    p.append(((Boolean)this.extend.get(tempInt)) + " ");
-                }
-
-                p.append("] \n");
-            } else {
-                p.append("/Extend [ true true ] \n");
-            }
-
-
-            if (this.function != null) {
-                p.append("/Function ");
-                p.append(this.function.referencePDF() + " \n");
-            }
-
-
-        } else if ((this.shadingType == 4) || (this.shadingType == 6)
-                   || (this.shadingType
-                       == 7)) {    // 4:Free-form Gouraud-shaded triangle meshes
-            // 6:coons patch meshes
-            // 7://tensor product patch meshes (which no one ever uses)
-            if (this.bitsPerCoordinate > 0) {
-                p.append("/BitsPerCoordinate " + this.bitsPerCoordinate
-                         + " \n");
-            } else {
-                p.append("/BitsPerCoordinate 1 \n");
-            }
-
-            if (this.bitsPerComponent > 0) {
-                p.append("/BitsPerComponent " + this.bitsPerComponent
-                         + " \n");
-            } else {
-                p.append("/BitsPerComponent 1 \n");
-            }
-
-            if (this.bitsPerFlag > 0) {
-                p.append("/BitsPerFlag " + this.bitsPerFlag + " \n");
-            } else {
-                p.append("/BitsPerFlag 2 \n");
-            }
-
-            if (this.decode != null) {
-                p.append("/Decode [ ");
-                vectorSize = this.decode.size();
-                for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                    p.append(((Boolean)this.decode.get(tempInt)) + " ");
-                }
-
-                p.append("] \n");
-            }
-
-            if (this.function != null) {
-                p.append("/Function ");
-                p.append(this.function.referencePDF() + " \n");
-            }
-
-        } else if (this.shadingType
-                   == 5) {    // Lattice Free form gouraud-shaded triangle mesh
-
-            if (this.bitsPerCoordinate > 0) {
-                p.append("/BitsPerCoordinate " + this.bitsPerCoordinate
-                         + " \n");
-            } else {
-                p.append("/BitsPerCoordinate 1 \n");
-            }
-
-            if (this.bitsPerComponent > 0) {
-                p.append("/BitsPerComponent " + this.bitsPerComponent
-                         + " \n");
-            } else {
-                p.append("/BitsPerComponent 1 \n");
-            }
-
-            if (this.decode != null) {
-                p.append("/Decode [ ");
-                vectorSize = this.decode.size();
-                for (tempInt = 0; tempInt < vectorSize; tempInt++) {
-                    p.append(((Boolean)this.decode.get(tempInt)) + " ");
-                }
-
-                p.append("] \n");
-            }
-
-            if (this.function != null) {
-                p.append("/Function ");
-                p.append(this.function.referencePDF() + " \n");
-            }
-
-            if (this.verticesPerRow > 0) {
-                p.append("/VerticesPerRow " + this.verticesPerRow + " \n");
-            } else {
-                p.append("/VerticesPerRow 2 \n");
-            }
-
-        }
-
-        p.append(">>");
-
-        return (p.toString());
+        ShadingPattern pattern = new ShadingPattern(this);
+        return pattern.toString(colorSpace, shadingType, background, bBox, antiAlias);
     }
 
     /** {@inheritDoc} */
@@ -623,4 +439,173 @@ public class PDFShading extends PDFObjec
         }
         return true;
     }
+
+    /**
+     * A method to write a type 1 shading object
+     * @param p The StringBuffer to write the shading object
+     * @return Returns the StringBuffer to which the shading object was written
+     */
+    public StringBuffer handleShadingType1(StringBuffer p) {
+        if (this.domain != null) {
+            p.append("/Domain [ ");
+            for (int domainIndex = 0; domainIndex < domain.size(); domainIndex++) {
+                p.append(PDFNumber.doubleOut((Double)this.domain.get(domainIndex))
+                         + " ");
+            }
+            p.append("] \n");
+        } else {
+            p.append("/Domain [ 0 1 ] \n");
+        }
+
+        if (this.matrix != null) {
+            p.append("/Matrix [ ");
+            for (int matrixIndex = 0; matrixIndex < matrix.size(); matrixIndex++) {
+                p.append(PDFNumber.doubleOut((Double)this.matrix.get(matrixIndex))
+                         + " ");
+            }
+            p.append("] \n");
+        }
+
+        if (this.function != null) {
+            p.append("/Function ");
+            p.append(this.function.referencePDF() + " \n");
+        }
+        return p;
+    }
+
+    /**
+     * A method to write a type 2 or 3 shading object
+     * @param p The StringBuffer to write the shading object
+     * @return Returns the StringBuffer to which the shading object was written
+     */
+    public StringBuffer handleShadingType2or3(StringBuffer p) {
+        // 3 is radial shading (circular gradient)
+        if (this.coords != null) {
+            p.append("/Coords [ ");
+            for (int coordIndex = 0; coordIndex < coords.size(); coordIndex++) {
+                p.append(PDFNumber.doubleOut((Double)this.coords.get(coordIndex))
+                         + " ");
+            }
+            p.append("] \n");
+        }
+
+        // DOMAIN
+        if (this.domain != null) {
+            p.append("/Domain [ ");
+            for (int domainIndex = 0; domainIndex < domain.size(); domainIndex++) {
+                p.append(PDFNumber.doubleOut((Double)this.domain.get(domainIndex))
+                         + " ");
+            }
+            p.append("] \n");
+        } else {
+            p.append("/Domain [ 0 1 ] \n");
+        }
+
+        if (this.extend != null) {
+            p.append("/Extend [ ");
+            for (int extendIndex = 0; extendIndex < extend.size(); extendIndex++) {
+                p.append((this.extend.get(extendIndex)) + " ");
+            }
+
+            p.append("] \n");
+        } else {
+            p.append("/Extend [ true true ] \n");
+        }
+
+
+        if (this.function != null) {
+            p.append("/Function ");
+            p.append(this.function.referencePDF() + " \n");
+        }
+
+        return p;
+    }
+
+    /**
+     * A method to write a type 4, 6 or 7 shading object
+     * @param p The StringBuffer to write the shading object
+     * @return Returns the StringBuffer to which the shading object was written
+     */
+    public StringBuffer handleShadingType4or6or7(StringBuffer p) {
+        // 6:coons patch meshes
+        // 7://tensor product patch meshes (which no one ever uses)
+        if (this.bitsPerCoordinate > 0) {
+            p.append("/BitsPerCoordinate " + this.bitsPerCoordinate
+                     + " \n");
+        } else {
+            p.append("/BitsPerCoordinate 1 \n");
+        }
+
+        if (this.bitsPerComponent > 0) {
+            p.append("/BitsPerComponent " + this.bitsPerComponent
+                     + " \n");
+        } else {
+            p.append("/BitsPerComponent 1 \n");
+        }
+
+        if (this.bitsPerFlag > 0) {
+            p.append("/BitsPerFlag " + this.bitsPerFlag + " \n");
+        } else {
+            p.append("/BitsPerFlag 2 \n");
+        }
+
+        if (this.decode != null) {
+            p.append("/Decode [ ");
+            for (int decodeIndex = 0; decodeIndex < decode.size(); decodeIndex++) {
+                p.append((this.decode.get(decodeIndex)) + " ");
+            }
+
+            p.append("] \n");
+        }
+
+        if (this.function != null) {
+            p.append("/Function ");
+            p.append(this.function.referencePDF() + " \n");
+        }
+
+        return p;
+    }
+
+    /**
+     * A method to write a type 5 shading object
+     * @param p The StringBuffer to write the shading object
+     * @return Returns the StringBuffer to which the shading object was written
+     */
+    public StringBuffer handleShadingType5(StringBuffer p) {
+        if (this.bitsPerCoordinate > 0) {
+            p.append("/BitsPerCoordinate " + this.bitsPerCoordinate
+                     + " \n");
+        } else {
+            p.append("/BitsPerCoordinate 1 \n");
+        }
+
+        if (this.bitsPerComponent > 0) {
+            p.append("/BitsPerComponent " + this.bitsPerComponent
+                     + " \n");
+        } else {
+            p.append("/BitsPerComponent 1 \n");
+        }
+
+        if (this.decode != null) {
+            p.append("/Decode [ ");
+            for (int decodeIndex = 0; decodeIndex < decode.size(); decodeIndex++) {
+                p.append((this.decode.get(decodeIndex)) + " ");
+            }
+
+            p.append("] \n");
+        }
+
+        if (this.function != null) {
+            p.append("/Function ");
+            p.append(this.function.referencePDF() + " \n");
+        }
+
+        if (this.verticesPerRow > 0) {
+            p.append("/VerticesPerRow " + this.verticesPerRow + " \n");
+        } else {
+            p.append("/VerticesPerRow 2 \n");
+        }
+
+        return p;
+    }
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSImageHandlerSVG.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSImageHandlerSVG.java?rev=1541551&r1=1541550&r2=1541551&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSImageHandlerSVG.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSImageHandlerSVG.java Wed Nov 13 15:24:26 2013
@@ -19,26 +19,50 @@
 
 package org.apache.fop.render.ps;
 
+import java.awt.Color;
+import java.awt.Dimension;
 import java.awt.Rectangle;
 import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.imageio.ImageIO;
 
 import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
 
 import org.apache.batik.bridge.BridgeContext;
 import org.apache.batik.bridge.GVTBuilder;
 import org.apache.batik.gvt.GraphicsNode;
+import org.apache.batik.transcoder.SVGAbstractTranscoder;
+import org.apache.batik.transcoder.TranscoderException;
+import org.apache.batik.transcoder.TranscoderInput;
+import org.apache.batik.transcoder.TranscoderOutput;
+import org.apache.batik.transcoder.image.PNGTranscoder;
 
 import org.apache.xmlgraphics.image.loader.Image;
 import org.apache.xmlgraphics.image.loader.ImageFlavor;
 import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
-import org.apache.xmlgraphics.java2d.ps.PSGraphics2D;
+import org.apache.xmlgraphics.ps.ImageEncoder;
+import org.apache.xmlgraphics.ps.ImageEncodingHelper;
 import org.apache.xmlgraphics.ps.PSGenerator;
 
 import org.apache.fop.image.loader.batik.BatikImageFlavors;
 import org.apache.fop.image.loader.batik.BatikUtil;
 import org.apache.fop.render.ImageHandler;
 import org.apache.fop.render.RenderingContext;
+import org.apache.fop.render.ps.svg.PSSVGGraphics2D;
 import org.apache.fop.svg.SVGEventProducer;
 import org.apache.fop.svg.SVGUserAgent;
 
@@ -47,6 +71,9 @@ import org.apache.fop.svg.SVGUserAgent;
  */
 public class PSImageHandlerSVG implements ImageHandler {
 
+    private static final Color FALLBACK_COLOR = new Color(255, 33, 117);
+    private HashMap<String, String> gradientsFound = new HashMap<String, String>();
+
     private static final ImageFlavor[] FLAVORS = new ImageFlavor[] {
         BatikImageFlavors.SVG_DOM
     };
@@ -58,78 +85,262 @@ public class PSImageHandlerSVG implement
         PSGenerator gen = psContext.getGenerator();
         ImageXMLDOM imageSVG = (ImageXMLDOM)image;
 
-        //Controls whether text painted by Batik is generated using text or path operations
-        boolean strokeText = false;
-        //TODO Configure text stroking
-
-        SVGUserAgent ua
-             = new SVGUserAgent(context.getUserAgent(), new AffineTransform());
-
-        PSGraphics2D graphics = new PSGraphics2D(strokeText, gen);
-        graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
-
-        BridgeContext ctx = new PSBridgeContext(ua,
-                (strokeText ? null : psContext.getFontInfo()),
-                context.getUserAgent().getImageManager(),
-                context.getUserAgent().getImageSessionContext());
-
-        //Cloning SVG DOM as Batik attaches non-thread-safe facilities (like the CSS engine)
-        //to it.
-        Document clonedDoc = BatikUtil.cloneSVGDocument(imageSVG.getDocument());
+        if (shouldRaster(imageSVG)) {
+            InputStream is = renderSVGToInputStream(context, imageSVG);
 
-        GraphicsNode root;
+            float x = (float) pos.getX() / 1000f;
+            float y = (float) pos.getY() / 1000f;
+            float w = (float) pos.getWidth() / 1000f;
+            float h = (float) pos.getHeight() / 1000f;
+            Rectangle2D targetRect = new Rectangle2D.Double(x, y, w, h);
+
+            MaskedImage mi = convertToRGB(ImageIO.read(is));
+            BufferedImage ri = mi.getImage();
+            ImageEncoder encoder = ImageEncodingHelper.createRenderedImageEncoder(ri);
+            Dimension imgDim = new Dimension(ri.getWidth(), ri.getHeight());
+            String imgDescription = ri.getClass().getName();
+            ImageEncodingHelper helper = new ImageEncodingHelper(ri);
+            ColorModel cm = helper.getEncodedColorModel();
+            PSImageUtils.writeImage(encoder, imgDim, imgDescription, targetRect, cm, gen, ri, mi.getMaskColor());
+        } else {
+            //Controls whether text painted by Batik is generated using text or path operations
+            boolean strokeText = false;
+            //TODO Configure text stroking
+
+            SVGUserAgent ua
+                 = new SVGUserAgent(context.getUserAgent(), new AffineTransform());
+
+            PSSVGGraphics2D graphics = new PSSVGGraphics2D(strokeText, gen);
+            graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
+
+            BridgeContext ctx = new PSBridgeContext(ua,
+                    (strokeText ? null : psContext.getFontInfo()),
+                    context.getUserAgent().getImageManager(),
+                    context.getUserAgent().getImageSessionContext());
+
+            //Cloning SVG DOM as Batik attaches non-thread-safe facilities (like the CSS engine)
+            //to it.
+            Document clonedDoc = BatikUtil.cloneSVGDocument(imageSVG.getDocument());
+
+            GraphicsNode root;
+            try {
+                GVTBuilder builder = new GVTBuilder();
+                root = builder.build(ctx, clonedDoc);
+            } catch (Exception e) {
+                SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
+                        context.getUserAgent().getEventBroadcaster());
+                eventProducer.svgNotBuilt(this, e, image.getInfo().getOriginalURI());
+                return;
+            }
+            // get the 'width' and 'height' attributes of the SVG document
+            float w = (float)ctx.getDocumentSize().getWidth() * 1000f;
+            float h = (float)ctx.getDocumentSize().getHeight() * 1000f;
+
+            float sx = pos.width / w;
+            float sy = pos.height / h;
+
+            ctx = null;
+
+            gen.commentln("%FOPBeginSVG");
+            gen.saveGraphicsState();
+            final boolean clip = false;
+            if (clip) {
+                /*
+                 * Clip to the svg area.
+                 * Note: To have the svg overlay (under) a text area then use
+                 * an fo:block-container
+                 */
+                gen.writeln("newpath");
+                gen.defineRect(pos.getMinX() / 1000f, pos.getMinY() / 1000f,
+                        pos.width / 1000f, pos.height / 1000f);
+                gen.writeln("clip");
+            }
+
+            // transform so that the coordinates (0,0) is from the top left
+            // and positive is down and to the right. (0,0) is where the
+            // viewBox puts it.
+            gen.concatMatrix(sx, 0, 0, sy, pos.getMinX() / 1000f, pos.getMinY() / 1000f);
+
+            AffineTransform transform = new AffineTransform();
+            // scale to viewbox
+            transform.translate(pos.getMinX(), pos.getMinY());
+            gen.getCurrentState().concatMatrix(transform);
+            try {
+                root.paint(graphics);
+            } catch (Exception e) {
+                SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
+                        context.getUserAgent().getEventBroadcaster());
+                eventProducer.svgRenderingError(this, e, image.getInfo().getOriginalURI());
+            }
+
+            gen.restoreGraphicsState();
+            gen.commentln("%FOPEndSVG");
+        }
+    }
+
+    private InputStream renderSVGToInputStream(RenderingContext context, ImageXMLDOM imageSVG) throws IOException {
+        PNGTranscoder png = new PNGTranscoder();
+        Float width = getDimension(imageSVG.getDocument(), "width") * 8;
+        png.addTranscodingHint(SVGAbstractTranscoder.KEY_WIDTH, width);
+        Float height = getDimension(imageSVG.getDocument(), "height") * 8;
+        png.addTranscodingHint(SVGAbstractTranscoder.KEY_HEIGHT, height);
+        TranscoderInput input = new TranscoderInput(imageSVG.getDocument());
+        ByteArrayOutputStream os = new ByteArrayOutputStream();
+        TranscoderOutput output = new TranscoderOutput(os);
         try {
-            GVTBuilder builder = new GVTBuilder();
-            root = builder.build(ctx, clonedDoc);
-        } catch (Exception e) {
+            png.transcode(input, output);
+        } catch (TranscoderException ex) {
             SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
                     context.getUserAgent().getEventBroadcaster());
-            eventProducer.svgNotBuilt(this, e, image.getInfo().getOriginalURI());
-            return;
+            eventProducer.svgRenderingError(this, ex, imageSVG.getInfo().getOriginalURI());
+        } finally {
+            os.flush();
+            os.close();
+        }
+        return new ByteArrayInputStream(os.toByteArray());
+    }
+
+    private MaskedImage convertToRGB(BufferedImage alphaImage) {
+        int[] red = new int[256];
+        int[] green = new int[256];
+        int[] blue = new int[256];
+        BufferedImage rgbImage = new BufferedImage(alphaImage.getWidth(),
+                alphaImage.getHeight(), BufferedImage.TYPE_INT_RGB);
+        //Count occurances of each colour in image
+        for (int cx = 0; cx < alphaImage.getWidth(); cx++) {
+            for (int cy = 0; cy < alphaImage.getHeight(); cy++) {
+                int pixelValue = alphaImage.getRGB(cx, cy);
+                Color pixelColor = new Color(pixelValue);
+                red[pixelColor.getRed()]++;
+                green[pixelColor.getGreen()]++;
+                blue[pixelColor.getBlue()]++;
+            }
+        }
+        //Find colour not in image
+        Color alphaSwap = null;
+        for (int i = 0; i < 256; i++) {
+            if (red[i] == 0) {
+                alphaSwap = new Color(i, 0, 0);
+                break;
+            } else if (green[i] == 0) {
+                alphaSwap = new Color(0, i, 0);
+                break;
+            } else if (blue[i] == 0) {
+                alphaSwap = new Color(0, 0, i);
+                break;
+            }
+        }
+        //Check if all variations are used in all three colours
+        if (alphaSwap == null) {
+            //Fallback colour is no unique colour channel can be found
+            alphaSwap = FALLBACK_COLOR;
+        }
+        //Replace alpha channel with the new mask colour
+        for (int cx = 0; cx < alphaImage.getWidth(); cx++) {
+            for (int cy = 0; cy < alphaImage.getHeight(); cy++) {
+                int pixelValue = alphaImage.getRGB(cx, cy);
+                if (pixelValue == 0) {
+                    rgbImage.setRGB(cx, cy, alphaSwap.getRGB());
+                } else {
+                    rgbImage.setRGB(cx, cy, alphaImage.getRGB(cx, cy));
+                }
+            }
+        }
+        return new MaskedImage(rgbImage, alphaSwap);
+    }
+
+    private static class MaskedImage {
+        private Color maskColor = new Color(0, 0, 0);
+        private BufferedImage image;
+
+        public MaskedImage(BufferedImage image, Color maskColor) {
+            this.image = image;
+            this.maskColor = maskColor;
+        }
+
+        public Color getMaskColor() {
+            return maskColor;
+        }
+
+        public BufferedImage getImage() {
+            return image;
+        }
+    }
+
+    private Float getDimension(Document document, String dimension) {
+        if (document.getFirstChild().getAttributes().getNamedItem(dimension) != null) {
+            String width = document.getFirstChild().getAttributes().getNamedItem(dimension).getNodeValue();
+            width = width.replaceAll("[^\\d.]", "");
+            return Float.parseFloat(width);
         }
-        // get the 'width' and 'height' attributes of the SVG document
-        float w = (float)ctx.getDocumentSize().getWidth() * 1000f;
-        float h = (float)ctx.getDocumentSize().getHeight() * 1000f;
-
-        float sx = pos.width / w;
-        float sy = pos.height / h;
-
-        ctx = null;
-
-        gen.commentln("%FOPBeginSVG");
-        gen.saveGraphicsState();
-        final boolean clip = false;
-        if (clip) {
-            /*
-             * Clip to the svg area.
-             * Note: To have the svg overlay (under) a text area then use
-             * an fo:block-container
-             */
-            gen.writeln("newpath");
-            gen.defineRect(pos.getMinX() / 1000f, pos.getMinY() / 1000f,
-                    pos.width / 1000f, pos.height / 1000f);
-            gen.writeln("clip");
-        }
-
-        // transform so that the coordinates (0,0) is from the top left
-        // and positive is down and to the right. (0,0) is where the
-        // viewBox puts it.
-        gen.concatMatrix(sx, 0, 0, sy, pos.getMinX() / 1000f, pos.getMinY() / 1000f);
-
-        AffineTransform transform = new AffineTransform();
-        // scale to viewbox
-        transform.translate(pos.getMinX(), pos.getMinY());
-        gen.getCurrentState().concatMatrix(transform);
+        return null;
+    }
+
+    private boolean shouldRaster(ImageXMLDOM image) {
+        //A list of objects on which to check opacity
         try {
-            root.paint(graphics);
-        } catch (Exception e) {
-            SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
-                    context.getUserAgent().getEventBroadcaster());
-            eventProducer.svgRenderingError(this, e, image.getInfo().getOriginalURI());
+        List<String> gradMatches = new ArrayList<String>();
+        gradMatches.add("radialGradient");
+        gradMatches.add("linearGradient");
+        return recurseSVGElements(image.getDocument().getChildNodes(), gradMatches, false);
+        } finally {
+            gradientsFound.clear();
         }
+    }
 
-        gen.restoreGraphicsState();
-        gen.commentln("%FOPEndSVG");
+    private boolean recurseSVGElements(NodeList childNodes, List<String> gradMatches, boolean isMatched) {
+        boolean opacityFound = false;
+        for (int i = 0; i < childNodes.getLength(); i++) {
+            Node curNode = childNodes.item(i);
+            if (isMatched && curNode.getLocalName() != null && curNode.getLocalName().equals("stop")) {
+                if (curNode.getAttributes().getNamedItem("style") != null) {
+                    String[] stylePairs = curNode.getAttributes().getNamedItem("style").getNodeValue()
+                            .split(";");
+                    for (int styleAtt = 0; styleAtt < stylePairs.length; styleAtt++) {
+                        String[] style = stylePairs[styleAtt].split(":");
+                        if (style[0].equalsIgnoreCase("stop-opacity")) {
+                            if (Double.parseDouble(style[1]) < 1) {
+                                return true;
+                            }
+                        }
+                    }
+                }
+                if (curNode.getAttributes().getNamedItem("stop-opacity") != null) {
+                    String opacityValue = curNode.getAttributes().getNamedItem("stop-opacity").getNodeValue();
+                    if (Double.parseDouble(opacityValue) < 1) {
+                        return true;
+                    }
+                }
+            }
+            String nodeName = curNode.getLocalName();
+            //Special case where rasterization needed for radial gradients
+            if (nodeName != null && nodeName.equals("ellipse")) {
+                String found = "";
+                String ellipseFill = curNode.getAttributes().getNamedItem("fill").getNodeValue();
+                Pattern pattern = Pattern.compile("#(.*?)\\)");
+                Matcher matcher = pattern.matcher(ellipseFill);
+                if (matcher.find()) {
+                    found = matcher.group(1);
+                }
+                if (gradientsFound.get(found) != null) {
+                    return true;
+                }
+            }
+            boolean inMatch = false;
+            if (!isMatched) {
+                inMatch = nodeName != null && gradMatches.contains(nodeName);
+                if (inMatch) {
+                    gradientsFound.put(curNode.getAttributes().getNamedItem("id").getNodeValue(), nodeName);
+                }
+            } else {
+                inMatch = true;
+            }
+            opacityFound = recurseSVGElements(curNode.getChildNodes(), gradMatches, inMatch);
+            if (opacityFound) {
+                return true;
+            }
+        }
+        return opacityFound;
     }
 
     /** {@inheritDoc} */

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSFunction.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSFunction.java?rev=1541551&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSFunction.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSFunction.java Wed Nov 13 15:24:26 2013
@@ -0,0 +1,143 @@
+/*
+ * 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.ps.svg;
+
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+
+import org.apache.fop.render.shading.Function;
+import org.apache.fop.render.shading.FunctionDelegate;
+import org.apache.fop.render.shading.FunctionPattern;
+
+public class PSFunction implements Function {
+
+    private FunctionDelegate delegate;
+
+    /**
+     * Creates a Postscript function dictionary
+     * @param theFunctionType The function type (0 = Sampled, 2 = Exponential
+     * Interpolation, 3 = Stitching)
+     * @param theDomain The function domain
+     * @param theRange Range used for clipping
+     * @param theFunctions An array of sub-functions such as determining the
+     * colour values used in a gradient.
+     * @param theBounds Bounds determines where each boundary exists for whatever
+     * the function is mean't. In a gradient case, it would be the point between
+     * colours.
+     * @param theEncode The function encoding
+     */
+    public PSFunction(int theFunctionType, List<Double> theDomain,
+            List<Double> theRange, List<Function> theFunctions,
+            List<Double> theBounds, List<Double> theEncode) {
+        delegate = new FunctionDelegate(this, theFunctionType, theDomain, theRange, theFunctions,
+                theBounds, theEncode);
+    }
+
+    /**
+     * Creates a Postscript function dictionary
+     * @param theFunctionType The function type (0 = Sampled, 2 = Exponential
+     * Interpolation, 3 = Stitching)
+     * @param theDomain The function domain
+     * @param theRange Range used for clipping
+     * @param theCZero In a gradient, this would be the first colour
+     * @param theCOne In a gradient, this would be the second colour
+     * @param theInterpolationExponentN Determines the number of values
+     * the function returns.
+     */
+    public PSFunction(int theFunctionType, List<Double> theDomain,
+            List<Double> theRange, List<Double> theCZero, List<Double> theCOne,
+            double theInterpolationExponentN) {
+        delegate = new FunctionDelegate(this, theFunctionType, theDomain, theRange, theCZero,
+                theCOne, theInterpolationExponentN);
+    }
+
+    /**
+     * Outputs the function to a byte array
+     */
+    public byte[] toByteString() {
+        FunctionPattern pattern = new FunctionPattern(this);
+        try {
+            return pattern.toWriteableString().getBytes("UTF-8");
+        } catch (UnsupportedEncodingException ex) {
+            //This should have been made an enum type to avoid throwing exceptions.
+            return new byte[0];
+        }
+    }
+
+    public int getFunctionType() {
+        return delegate.getFunctionType();
+    }
+
+    public List<Double> getBounds() {
+        return delegate.getBounds();
+    }
+
+    public List<Double> getDomain() {
+        return delegate.getDomain();
+    }
+
+    public List<Double> getSize() {
+        return delegate.getSize();
+    }
+
+    public List<String> getFilter() {
+        return delegate.getFilter();
+    }
+
+    public List<Double> getEncode() {
+        return delegate.getEncode();
+    }
+
+    public List<Function> getFunctions() {
+        return delegate.getFunctions();
+    }
+
+    public int getBitsPerSample() {
+        return delegate.getBitsPerSample();
+    }
+
+    public double getInterpolationExponentN() {
+        return delegate.getInterpolationExponentN();
+    }
+
+    public int getOrder() {
+        return delegate.getOrder();
+    }
+
+    public List<Double> getRange() {
+        return delegate.getRange();
+    }
+
+    public List<Double> getDecode() {
+        return delegate.getDecode();
+    }
+
+    public StringBuffer getDataStream() {
+        return delegate.getDataStream();
+    }
+
+    public List<Double> getCZero() {
+        return delegate.getCZero();
+    }
+
+    public List<Double> getCOne() {
+        return delegate.getCOne();
+    }
+}

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSFunction.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSPattern.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSPattern.java?rev=1541551&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSPattern.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSPattern.java Wed Nov 13 15:24:26 2013
@@ -0,0 +1,103 @@
+/*
+ * 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.ps.svg;
+
+import java.util.List;
+
+import org.apache.fop.render.shading.Pattern;
+import org.apache.fop.render.shading.Shading;
+
+public class PSPattern implements Pattern {
+
+    /**
+     * Either one (1) for tiling, or two (2) for shading.
+     */
+    protected int patternType = 2;      // Default
+
+    /**
+     * The Shading object comprising the Type 2 pattern
+     */
+    protected PSShading shading = null;
+
+    /**
+     * List of Integers represetning the Extended unique Identifier
+     */
+    protected List xUID = null;
+
+    /**
+     * TODO use PDFGState
+     * String representing the extended Graphics state.
+     * Probably will never be used like this.
+     */
+    protected StringBuffer extGState = null;
+
+    /**
+     * Creates a radial or axial shading pattern
+     * @param thePatternType The pattern type which will be 3 for radial and 2 for axial
+     * @param theShading The shading object to determine how the gradient
+     * is drawn
+     * @param theXUID The XUID
+     * @param theExtGState The exit state
+     */
+    public PSPattern(int thePatternType, Shading theShading, List theXUID,
+                     StringBuffer theExtGState) {
+        this.patternType = 2;             // thePatternType;
+        assert theShading instanceof PSShading;
+        this.shading = (PSShading)theShading;
+        this.xUID = theXUID;
+        this.extGState = theExtGState;    // always null
+    }
+
+    /**
+     * Outputs the radial or axial pattern as a string dictionary to insert
+     * into a postscript document.
+     */
+    public String toString() {
+        int vectorSize = 0;
+        int tempInt = 0;
+        StringBuffer p = new StringBuffer(64);
+        p.append("/Pattern setcolorspace\n");
+        p.append("<< \n/Type /Pattern \n");
+
+        p.append("/PatternType " + this.patternType + " \n");
+
+        if (this.shading != null) {
+            p.append("/Shading " + this.shading.toString() + " \n");
+        }
+
+        if (this.xUID != null) {
+            vectorSize = this.xUID.size();
+            p.append("/XUID [ ");
+            for (tempInt = 0; tempInt < vectorSize; tempInt++) {
+                p.append((this.xUID.get(tempInt)) + " ");
+            }
+            p.append("] \n");
+        }
+
+        if (this.extGState != null) {
+            p.append("/ExtGState " + this.extGState + " \n");
+        }
+
+        p.append(">> \n");
+        p.append("matrix makepattern setcolor\n");
+
+        return p.toString();
+    }
+}

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/svg/PSPattern.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org