]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Renamed shading package to gradient
authorVincent Hennebert <vhennebert@apache.org>
Mon, 14 Jul 2014 21:24:02 +0000 (21:24 +0000)
committerVincent Hennebert <vhennebert@apache.org>
Mon, 14 Jul 2014 21:24:02 +0000 (21:24 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/FOP-2393_gradient-rendering@1610534 13f79535-47bb-0310-9956-ffa450edef68

12 files changed:
src/java/org/apache/fop/pdf/PDFFunction.java
src/java/org/apache/fop/pdf/PDFShading.java
src/java/org/apache/fop/render/gradient/Function.java [new file with mode: 0644]
src/java/org/apache/fop/render/gradient/GradientMaker.java [new file with mode: 0644]
src/java/org/apache/fop/render/gradient/Pattern.java [new file with mode: 0644]
src/java/org/apache/fop/render/gradient/Shading.java [new file with mode: 0644]
src/java/org/apache/fop/render/ps/svg/PSSVGGraphics2D.java
src/java/org/apache/fop/render/shading/Function.java [deleted file]
src/java/org/apache/fop/render/shading/GradientMaker.java [deleted file]
src/java/org/apache/fop/render/shading/Pattern.java [deleted file]
src/java/org/apache/fop/render/shading/Shading.java [deleted file]
src/java/org/apache/fop/svg/PDFGraphics2D.java

index bdd61a86da51a56ed01cc8928108623d3df53b4e..65ec0ea90b403adaeeda53860474dd4ec13fefa5 100644 (file)
@@ -24,7 +24,7 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 
-import org.apache.fop.render.shading.Function;
+import org.apache.fop.render.gradient.Function;
 
 /**
  * class representing a PDF Function.
index a45c14e66b5ca5aede96479a2519af03cde6b9ba..577e10a09ed3e644d6e626549472229a107ccdd8 100644 (file)
@@ -21,7 +21,7 @@ package org.apache.fop.pdf;
 
 import java.util.List;
 
-import org.apache.fop.render.shading.Shading;
+import org.apache.fop.render.gradient.Shading;
 
 
 /**
diff --git a/src/java/org/apache/fop/render/gradient/Function.java b/src/java/org/apache/fop/render/gradient/Function.java
new file mode 100644 (file)
index 0000000..f374795
--- /dev/null
@@ -0,0 +1,515 @@
+/*
+ * 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.
+ */
+
+package org.apache.fop.render.gradient;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.fop.pdf.PDFNumber;
+
+public class Function {
+
+    /**
+     * Required: The Type of function (0,2,3,4) default is 0.
+     */
+    private int functionType;
+
+    /**
+     * Required: 2 * m Array of Double numbers which are possible inputs to the function
+     */
+    private List<Double> domain;
+
+    /**
+     * Required: 2 * n Array of Double numbers which are possible outputs to the function
+     */
+    private List<Double> range;
+
+    /* ********************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<Double> size;
+
+    /**
+     * Required for Type 0: Number of Bits used to represent each sample value.
+     * Limited to 1,2,4,8,12,16,24, or 32
+     */
+    private int bitsPerSample = 1;
+
+    /**
+     * Optional for Type 0: order of interpolation between samples.
+     * Limited to linear (1) or cubic (3). Default is 1
+     */
+    private 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.
+     */
+    private List<Double> encode;
+
+    /**
+     * Optional for Type 0: A 2 * n array of Doubles which provides
+     * a linear mapping of sample values to the range. Defaults to Range.
+     */
+    private List<Double> decode;
+
+    /**
+     * 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
+     */
+    private StringBuffer functionDataStream;
+
+    /**
+     * 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.
+     */
+    private List<String> filter;
+    /* *************************TYPE 2************************** */
+
+    /**
+     * Required For Type 2: An Array of n Doubles defining
+     * the function result when x=0. Default is [0].
+     */
+    private float[] cZero;
+
+    /**
+     * Required For Type 2: An Array of n Doubles defining
+     * the function result when x=1. Default is [1].
+     */
+    private float[] cOne;
+
+    /**
+     * Required for Type 2: The interpolation exponent.
+     * Each value x will return n results.
+     * Must be greater than 0.
+     */
+    private 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.
+     */
+    private List<Function> functions;
+
+    /**
+     * 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.
+     */
+    private List<Double> bounds;
+
+    /**
+     * create an complete Function object of Type 2, an Exponential Interpolation function.
+     *
+     * Use null for an optional object parameter if you choose not to use it.
+     * For optional int parameters, pass the default.
+     * @param functionType The type of the function, which should be 2.
+     * @param domain List objects of Double objects.
+     * This is the domain of the function.
+     * See page 264 of the PDF 1.3 Spec.
+     * @param range List of Doubles that is the Range of the function.
+     * See page 264 of the PDF 1.3 Spec.
+     * @param cZero This is a vector of Double objects which defines the function result
+     * when x=0.
+     *
+     * This attribute is optional.
+     * It's described on page 268 of the PDF 1.3 spec.
+     * @param cOne This is a vector of Double objects which defines the function result
+     * when x=1.
+     *
+     * This attribute is optional.
+     * It's described on page 268 of the PDF 1.3 spec.
+     * @param interpolationExponentN This is the inerpolation exponent.
+     *
+     * This attribute is required.
+     * PDF Spec page 268
+     */
+    public Function(int functionType, List<Double> domain, List<Double> range,
+                       float[] cZero, float[] cOne, double interpolationExponentN) {
+        this.functionType = 2;    // dang well better be 2;
+
+        this.cZero = cZero;
+        this.cOne = cOne;
+        this.interpolationExponentN = interpolationExponentN;
+
+        this.domain = domain;
+        this.range = range;
+
+    }
+
+    /**
+     * create an complete Function object of Type 3, a Stitching function.
+     *
+     * Use null for an optional object parameter if you choose not to use it.
+     * For optional int parameters, pass the default.
+     * @param functionType This is the function type. It should be 3,
+     * for a stitching function.
+     * @param domain List objects of Double objects.
+     * This is the domain of the function.
+     * See page 264 of the PDF 1.3 Spec.
+     * @param range List objects of Double objects.
+     * This is the Range of the function.
+     * See page 264 of the PDF 1.3 Spec.
+     * @param functions A List of the PDFFunction objects that the stitching function stitches.
+     *
+     * This attributed is required.
+     * It is described on page 269 of the PDF spec.
+     * @param bounds This is a vector of Doubles representing the numbers that,
+     * in conjunction with Domain define the intervals to which each function from
+     * the 'functions' object applies. It must be in order of increasing magnitude,
+     * and each must be within Domain.
+     *
+     * It basically sets how much of the gradient each function handles.
+     *
+     * This attributed is required.
+     * It's described on page 269 of the PDF 1.3 spec.
+     * @param encode List objects of Double objects.
+     * This is the linear mapping of input values intop the domain
+     * of the function's sample table. Default is hard to represent in
+     * ascii, but basically [0 (Size0 1) 0 (Size1 1)...].
+     * This attribute is required.
+     *
+     * See page 270 in the PDF 1.3 spec.
+     */
+    public Function(int functionType, List<Double> domain, List<Double> range,
+                       List<Function> functions, List<Double> bounds,
+                       List<Double> encode) {
+        this.functionType = 3;    // dang well better be 3;
+
+        this.functions = functions;
+        this.bounds = bounds;
+        this.encode = encode;
+        this.domain = domain;
+        this.range = range;
+
+    }
+
+    /**
+     * Gets the function type
+     */
+    public int getFunctionType() {
+        return functionType;
+    }
+
+    /**
+     * Gets the function bounds
+     */
+    public List<Double> getBounds() {
+        return bounds;
+    }
+
+    /**
+     * The function domain
+     */
+    public List<Double> getDomain() {
+        return domain;
+    }
+
+    /**
+     * The function size
+     */
+    public List<Double> getSize() {
+        return size;
+    }
+
+    /**
+     * Gets the function encoding
+     */
+    public List<Double> getEncode() {
+        return encode;
+    }
+
+    /**
+     * Gets the sub-functions
+     */
+    public List<Function> getFunctions() {
+        if (functions == null) {
+            return Collections.emptyList();
+        } else {
+            return functions;
+        }
+    }
+
+    /**
+     * Gets the function filter
+     */
+    public List<String> getFilter() {
+        return filter;
+    }
+
+    /**
+     * Gets the bits per sample of the function
+     */
+    public int getBitsPerSample() {
+        return bitsPerSample;
+    }
+
+    /**
+     * Gets the interpolation exponent of the function
+     */
+    public double getInterpolationExponentN() {
+        return interpolationExponentN;
+    }
+
+    /**
+     * Gets the function order
+     */
+    public int getOrder() {
+        return order;
+    }
+
+    /**
+     * Gets the function range
+     */
+    public List<Double> getRange() {
+        return range;
+    }
+
+    /**
+     * Gets the function decoding
+     */
+    public List<Double> getDecode() {
+        return decode;
+    }
+
+    /**
+     * Gets the function data stream
+     */
+    public StringBuffer getDataStream() {
+        return functionDataStream;
+    }
+
+    /**
+     * Gets the function C0 value (color for gradient)
+     */
+    public float[] getCZero() {
+        return cZero;
+    }
+
+    /**
+     * Gets the function C1 value (color for gradient)
+     */
+    public float[] getCOne() {
+        return cOne;
+    }
+
+    public String toWriteableString(List<String> functionsStrings) {
+        StringBuilder out = new StringBuilder(256);
+        out.append("<<\n/FunctionType " + functionType + "\n");
+        outputDomain(out);
+        if (this.functionType == 0) {
+            outputSize(out);
+            outputEncode(out);
+            outputBitsPerSample(out);
+            outputOrder(out);
+            outputRange(out);
+            outputDecode(out);
+            if (functionDataStream != null) {
+                out.append("/Length " + (functionDataStream.length() + 1) + "\n");
+            }
+            outputFilter(out);
+            out.append(">>");
+            if (functionDataStream != null) {
+                out.append("\nstream\n" + functionDataStream + "\nendstream");
+            }
+        } else if (functionType == 2) {
+            outputRange(out);
+            outputCZero(out);
+            outputCOne(out);
+            outputInterpolationExponentN(out);
+            out.append(">>");
+        } else if (functionType == 3) {
+            outputRange(out);
+            if (!functions.isEmpty()) {
+                out.append("/Functions [ ");
+                for (String f : functionsStrings) {
+                    out.append(f);
+                    out.append(' ');
+                }
+                out.append("]\n");
+            }
+            outputEncode(out);
+            out.append("/Bounds ");
+            if (bounds != null) {
+                outputDoubles(out, bounds);
+            } else if (!functions.isEmpty()) {
+                // 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 ]
+                int numberOfFunctions = functions.size();
+                String functionsFraction = PDFNumber.doubleOut(Double.valueOf(1.0 / (numberOfFunctions)));
+                out.append("[ ");
+                for (int i = 0; i + 1 < numberOfFunctions; i++) {
+                    out.append(functionsFraction);
+                    out.append(" ");
+                }
+                out.append("]");
+            }
+            out.append("\n>>");
+        } else if (functionType == 4) {
+            outputRange(out);
+            if (functionDataStream != null) {
+                out.append("/Length " + (functionDataStream.length() + 1) + "\n");
+            }
+            out.append(">>");
+            if (functionDataStream != null) {
+                out.append("\nstream\n{ " + functionDataStream + " }\nendstream");
+            }
+        }
+        return out.toString();
+    }
+
+    private void outputDomain(StringBuilder p) {
+        if (domain != null) {
+            p.append("/Domain ");
+            outputDoubles(p, domain);
+            p.append("\n");
+        } else {
+            p.append("/Domain [ 0 1 ]\n");
+        }
+    }
+
+    private void outputSize(StringBuilder out) {
+        if (size != null) {
+            out.append("/Size ");
+            outputDoubles(out, size);
+            out.append("\n");
+        }
+    }
+
+    private void outputBitsPerSample(StringBuilder out) {
+        out.append("/BitsPerSample " + bitsPerSample + "\n");
+    }
+
+    private void outputOrder(StringBuilder out) {
+        if (order == 1 || order == 3) {
+            out.append("\n/Order " + order + "\n");
+        }
+    }
+
+    private void outputRange(StringBuilder out) {
+        if (range != null) {
+            out.append("/Range ");
+            outputDoubles(out, range);
+            out.append("\n");
+        }
+    }
+
+    private void outputEncode(StringBuilder out) {
+        if (encode != null) {
+            out.append("/Encode ");
+            outputDoubles(out, encode);
+            out.append("\n");
+        } else {
+            out.append("/Encode [ ");
+            int size = functions.size();
+            for (int i = 0; i < size; i++) {
+                out.append("0 1 ");
+            }
+            out.append("]\n");
+        }
+    }
+
+    private void outputDecode(StringBuilder out) {
+        if (decode != null) {
+            out.append("/Decode ");
+            outputDoubles(out, decode);
+            out.append("\n");
+        }
+    }
+
+    private void outputFilter(StringBuilder out) {
+        if (filter != null) {
+            int size = filter.size();
+            out.append("/Filter ");
+            if (size == 1) {
+                out.append("/" + filter.get(0) + "\n");
+            } else {
+                out.append("[ ");
+                for (int i = 0; i < size; i++) {
+                    out.append("/" + filter.get(0) + " ");
+                }
+                out.append("]\n");
+            }
+        }
+    }
+
+    private void outputCZero(StringBuilder out) {
+        if (cZero != null) {
+            out.append("/C0 [ ");
+            for (float c : cZero) {
+                out.append(PDFNumber.doubleOut(c));
+                out.append(" ");
+            }
+            out.append("]\n");
+        }
+    }
+
+    private void outputCOne(StringBuilder out) {
+        if (cOne != null) {
+            out.append("/C1 [ ");
+            for (float c : cOne) {
+                out.append(PDFNumber.doubleOut(c));
+                out.append(" ");
+            }
+            out.append("]\n");
+        }
+    }
+
+    private void outputInterpolationExponentN(StringBuilder out) {
+        out.append("/N ");
+        out.append(PDFNumber.doubleOut(Double.valueOf(interpolationExponentN)));
+        out.append("\n");
+    }
+
+    private void outputDoubles(StringBuilder out, List<Double> doubles) {
+        out.append("[ ");
+        for (Double d : doubles) {
+            out.append(PDFNumber.doubleOut(d));
+            out.append(" ");
+        }
+        out.append("]");
+    }
+
+}
diff --git a/src/java/org/apache/fop/render/gradient/GradientMaker.java b/src/java/org/apache/fop/render/gradient/GradientMaker.java
new file mode 100644 (file)
index 0000000..02db2c5
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * 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.gradient;
+
+import java.awt.Color;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.batik.ext.awt.LinearGradientPaint;
+import org.apache.batik.ext.awt.MultipleGradientPaint;
+import org.apache.batik.ext.awt.RadialGradientPaint;
+
+import org.apache.xmlgraphics.java2d.color.ColorUtil;
+
+import org.apache.fop.pdf.PDFDeviceColorSpace;
+
+public final class GradientMaker {
+
+    private GradientMaker() { }
+
+    public static Pattern makeLinearGradient(LinearGradientPaint gp,
+            AffineTransform baseTransform, AffineTransform transform) {
+        Point2D startPoint = gp.getStartPoint();
+        Point2D endPoint = gp.getEndPoint();
+        List<Double> coords = new java.util.ArrayList<Double>(4);
+        coords.add(new Double(startPoint.getX()));
+        coords.add(new Double(startPoint.getY()));
+        coords.add(new Double(endPoint.getX()));
+        coords.add(new Double(endPoint.getY()));
+        return makeGradient(gp, coords, baseTransform, transform);
+    }
+
+    public static Pattern makeRadialGradient(RadialGradientPaint gradient,
+            AffineTransform baseTransform, AffineTransform transform) {
+        double radius = gradient.getRadius();
+        Point2D center = gradient.getCenterPoint();
+        Point2D focus = gradient.getFocusPoint();
+        double dx = focus.getX() - center.getX();
+        double dy = focus.getY() - center.getY();
+        double d = Math.sqrt(dx * dx + dy * dy);
+        if (d > radius) {
+            // The center point must be within the circle with
+            // radius radius centered at center so limit it to that.
+            double scale = (radius * .9999) / d;
+            dx *= scale;
+            dy *= scale;
+        }
+        List<Double> coords = new java.util.ArrayList<Double>(6);
+        coords.add(Double.valueOf(center.getX() + dx));
+        coords.add(Double.valueOf(center.getY() + dy));
+        coords.add(Double.valueOf(0));
+        coords.add(Double.valueOf(center.getX()));
+        coords.add(Double.valueOf(center.getY()));
+        coords.add(Double.valueOf(radius));
+        return makeGradient(gradient, coords, baseTransform, transform);
+    }
+
+    private static Pattern makeGradient(MultipleGradientPaint gradient, List<Double> coords,
+            AffineTransform baseTransform, AffineTransform transform) {
+        List<Double> matrix = makeTransform(gradient, baseTransform, transform);
+        List<Double> bounds = makeBounds(gradient);
+        List<Function> functions = makeFunctions(gradient);
+        // Gradients are currently restricted to sRGB
+        PDFDeviceColorSpace colorSpace = new PDFDeviceColorSpace(PDFDeviceColorSpace.DEVICE_RGB);
+        Function function = new Function(3, null, null, functions, bounds, null);
+        int shadingType = gradient instanceof LinearGradientPaint ? 2 : 3;
+        Shading shading = new Shading(shadingType, colorSpace, coords, function);
+        return new Pattern(2, shading, matrix);
+    }
+
+    private static List<Double> makeTransform(MultipleGradientPaint gradient,
+            AffineTransform baseTransform, AffineTransform transform) {
+        AffineTransform gradientTransform = new AffineTransform(baseTransform);
+        gradientTransform.concatenate(transform);
+        gradientTransform.concatenate(gradient.getTransform());
+        List<Double> matrix = new ArrayList<Double>(6);
+        double[] m = new double[6];
+        gradientTransform.getMatrix(m);
+        for (double d : m) {
+            matrix.add(Double.valueOf(d));
+        }
+        return matrix;
+    }
+
+    private static Color getsRGBColor(Color c) {
+        // Color space must be consistent, so convert to sRGB if necessary
+        // TODO really?
+        return c.getColorSpace().isCS_sRGB() ? c : ColorUtil.toSRGBColor(c);
+    }
+
+    private static List<Double> makeBounds(MultipleGradientPaint gradient) {
+        // TODO is the conversion to double necessary?
+        float[] fractions = gradient.getFractions();
+        List<Double> bounds = new java.util.ArrayList<Double>(fractions.length);
+        for (float offset : fractions) {
+            if (0f < offset && offset < 1f) {
+                bounds.add(Double.valueOf(offset));
+            }
+        }
+        return bounds;
+    }
+
+    private static List<Function> makeFunctions(MultipleGradientPaint gradient) {
+        List<Color> colors = makeColors(gradient);
+        List<Function> functions = new ArrayList<Function>();
+        for (int currentPosition = 0, lastPosition = colors.size() - 1;
+                currentPosition < lastPosition;
+                currentPosition++) {
+            Color currentColor = colors.get(currentPosition);
+            Color nextColor = colors.get(currentPosition + 1);
+            float[] c0 = currentColor.getColorComponents(null);
+            float[] c1 = nextColor.getColorComponents(null);
+            Function function = new Function(2, null, null, c0, c1, 1.0);
+            functions.add(function);
+        }
+        return functions;
+    }
+
+    private static List<Color> makeColors(MultipleGradientPaint gradient) {
+        Color[] svgColors = gradient.getColors();
+        List<Color> gradientColors = new ArrayList<Color>(svgColors.length + 2);
+        float[] fractions = gradient.getFractions();
+        if (fractions[0] > 0f) {
+            gradientColors.add(getsRGBColor(svgColors[0]));
+        }
+        for (Color c : svgColors) {
+            gradientColors.add(getsRGBColor(c));
+        }
+        if (fractions[fractions.length - 1] < 1f) {
+            gradientColors.add(getsRGBColor(svgColors[svgColors.length - 1]));
+        }
+        return gradientColors;
+    }
+
+}
diff --git a/src/java/org/apache/fop/render/gradient/Pattern.java b/src/java/org/apache/fop/render/gradient/Pattern.java
new file mode 100644 (file)
index 0000000..cc244f5
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+package org.apache.fop.render.gradient;
+
+import java.util.List;
+
+public class Pattern {
+
+    private final int patternType;
+
+    private final Shading shading;
+
+    private final List<Double> matrix;
+
+    Pattern(int patternType, Shading shading, List<Double> matrix) {
+        this.patternType = patternType;
+        this.shading = shading;
+        this.matrix = matrix;
+    }
+
+    /**
+     * Either one (1) for tiling, or two (2) for shading.
+     */
+    public int getPatternType() {
+        return patternType;
+    }
+
+    public Shading getShading() {
+        return shading;
+    }
+
+    public List<Double> getMatrix() {
+        return matrix;
+    }
+
+}
diff --git a/src/java/org/apache/fop/render/gradient/Shading.java b/src/java/org/apache/fop/render/gradient/Shading.java
new file mode 100644 (file)
index 0000000..61f933c
--- /dev/null
@@ -0,0 +1,376 @@
+/*
+ * 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.
+ */
+
+package org.apache.fop.render.gradient;
+
+import java.util.List;
+
+import org.apache.fop.pdf.PDFDeviceColorSpace;
+import org.apache.fop.pdf.PDFNumber;
+
+
+public class Shading {
+
+    public interface FunctionRenderer {
+
+        void outputFunction(StringBuilder out);
+    }
+
+    /**
+     * Required: The Type of shading (1,2,3,4,5,6,7)
+     */
+    private final int shadingType;
+
+    /**
+     * A ColorSpace representing the colorspace. "DeviceRGB" is an example.
+     */
+    private final PDFDeviceColorSpace colorSpace;
+
+    /**
+     * Required for Type 2: An Array of four numbers specifying
+     *                      the starting and ending coordinate pairs
+     * Required for Type 3: An Array of six numbers [x0,y0,r0,x1,y1,r1]
+     *                      specifying the centers and radii of
+     *                      the starting and ending circles.
+     */
+    private final List<Double> coords;
+
+    /**
+     * Required for Type 1, 2, and 3:
+     * The object of the color mapping function (usually type 2 or 3).
+     * Optional for Type 4,5,6, and 7: When it's nearly the same thing.
+     */
+    private final Function function;
+
+    /**
+     * Optional: A List specifying the clipping rectangle
+     */
+    private final List<Double> bbox;
+
+    /**
+     * Optional for Type 1: A transformation matrix
+     */
+    private final List<Double> matrix;
+
+    /**
+     * The background color. Since shading is opaque,
+     * this is very rarely used.
+     */
+    private final List<Double> background;
+
+    /**
+     * Optional for Type 1: Array of four numbers, xmin, xmax, ymin, ymax.
+     *                      Default is [0 1 0 1]
+     * Optional for Type 2: An array of two numbers between which the blend
+     *                      varies between start and end points. Default is 0, 1.
+     * Optional for Type 3: An array of two numbers between which the blend
+     *                      varies between start and end points. Default is 0, 1.
+     */
+    private final List<Double> domain;
+
+    /**
+     * Required for Type 4,5,6, and 7: Array of Doubles which specifies
+     * how to decode coordinate and color component values.
+     * Each type has a differing number of decode array members, so check
+     * the spec.
+     * Page 303 in PDF Spec 1.3
+     */
+    private final List<Double> decode;
+
+    /**
+     * Required for Type 2+3: An Array of two boolean values specifying
+     * whether to extend the start and end colors past the start
+     * and end points, respectively.
+     * Default is false, false.
+     */
+    private final List<Boolean> extend;
+
+    /**
+     * Required for Type 4,5,6, and 7: Specifies the number of bits used
+     * to represent each vertex coordinate.
+     * Allowed to be 1,2,4,8,12,16,24, or 32.
+     */
+    private final int bitsPerCoordinate;
+
+    /**
+     * Required for Type 4,5,6, and 7: Specifies the number of bits used
+     * to represent the edge flag for each vertex.
+     * Allowed to be 2,4,or 8, while the Edge flag itself is allowed to
+     * be 0,1 or 2.
+     */
+    private final int bitsPerFlag;
+
+    /**
+     * Optional: A flag whether or not to filter the shading function
+     * to prevent aliasing artifacts. Default is false.
+     */
+    private final boolean antiAlias;
+
+    /**
+     * Required for Type 4,5,6, and 7: Specifies the number of bits used
+     * to represent each color coordinate.
+     * Allowed to be 1,2,4,8,12, or 16
+     */
+    private final int bitsPerComponent;
+
+    /**
+     * Required for Type 5:The number of vertices in each "row" of
+     * the lattice; it must be greater than or equal to 2.
+     */
+    private final int verticesPerRow;
+
+    public Shading(int shadingType, PDFDeviceColorSpace colorSpace,
+            List<Double> coords, Function function) {
+        this.shadingType = shadingType;
+        this.colorSpace = colorSpace;
+        this.background = null;
+        this.bbox = null;
+        this.antiAlias = false;
+        this.coords = coords;
+        this.domain = null;
+        this.function = function;
+        this.extend = null;
+        this.matrix = null;
+        this.decode = null;
+        this.bitsPerCoordinate = 0;
+        this.bitsPerFlag = 0;
+        this.bitsPerComponent = 0;
+        this.verticesPerRow = 0;
+    }
+
+    public int getShadingType() {
+        return shadingType;
+    }
+
+    public PDFDeviceColorSpace getColorSpace() {
+        return colorSpace;
+    }
+
+    public List<Double> getCoords() {
+        return coords;
+    }
+
+    public Function getFunction() {
+        return function;
+    }
+
+    public List<Double> getBBox() {
+        return bbox;
+    }
+
+    public List<Double> getMatrix() {
+        return matrix;
+    }
+
+    public List<Double> getBackground() {
+        return background;
+    }
+
+    public List<Double> getDomain() {
+        return domain;
+    }
+
+    public List<Double> getDecode() {
+        return decode;
+    }
+
+    public List<Boolean> getExtend() {
+        return extend;
+    }
+
+    public int getBitsPerCoordinate() {
+        return bitsPerCoordinate;
+    }
+
+    public int getBitsPerFlag() {
+        return bitsPerFlag;
+    }
+
+    public boolean isAntiAlias() {
+        return antiAlias;
+    }
+
+    public int getBitsPerComponent() {
+        return bitsPerComponent;
+    }
+
+    public int getVerticesPerRow() {
+        return verticesPerRow;
+    }
+
+    public void output(StringBuilder out, FunctionRenderer functionRenderer) {
+        out.append("<<\n/ShadingType " + shadingType + "\n");
+        if (colorSpace != null) {
+            out.append("/ColorSpace /" + colorSpace.getName() + "\n");
+        }
+
+        if (background != null) {
+            out.append("/Background ");
+            outputDoubles(out, background);
+            out.append("\n");
+        }
+
+        if (bbox != null) {
+            out.append("/BBox");
+            outputDoubles(out, bbox);
+            out.append("\n");
+        }
+
+        if (antiAlias) {
+            out.append("/AntiAlias " + antiAlias + "\n");
+        }
+
+        switch (shadingType) {
+        // Function based shading
+        case 1: outputShadingType1(out, functionRenderer); break;
+        // Axial shading
+        case 2:
+        // Radial shading
+        case 3: outputShadingType2or3(out, functionRenderer); break;
+        // Free-form Gouraud-shaded triangle meshes
+        case 4:
+        // Coons patch meshes
+        case 6:
+        // Tensor product patch meshes
+        case 7: outputShadingType4or6or7(out, functionRenderer); break;
+        // Lattice Free form gouraud-shaded triangle mesh
+        case 5: outputShadingType5(out, functionRenderer); break;
+        default: throw new UnsupportedOperationException("Shading type " + shadingType);
+        }
+
+        out.append(">>");
+    }
+
+    private void outputDoubles(StringBuilder out, List<Double> doubles) {
+        out.append("[ ");
+        for (Double d : doubles) {
+            out.append(PDFNumber.doubleOut(d));
+            out.append(" ");
+        }
+        out.append("]");
+    }
+
+    private void outputShadingType1(StringBuilder out, Shading.FunctionRenderer functionRenderer) {
+        if (domain != null) {
+            out.append("/Domain ");
+            outputDoubles(out, domain);
+            out.append("\n");
+        } else {
+            out.append("/Domain [ 0 1 ] \n");
+        }
+
+        if (matrix != null) {
+            out.append("/Matrix ");
+            outputDoubles(out, matrix);
+            out.append("\n");
+        }
+        outputFunction(out, functionRenderer);
+    }
+
+    private void outputShadingType2or3(StringBuilder out, Shading.FunctionRenderer functionRenderer) {
+        if (coords != null) {
+            out.append("/Coords ");
+            outputDoubles(out, coords);
+            out.append("\n");
+        }
+
+        if (domain != null) {
+            out.append("/Domain ");
+            outputDoubles(out, domain);
+            out.append("\n");
+        } else {
+            out.append("/Domain [ 0 1 ] \n");
+        }
+
+        if (extend != null) {
+            out.append("/Extend [");
+            for (Boolean b : extend) {
+                out.append(b);
+                out.append(" ");
+            }
+            out.append("\n");
+        } else {
+            out.append("/Extend [ true true ] \n");
+        }
+
+        outputFunction(out, functionRenderer);
+    }
+
+    private void outputShadingType4or6or7(StringBuilder out, Shading.FunctionRenderer functionRenderer) {
+        if (bitsPerCoordinate > 0) {
+            out.append("/BitsPerCoordinate " + bitsPerCoordinate + "\n");
+        } else {
+            out.append("/BitsPerCoordinate 1 \n");
+        }
+
+        if (bitsPerComponent > 0) {
+            out.append("/BitsPerComponent " + bitsPerComponent + "\n");
+        } else {
+            out.append("/BitsPerComponent 1 \n");
+        }
+
+        if (bitsPerFlag > 0) {
+            out.append("/BitsPerFlag " + bitsPerFlag + "\n");
+        } else {
+            out.append("/BitsPerFlag 2 \n");
+        }
+
+        if (decode != null) {
+            out.append("/Decode ");
+            outputDoubles(out, decode);
+            out.append("\n");
+        }
+
+        outputFunction(out, functionRenderer);
+    }
+
+    private void outputShadingType5(StringBuilder out, Shading.FunctionRenderer functionRenderer) {
+        if (bitsPerCoordinate > 0) {
+            out.append("/BitsPerCoordinate " + bitsPerCoordinate + "\n");
+        } else {
+            out.append("/BitsPerCoordinate 1 \n");
+        }
+
+        if (bitsPerComponent > 0) {
+            out.append("/BitsPerComponent " + bitsPerComponent + "\n");
+        } else {
+            out.append("/BitsPerComponent 1 \n");
+        }
+
+        if (decode != null) {
+            out.append("/Decode ");
+            outputDoubles(out, decode);
+            out.append("\n");
+        }
+
+        outputFunction(out, functionRenderer);
+
+        if (verticesPerRow > 0) {
+            out.append("/VerticesPerRow " + verticesPerRow + "\n");
+        } else {
+            out.append("/VerticesPerRow 2 \n");
+        }
+    }
+
+    private void outputFunction(StringBuilder out, FunctionRenderer functionRenderer) {
+        if (function != null) {
+            out.append("/Function ");
+            functionRenderer.outputFunction(out);
+            out.append("\n");
+        }
+    }
+}
index 9f428dca65393a62877801dbd080af59fd332b16..55811f2c954ada49c3e1ff3759c2faaa9cb48315 100644 (file)
@@ -35,10 +35,10 @@ import org.apache.batik.ext.awt.RadialGradientPaint;
 import org.apache.xmlgraphics.java2d.ps.PSGraphics2D;
 import org.apache.xmlgraphics.ps.PSGenerator;
 
-import org.apache.fop.render.shading.Function;
-import org.apache.fop.render.shading.GradientMaker;
-import org.apache.fop.render.shading.Pattern;
-import org.apache.fop.render.shading.Shading;
+import org.apache.fop.render.gradient.Function;
+import org.apache.fop.render.gradient.GradientMaker;
+import org.apache.fop.render.gradient.Pattern;
+import org.apache.fop.render.gradient.Shading;
 
 
 public class PSSVGGraphics2D extends PSGraphics2D {
diff --git a/src/java/org/apache/fop/render/shading/Function.java b/src/java/org/apache/fop/render/shading/Function.java
deleted file mode 100644 (file)
index 8fb6528..0000000
+++ /dev/null
@@ -1,515 +0,0 @@
-/*
- * 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.
- */
-
-package org.apache.fop.render.shading;
-
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.fop.pdf.PDFNumber;
-
-public class Function {
-
-    /**
-     * Required: The Type of function (0,2,3,4) default is 0.
-     */
-    private int functionType;
-
-    /**
-     * Required: 2 * m Array of Double numbers which are possible inputs to the function
-     */
-    private List<Double> domain;
-
-    /**
-     * Required: 2 * n Array of Double numbers which are possible outputs to the function
-     */
-    private List<Double> range;
-
-    /* ********************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<Double> size;
-
-    /**
-     * Required for Type 0: Number of Bits used to represent each sample value.
-     * Limited to 1,2,4,8,12,16,24, or 32
-     */
-    private int bitsPerSample = 1;
-
-    /**
-     * Optional for Type 0: order of interpolation between samples.
-     * Limited to linear (1) or cubic (3). Default is 1
-     */
-    private 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.
-     */
-    private List<Double> encode;
-
-    /**
-     * Optional for Type 0: A 2 * n array of Doubles which provides
-     * a linear mapping of sample values to the range. Defaults to Range.
-     */
-    private List<Double> decode;
-
-    /**
-     * 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
-     */
-    private StringBuffer functionDataStream;
-
-    /**
-     * 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.
-     */
-    private List<String> filter;
-    /* *************************TYPE 2************************** */
-
-    /**
-     * Required For Type 2: An Array of n Doubles defining
-     * the function result when x=0. Default is [0].
-     */
-    private float[] cZero;
-
-    /**
-     * Required For Type 2: An Array of n Doubles defining
-     * the function result when x=1. Default is [1].
-     */
-    private float[] cOne;
-
-    /**
-     * Required for Type 2: The interpolation exponent.
-     * Each value x will return n results.
-     * Must be greater than 0.
-     */
-    private 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.
-     */
-    private List<Function> functions;
-
-    /**
-     * 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.
-     */
-    private List<Double> bounds;
-
-    /**
-     * create an complete Function object of Type 2, an Exponential Interpolation function.
-     *
-     * Use null for an optional object parameter if you choose not to use it.
-     * For optional int parameters, pass the default.
-     * @param functionType The type of the function, which should be 2.
-     * @param domain List objects of Double objects.
-     * This is the domain of the function.
-     * See page 264 of the PDF 1.3 Spec.
-     * @param range List of Doubles that is the Range of the function.
-     * See page 264 of the PDF 1.3 Spec.
-     * @param cZero This is a vector of Double objects which defines the function result
-     * when x=0.
-     *
-     * This attribute is optional.
-     * It's described on page 268 of the PDF 1.3 spec.
-     * @param cOne This is a vector of Double objects which defines the function result
-     * when x=1.
-     *
-     * This attribute is optional.
-     * It's described on page 268 of the PDF 1.3 spec.
-     * @param interpolationExponentN This is the inerpolation exponent.
-     *
-     * This attribute is required.
-     * PDF Spec page 268
-     */
-    public Function(int functionType, List<Double> domain, List<Double> range,
-                       float[] cZero, float[] cOne, double interpolationExponentN) {
-        this.functionType = 2;    // dang well better be 2;
-
-        this.cZero = cZero;
-        this.cOne = cOne;
-        this.interpolationExponentN = interpolationExponentN;
-
-        this.domain = domain;
-        this.range = range;
-
-    }
-
-    /**
-     * create an complete Function object of Type 3, a Stitching function.
-     *
-     * Use null for an optional object parameter if you choose not to use it.
-     * For optional int parameters, pass the default.
-     * @param functionType This is the function type. It should be 3,
-     * for a stitching function.
-     * @param domain List objects of Double objects.
-     * This is the domain of the function.
-     * See page 264 of the PDF 1.3 Spec.
-     * @param range List objects of Double objects.
-     * This is the Range of the function.
-     * See page 264 of the PDF 1.3 Spec.
-     * @param functions A List of the PDFFunction objects that the stitching function stitches.
-     *
-     * This attributed is required.
-     * It is described on page 269 of the PDF spec.
-     * @param bounds This is a vector of Doubles representing the numbers that,
-     * in conjunction with Domain define the intervals to which each function from
-     * the 'functions' object applies. It must be in order of increasing magnitude,
-     * and each must be within Domain.
-     *
-     * It basically sets how much of the gradient each function handles.
-     *
-     * This attributed is required.
-     * It's described on page 269 of the PDF 1.3 spec.
-     * @param encode List objects of Double objects.
-     * This is the linear mapping of input values intop the domain
-     * of the function's sample table. Default is hard to represent in
-     * ascii, but basically [0 (Size0 1) 0 (Size1 1)...].
-     * This attribute is required.
-     *
-     * See page 270 in the PDF 1.3 spec.
-     */
-    public Function(int functionType, List<Double> domain, List<Double> range,
-                       List<Function> functions, List<Double> bounds,
-                       List<Double> encode) {
-        this.functionType = 3;    // dang well better be 3;
-
-        this.functions = functions;
-        this.bounds = bounds;
-        this.encode = encode;
-        this.domain = domain;
-        this.range = range;
-
-    }
-
-    /**
-     * Gets the function type
-     */
-    public int getFunctionType() {
-        return functionType;
-    }
-
-    /**
-     * Gets the function bounds
-     */
-    public List<Double> getBounds() {
-        return bounds;
-    }
-
-    /**
-     * The function domain
-     */
-    public List<Double> getDomain() {
-        return domain;
-    }
-
-    /**
-     * The function size
-     */
-    public List<Double> getSize() {
-        return size;
-    }
-
-    /**
-     * Gets the function encoding
-     */
-    public List<Double> getEncode() {
-        return encode;
-    }
-
-    /**
-     * Gets the sub-functions
-     */
-    public List<Function> getFunctions() {
-        if (functions == null) {
-            return Collections.emptyList();
-        } else {
-            return functions;
-        }
-    }
-
-    /**
-     * Gets the function filter
-     */
-    public List<String> getFilter() {
-        return filter;
-    }
-
-    /**
-     * Gets the bits per sample of the function
-     */
-    public int getBitsPerSample() {
-        return bitsPerSample;
-    }
-
-    /**
-     * Gets the interpolation exponent of the function
-     */
-    public double getInterpolationExponentN() {
-        return interpolationExponentN;
-    }
-
-    /**
-     * Gets the function order
-     */
-    public int getOrder() {
-        return order;
-    }
-
-    /**
-     * Gets the function range
-     */
-    public List<Double> getRange() {
-        return range;
-    }
-
-    /**
-     * Gets the function decoding
-     */
-    public List<Double> getDecode() {
-        return decode;
-    }
-
-    /**
-     * Gets the function data stream
-     */
-    public StringBuffer getDataStream() {
-        return functionDataStream;
-    }
-
-    /**
-     * Gets the function C0 value (color for gradient)
-     */
-    public float[] getCZero() {
-        return cZero;
-    }
-
-    /**
-     * Gets the function C1 value (color for gradient)
-     */
-    public float[] getCOne() {
-        return cOne;
-    }
-
-    public String toWriteableString(List<String> functionsStrings) {
-        StringBuilder out = new StringBuilder(256);
-        out.append("<<\n/FunctionType " + functionType + "\n");
-        outputDomain(out);
-        if (this.functionType == 0) {
-            outputSize(out);
-            outputEncode(out);
-            outputBitsPerSample(out);
-            outputOrder(out);
-            outputRange(out);
-            outputDecode(out);
-            if (functionDataStream != null) {
-                out.append("/Length " + (functionDataStream.length() + 1) + "\n");
-            }
-            outputFilter(out);
-            out.append(">>");
-            if (functionDataStream != null) {
-                out.append("\nstream\n" + functionDataStream + "\nendstream");
-            }
-        } else if (functionType == 2) {
-            outputRange(out);
-            outputCZero(out);
-            outputCOne(out);
-            outputInterpolationExponentN(out);
-            out.append(">>");
-        } else if (functionType == 3) {
-            outputRange(out);
-            if (!functions.isEmpty()) {
-                out.append("/Functions [ ");
-                for (String f : functionsStrings) {
-                    out.append(f);
-                    out.append(' ');
-                }
-                out.append("]\n");
-            }
-            outputEncode(out);
-            out.append("/Bounds ");
-            if (bounds != null) {
-                outputDoubles(out, bounds);
-            } else if (!functions.isEmpty()) {
-                // 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 ]
-                int numberOfFunctions = functions.size();
-                String functionsFraction = PDFNumber.doubleOut(Double.valueOf(1.0 / (numberOfFunctions)));
-                out.append("[ ");
-                for (int i = 0; i + 1 < numberOfFunctions; i++) {
-                    out.append(functionsFraction);
-                    out.append(" ");
-                }
-                out.append("]");
-            }
-            out.append("\n>>");
-        } else if (functionType == 4) {
-            outputRange(out);
-            if (functionDataStream != null) {
-                out.append("/Length " + (functionDataStream.length() + 1) + "\n");
-            }
-            out.append(">>");
-            if (functionDataStream != null) {
-                out.append("\nstream\n{ " + functionDataStream + " }\nendstream");
-            }
-        }
-        return out.toString();
-    }
-
-    private void outputDomain(StringBuilder p) {
-        if (domain != null) {
-            p.append("/Domain ");
-            outputDoubles(p, domain);
-            p.append("\n");
-        } else {
-            p.append("/Domain [ 0 1 ]\n");
-        }
-    }
-
-    private void outputSize(StringBuilder out) {
-        if (size != null) {
-            out.append("/Size ");
-            outputDoubles(out, size);
-            out.append("\n");
-        }
-    }
-
-    private void outputBitsPerSample(StringBuilder out) {
-        out.append("/BitsPerSample " + bitsPerSample + "\n");
-    }
-
-    private void outputOrder(StringBuilder out) {
-        if (order == 1 || order == 3) {
-            out.append("\n/Order " + order + "\n");
-        }
-    }
-
-    private void outputRange(StringBuilder out) {
-        if (range != null) {
-            out.append("/Range ");
-            outputDoubles(out, range);
-            out.append("\n");
-        }
-    }
-
-    private void outputEncode(StringBuilder out) {
-        if (encode != null) {
-            out.append("/Encode ");
-            outputDoubles(out, encode);
-            out.append("\n");
-        } else {
-            out.append("/Encode [ ");
-            int size = functions.size();
-            for (int i = 0; i < size; i++) {
-                out.append("0 1 ");
-            }
-            out.append("]\n");
-        }
-    }
-
-    private void outputDecode(StringBuilder out) {
-        if (decode != null) {
-            out.append("/Decode ");
-            outputDoubles(out, decode);
-            out.append("\n");
-        }
-    }
-
-    private void outputFilter(StringBuilder out) {
-        if (filter != null) {
-            int size = filter.size();
-            out.append("/Filter ");
-            if (size == 1) {
-                out.append("/" + filter.get(0) + "\n");
-            } else {
-                out.append("[ ");
-                for (int i = 0; i < size; i++) {
-                    out.append("/" + filter.get(0) + " ");
-                }
-                out.append("]\n");
-            }
-        }
-    }
-
-    private void outputCZero(StringBuilder out) {
-        if (cZero != null) {
-            out.append("/C0 [ ");
-            for (float c : cZero) {
-                out.append(PDFNumber.doubleOut(c));
-                out.append(" ");
-            }
-            out.append("]\n");
-        }
-    }
-
-    private void outputCOne(StringBuilder out) {
-        if (cOne != null) {
-            out.append("/C1 [ ");
-            for (float c : cOne) {
-                out.append(PDFNumber.doubleOut(c));
-                out.append(" ");
-            }
-            out.append("]\n");
-        }
-    }
-
-    private void outputInterpolationExponentN(StringBuilder out) {
-        out.append("/N ");
-        out.append(PDFNumber.doubleOut(Double.valueOf(interpolationExponentN)));
-        out.append("\n");
-    }
-
-    private void outputDoubles(StringBuilder out, List<Double> doubles) {
-        out.append("[ ");
-        for (Double d : doubles) {
-            out.append(PDFNumber.doubleOut(d));
-            out.append(" ");
-        }
-        out.append("]");
-    }
-
-}
diff --git a/src/java/org/apache/fop/render/shading/GradientMaker.java b/src/java/org/apache/fop/render/shading/GradientMaker.java
deleted file mode 100644 (file)
index d9c55ea..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * 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.shading;
-
-import java.awt.Color;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Point2D;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.batik.ext.awt.LinearGradientPaint;
-import org.apache.batik.ext.awt.MultipleGradientPaint;
-import org.apache.batik.ext.awt.RadialGradientPaint;
-
-import org.apache.xmlgraphics.java2d.color.ColorUtil;
-
-import org.apache.fop.pdf.PDFDeviceColorSpace;
-
-public final class GradientMaker {
-
-    private GradientMaker() { }
-
-    public static Pattern makeLinearGradient(LinearGradientPaint gp,
-            AffineTransform baseTransform, AffineTransform transform) {
-        Point2D startPoint = gp.getStartPoint();
-        Point2D endPoint = gp.getEndPoint();
-        List<Double> coords = new java.util.ArrayList<Double>(4);
-        coords.add(new Double(startPoint.getX()));
-        coords.add(new Double(startPoint.getY()));
-        coords.add(new Double(endPoint.getX()));
-        coords.add(new Double(endPoint.getY()));
-        return makeGradient(gp, coords, baseTransform, transform);
-    }
-
-    public static Pattern makeRadialGradient(RadialGradientPaint gradient,
-            AffineTransform baseTransform, AffineTransform transform) {
-        double radius = gradient.getRadius();
-        Point2D center = gradient.getCenterPoint();
-        Point2D focus = gradient.getFocusPoint();
-        double dx = focus.getX() - center.getX();
-        double dy = focus.getY() - center.getY();
-        double d = Math.sqrt(dx * dx + dy * dy);
-        if (d > radius) {
-            // The center point must be within the circle with
-            // radius radius centered at center so limit it to that.
-            double scale = (radius * .9999) / d;
-            dx *= scale;
-            dy *= scale;
-        }
-        List<Double> coords = new java.util.ArrayList<Double>(6);
-        coords.add(Double.valueOf(center.getX() + dx));
-        coords.add(Double.valueOf(center.getY() + dy));
-        coords.add(Double.valueOf(0));
-        coords.add(Double.valueOf(center.getX()));
-        coords.add(Double.valueOf(center.getY()));
-        coords.add(Double.valueOf(radius));
-        return makeGradient(gradient, coords, baseTransform, transform);
-    }
-
-    private static Pattern makeGradient(MultipleGradientPaint gradient, List<Double> coords,
-            AffineTransform baseTransform, AffineTransform transform) {
-        List<Double> matrix = makeTransform(gradient, baseTransform, transform);
-        List<Double> bounds = makeBounds(gradient);
-        List<Function> functions = makeFunctions(gradient);
-        // Gradients are currently restricted to sRGB
-        PDFDeviceColorSpace colorSpace = new PDFDeviceColorSpace(PDFDeviceColorSpace.DEVICE_RGB);
-        Function function = new Function(3, null, null, functions, bounds, null);
-        int shadingType = gradient instanceof LinearGradientPaint ? 2 : 3;
-        Shading shading = new Shading(shadingType, colorSpace, coords, function);
-        return new Pattern(2, shading, matrix);
-    }
-
-    private static List<Double> makeTransform(MultipleGradientPaint gradient,
-            AffineTransform baseTransform, AffineTransform transform) {
-        AffineTransform gradientTransform = new AffineTransform(baseTransform);
-        gradientTransform.concatenate(transform);
-        gradientTransform.concatenate(gradient.getTransform());
-        List<Double> matrix = new ArrayList<Double>(6);
-        double[] m = new double[6];
-        gradientTransform.getMatrix(m);
-        for (double d : m) {
-            matrix.add(Double.valueOf(d));
-        }
-        return matrix;
-    }
-
-    private static Color getsRGBColor(Color c) {
-        // Color space must be consistent, so convert to sRGB if necessary
-        // TODO really?
-        return c.getColorSpace().isCS_sRGB() ? c : ColorUtil.toSRGBColor(c);
-    }
-
-    private static List<Double> makeBounds(MultipleGradientPaint gradient) {
-        // TODO is the conversion to double necessary?
-        float[] fractions = gradient.getFractions();
-        List<Double> bounds = new java.util.ArrayList<Double>(fractions.length);
-        for (float offset : fractions) {
-            if (0f < offset && offset < 1f) {
-                bounds.add(Double.valueOf(offset));
-            }
-        }
-        return bounds;
-    }
-
-    private static List<Function> makeFunctions(MultipleGradientPaint gradient) {
-        List<Color> colors = makeColors(gradient);
-        List<Function> functions = new ArrayList<Function>();
-        for (int currentPosition = 0, lastPosition = colors.size() - 1;
-                currentPosition < lastPosition;
-                currentPosition++) {
-            Color currentColor = colors.get(currentPosition);
-            Color nextColor = colors.get(currentPosition + 1);
-            float[] c0 = currentColor.getColorComponents(null);
-            float[] c1 = nextColor.getColorComponents(null);
-            Function function = new Function(2, null, null, c0, c1, 1.0);
-            functions.add(function);
-        }
-        return functions;
-    }
-
-    private static List<Color> makeColors(MultipleGradientPaint gradient) {
-        Color[] svgColors = gradient.getColors();
-        List<Color> gradientColors = new ArrayList<Color>(svgColors.length + 2);
-        float[] fractions = gradient.getFractions();
-        if (fractions[0] > 0f) {
-            gradientColors.add(getsRGBColor(svgColors[0]));
-        }
-        for (Color c : svgColors) {
-            gradientColors.add(getsRGBColor(c));
-        }
-        if (fractions[fractions.length - 1] < 1f) {
-            gradientColors.add(getsRGBColor(svgColors[svgColors.length - 1]));
-        }
-        return gradientColors;
-    }
-
-}
diff --git a/src/java/org/apache/fop/render/shading/Pattern.java b/src/java/org/apache/fop/render/shading/Pattern.java
deleted file mode 100644 (file)
index 91101a3..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.
- */
-
-package org.apache.fop.render.shading;
-
-import java.util.List;
-
-public class Pattern {
-
-    private final int patternType;
-
-    private final Shading shading;
-
-    private final List<Double> matrix;
-
-    Pattern(int patternType, Shading shading, List<Double> matrix) {
-        this.patternType = patternType;
-        this.shading = shading;
-        this.matrix = matrix;
-    }
-
-    /**
-     * Either one (1) for tiling, or two (2) for shading.
-     */
-    public int getPatternType() {
-        return patternType;
-    }
-
-    public Shading getShading() {
-        return shading;
-    }
-
-    public List<Double> getMatrix() {
-        return matrix;
-    }
-
-}
diff --git a/src/java/org/apache/fop/render/shading/Shading.java b/src/java/org/apache/fop/render/shading/Shading.java
deleted file mode 100644 (file)
index 89b4add..0000000
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * 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.
- */
-
-package org.apache.fop.render.shading;
-
-import java.util.List;
-
-import org.apache.fop.pdf.PDFDeviceColorSpace;
-import org.apache.fop.pdf.PDFNumber;
-
-
-public class Shading {
-
-    public interface FunctionRenderer {
-
-        void outputFunction(StringBuilder out);
-    }
-
-    /**
-     * Required: The Type of shading (1,2,3,4,5,6,7)
-     */
-    private final int shadingType;
-
-    /**
-     * A ColorSpace representing the colorspace. "DeviceRGB" is an example.
-     */
-    private final PDFDeviceColorSpace colorSpace;
-
-    /**
-     * Required for Type 2: An Array of four numbers specifying
-     *                      the starting and ending coordinate pairs
-     * Required for Type 3: An Array of six numbers [x0,y0,r0,x1,y1,r1]
-     *                      specifying the centers and radii of
-     *                      the starting and ending circles.
-     */
-    private final List<Double> coords;
-
-    /**
-     * Required for Type 1, 2, and 3:
-     * The object of the color mapping function (usually type 2 or 3).
-     * Optional for Type 4,5,6, and 7: When it's nearly the same thing.
-     */
-    private final Function function;
-
-    /**
-     * Optional: A List specifying the clipping rectangle
-     */
-    private final List<Double> bbox;
-
-    /**
-     * Optional for Type 1: A transformation matrix
-     */
-    private final List<Double> matrix;
-
-    /**
-     * The background color. Since shading is opaque,
-     * this is very rarely used.
-     */
-    private final List<Double> background;
-
-    /**
-     * Optional for Type 1: Array of four numbers, xmin, xmax, ymin, ymax.
-     *                      Default is [0 1 0 1]
-     * Optional for Type 2: An array of two numbers between which the blend
-     *                      varies between start and end points. Default is 0, 1.
-     * Optional for Type 3: An array of two numbers between which the blend
-     *                      varies between start and end points. Default is 0, 1.
-     */
-    private final List<Double> domain;
-
-    /**
-     * Required for Type 4,5,6, and 7: Array of Doubles which specifies
-     * how to decode coordinate and color component values.
-     * Each type has a differing number of decode array members, so check
-     * the spec.
-     * Page 303 in PDF Spec 1.3
-     */
-    private final List<Double> decode;
-
-    /**
-     * Required for Type 2+3: An Array of two boolean values specifying
-     * whether to extend the start and end colors past the start
-     * and end points, respectively.
-     * Default is false, false.
-     */
-    private final List<Boolean> extend;
-
-    /**
-     * Required for Type 4,5,6, and 7: Specifies the number of bits used
-     * to represent each vertex coordinate.
-     * Allowed to be 1,2,4,8,12,16,24, or 32.
-     */
-    private final int bitsPerCoordinate;
-
-    /**
-     * Required for Type 4,5,6, and 7: Specifies the number of bits used
-     * to represent the edge flag for each vertex.
-     * Allowed to be 2,4,or 8, while the Edge flag itself is allowed to
-     * be 0,1 or 2.
-     */
-    private final int bitsPerFlag;
-
-    /**
-     * Optional: A flag whether or not to filter the shading function
-     * to prevent aliasing artifacts. Default is false.
-     */
-    private final boolean antiAlias;
-
-    /**
-     * Required for Type 4,5,6, and 7: Specifies the number of bits used
-     * to represent each color coordinate.
-     * Allowed to be 1,2,4,8,12, or 16
-     */
-    private final int bitsPerComponent;
-
-    /**
-     * Required for Type 5:The number of vertices in each "row" of
-     * the lattice; it must be greater than or equal to 2.
-     */
-    private final int verticesPerRow;
-
-    public Shading(int shadingType, PDFDeviceColorSpace colorSpace,
-            List<Double> coords, Function function) {
-        this.shadingType = shadingType;
-        this.colorSpace = colorSpace;
-        this.background = null;
-        this.bbox = null;
-        this.antiAlias = false;
-        this.coords = coords;
-        this.domain = null;
-        this.function = function;
-        this.extend = null;
-        this.matrix = null;
-        this.decode = null;
-        this.bitsPerCoordinate = 0;
-        this.bitsPerFlag = 0;
-        this.bitsPerComponent = 0;
-        this.verticesPerRow = 0;
-    }
-
-    public int getShadingType() {
-        return shadingType;
-    }
-
-    public PDFDeviceColorSpace getColorSpace() {
-        return colorSpace;
-    }
-
-    public List<Double> getCoords() {
-        return coords;
-    }
-
-    public Function getFunction() {
-        return function;
-    }
-
-    public List<Double> getBBox() {
-        return bbox;
-    }
-
-    public List<Double> getMatrix() {
-        return matrix;
-    }
-
-    public List<Double> getBackground() {
-        return background;
-    }
-
-    public List<Double> getDomain() {
-        return domain;
-    }
-
-    public List<Double> getDecode() {
-        return decode;
-    }
-
-    public List<Boolean> getExtend() {
-        return extend;
-    }
-
-    public int getBitsPerCoordinate() {
-        return bitsPerCoordinate;
-    }
-
-    public int getBitsPerFlag() {
-        return bitsPerFlag;
-    }
-
-    public boolean isAntiAlias() {
-        return antiAlias;
-    }
-
-    public int getBitsPerComponent() {
-        return bitsPerComponent;
-    }
-
-    public int getVerticesPerRow() {
-        return verticesPerRow;
-    }
-
-    public void output(StringBuilder out, FunctionRenderer functionRenderer) {
-        out.append("<<\n/ShadingType " + shadingType + "\n");
-        if (colorSpace != null) {
-            out.append("/ColorSpace /" + colorSpace.getName() + "\n");
-        }
-
-        if (background != null) {
-            out.append("/Background ");
-            outputDoubles(out, background);
-            out.append("\n");
-        }
-
-        if (bbox != null) {
-            out.append("/BBox");
-            outputDoubles(out, bbox);
-            out.append("\n");
-        }
-
-        if (antiAlias) {
-            out.append("/AntiAlias " + antiAlias + "\n");
-        }
-
-        switch (shadingType) {
-        // Function based shading
-        case 1: outputShadingType1(out, functionRenderer); break;
-        // Axial shading
-        case 2:
-        // Radial shading
-        case 3: outputShadingType2or3(out, functionRenderer); break;
-        // Free-form Gouraud-shaded triangle meshes
-        case 4:
-        // Coons patch meshes
-        case 6:
-        // Tensor product patch meshes
-        case 7: outputShadingType4or6or7(out, functionRenderer); break;
-        // Lattice Free form gouraud-shaded triangle mesh
-        case 5: outputShadingType5(out, functionRenderer); break;
-        default: throw new UnsupportedOperationException("Shading type " + shadingType);
-        }
-
-        out.append(">>");
-    }
-
-    private void outputDoubles(StringBuilder out, List<Double> doubles) {
-        out.append("[ ");
-        for (Double d : doubles) {
-            out.append(PDFNumber.doubleOut(d));
-            out.append(" ");
-        }
-        out.append("]");
-    }
-
-    private void outputShadingType1(StringBuilder out, Shading.FunctionRenderer functionRenderer) {
-        if (domain != null) {
-            out.append("/Domain ");
-            outputDoubles(out, domain);
-            out.append("\n");
-        } else {
-            out.append("/Domain [ 0 1 ] \n");
-        }
-
-        if (matrix != null) {
-            out.append("/Matrix ");
-            outputDoubles(out, matrix);
-            out.append("\n");
-        }
-        outputFunction(out, functionRenderer);
-    }
-
-    private void outputShadingType2or3(StringBuilder out, Shading.FunctionRenderer functionRenderer) {
-        if (coords != null) {
-            out.append("/Coords ");
-            outputDoubles(out, coords);
-            out.append("\n");
-        }
-
-        if (domain != null) {
-            out.append("/Domain ");
-            outputDoubles(out, domain);
-            out.append("\n");
-        } else {
-            out.append("/Domain [ 0 1 ] \n");
-        }
-
-        if (extend != null) {
-            out.append("/Extend [");
-            for (Boolean b : extend) {
-                out.append(b);
-                out.append(" ");
-            }
-            out.append("\n");
-        } else {
-            out.append("/Extend [ true true ] \n");
-        }
-
-        outputFunction(out, functionRenderer);
-    }
-
-    private void outputShadingType4or6or7(StringBuilder out, Shading.FunctionRenderer functionRenderer) {
-        if (bitsPerCoordinate > 0) {
-            out.append("/BitsPerCoordinate " + bitsPerCoordinate + "\n");
-        } else {
-            out.append("/BitsPerCoordinate 1 \n");
-        }
-
-        if (bitsPerComponent > 0) {
-            out.append("/BitsPerComponent " + bitsPerComponent + "\n");
-        } else {
-            out.append("/BitsPerComponent 1 \n");
-        }
-
-        if (bitsPerFlag > 0) {
-            out.append("/BitsPerFlag " + bitsPerFlag + "\n");
-        } else {
-            out.append("/BitsPerFlag 2 \n");
-        }
-
-        if (decode != null) {
-            out.append("/Decode ");
-            outputDoubles(out, decode);
-            out.append("\n");
-        }
-
-        outputFunction(out, functionRenderer);
-    }
-
-    private void outputShadingType5(StringBuilder out, Shading.FunctionRenderer functionRenderer) {
-        if (bitsPerCoordinate > 0) {
-            out.append("/BitsPerCoordinate " + bitsPerCoordinate + "\n");
-        } else {
-            out.append("/BitsPerCoordinate 1 \n");
-        }
-
-        if (bitsPerComponent > 0) {
-            out.append("/BitsPerComponent " + bitsPerComponent + "\n");
-        } else {
-            out.append("/BitsPerComponent 1 \n");
-        }
-
-        if (decode != null) {
-            out.append("/Decode ");
-            outputDoubles(out, decode);
-            out.append("\n");
-        }
-
-        outputFunction(out, functionRenderer);
-
-        if (verticesPerRow > 0) {
-            out.append("/VerticesPerRow " + verticesPerRow + "\n");
-        } else {
-            out.append("/VerticesPerRow 2 \n");
-        }
-    }
-
-    private void outputFunction(StringBuilder out, FunctionRenderer functionRenderer) {
-        if (function != null) {
-            out.append("/Function ");
-            functionRenderer.outputFunction(out);
-            out.append("\n");
-        }
-    }
-}
index 359c1c0aacbbc7d4996c8dc93c69c22bf90661bd..f8a480d83fe1071d22436ee45f0435ba1104d22f 100644 (file)
@@ -93,13 +93,13 @@ import org.apache.fop.pdf.PDFResources;
 import org.apache.fop.pdf.PDFShading;
 import org.apache.fop.pdf.PDFText;
 import org.apache.fop.pdf.PDFXObject;
+import org.apache.fop.render.gradient.Function;
+import org.apache.fop.render.gradient.GradientMaker;
+import org.apache.fop.render.gradient.Pattern;
+import org.apache.fop.render.gradient.Shading;
 import org.apache.fop.render.pdf.ImageRawCCITTFaxAdapter;
 import org.apache.fop.render.pdf.ImageRawJPEGAdapter;
 import org.apache.fop.render.pdf.ImageRenderedAdapter;
-import org.apache.fop.render.shading.Function;
-import org.apache.fop.render.shading.GradientMaker;
-import org.apache.fop.render.shading.Pattern;
-import org.apache.fop.render.shading.Shading;
 
 /**
  * <p>PDF Graphics 2D.