From: Vincent Hennebert Date: Mon, 14 Jul 2014 21:24:02 +0000 (+0000) Subject: Renamed shading package to gradient X-Git-Tag: fop-2_0~97^2~13 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=137171a8e7b96fcff3b9c87195cda692b1fdbfa0;p=xmlgraphics-fop.git Renamed shading package to gradient git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/FOP-2393_gradient-rendering@1610534 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/java/org/apache/fop/pdf/PDFFunction.java b/src/java/org/apache/fop/pdf/PDFFunction.java index bdd61a86d..65ec0ea90 100644 --- a/src/java/org/apache/fop/pdf/PDFFunction.java +++ b/src/java/org/apache/fop/pdf/PDFFunction.java @@ -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. diff --git a/src/java/org/apache/fop/pdf/PDFShading.java b/src/java/org/apache/fop/pdf/PDFShading.java index a45c14e66..577e10a09 100644 --- a/src/java/org/apache/fop/pdf/PDFShading.java +++ b/src/java/org/apache/fop/pdf/PDFShading.java @@ -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 index 000000000..f37479538 --- /dev/null +++ b/src/java/org/apache/fop/render/gradient/Function.java @@ -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 domain; + + /** + * Required: 2 * n Array of Double numbers which are possible outputs to the function + */ + private List 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 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 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 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 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 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 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 domain, List 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 domain, List range, + List functions, List bounds, + List 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 getBounds() { + return bounds; + } + + /** + * The function domain + */ + public List getDomain() { + return domain; + } + + /** + * The function size + */ + public List getSize() { + return size; + } + + /** + * Gets the function encoding + */ + public List getEncode() { + return encode; + } + + /** + * Gets the sub-functions + */ + public List getFunctions() { + if (functions == null) { + return Collections.emptyList(); + } else { + return functions; + } + } + + /** + * Gets the function filter + */ + public List 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 getRange() { + return range; + } + + /** + * Gets the function decoding + */ + public List 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 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 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 index 000000000..02db2c5fe --- /dev/null +++ b/src/java/org/apache/fop/render/gradient/GradientMaker.java @@ -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 coords = new java.util.ArrayList(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 coords = new java.util.ArrayList(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 coords, + AffineTransform baseTransform, AffineTransform transform) { + List matrix = makeTransform(gradient, baseTransform, transform); + List bounds = makeBounds(gradient); + List 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 makeTransform(MultipleGradientPaint gradient, + AffineTransform baseTransform, AffineTransform transform) { + AffineTransform gradientTransform = new AffineTransform(baseTransform); + gradientTransform.concatenate(transform); + gradientTransform.concatenate(gradient.getTransform()); + List matrix = new ArrayList(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 makeBounds(MultipleGradientPaint gradient) { + // TODO is the conversion to double necessary? + float[] fractions = gradient.getFractions(); + List bounds = new java.util.ArrayList(fractions.length); + for (float offset : fractions) { + if (0f < offset && offset < 1f) { + bounds.add(Double.valueOf(offset)); + } + } + return bounds; + } + + private static List makeFunctions(MultipleGradientPaint gradient) { + List colors = makeColors(gradient); + List functions = new ArrayList(); + 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 makeColors(MultipleGradientPaint gradient) { + Color[] svgColors = gradient.getColors(); + List gradientColors = new ArrayList(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 index 000000000..cc244f58c --- /dev/null +++ b/src/java/org/apache/fop/render/gradient/Pattern.java @@ -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 matrix; + + Pattern(int patternType, Shading shading, List 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 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 index 000000000..61f933cdd --- /dev/null +++ b/src/java/org/apache/fop/render/gradient/Shading.java @@ -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 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 bbox; + + /** + * Optional for Type 1: A transformation matrix + */ + private final List matrix; + + /** + * The background color. Since shading is opaque, + * this is very rarely used. + */ + private final List 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 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 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 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 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 getCoords() { + return coords; + } + + public Function getFunction() { + return function; + } + + public List getBBox() { + return bbox; + } + + public List getMatrix() { + return matrix; + } + + public List getBackground() { + return background; + } + + public List getDomain() { + return domain; + } + + public List getDecode() { + return decode; + } + + public List 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 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"); + } + } +} diff --git a/src/java/org/apache/fop/render/ps/svg/PSSVGGraphics2D.java b/src/java/org/apache/fop/render/ps/svg/PSSVGGraphics2D.java index 9f428dca6..55811f2c9 100644 --- a/src/java/org/apache/fop/render/ps/svg/PSSVGGraphics2D.java +++ b/src/java/org/apache/fop/render/ps/svg/PSSVGGraphics2D.java @@ -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 index 8fb6528cb..000000000 --- a/src/java/org/apache/fop/render/shading/Function.java +++ /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 domain; - - /** - * Required: 2 * n Array of Double numbers which are possible outputs to the function - */ - private List 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 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 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 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 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 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 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 domain, List 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 domain, List range, - List functions, List bounds, - List 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 getBounds() { - return bounds; - } - - /** - * The function domain - */ - public List getDomain() { - return domain; - } - - /** - * The function size - */ - public List getSize() { - return size; - } - - /** - * Gets the function encoding - */ - public List getEncode() { - return encode; - } - - /** - * Gets the sub-functions - */ - public List getFunctions() { - if (functions == null) { - return Collections.emptyList(); - } else { - return functions; - } - } - - /** - * Gets the function filter - */ - public List 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 getRange() { - return range; - } - - /** - * Gets the function decoding - */ - public List 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 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 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 index d9c55ea75..000000000 --- a/src/java/org/apache/fop/render/shading/GradientMaker.java +++ /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 coords = new java.util.ArrayList(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 coords = new java.util.ArrayList(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 coords, - AffineTransform baseTransform, AffineTransform transform) { - List matrix = makeTransform(gradient, baseTransform, transform); - List bounds = makeBounds(gradient); - List 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 makeTransform(MultipleGradientPaint gradient, - AffineTransform baseTransform, AffineTransform transform) { - AffineTransform gradientTransform = new AffineTransform(baseTransform); - gradientTransform.concatenate(transform); - gradientTransform.concatenate(gradient.getTransform()); - List matrix = new ArrayList(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 makeBounds(MultipleGradientPaint gradient) { - // TODO is the conversion to double necessary? - float[] fractions = gradient.getFractions(); - List bounds = new java.util.ArrayList(fractions.length); - for (float offset : fractions) { - if (0f < offset && offset < 1f) { - bounds.add(Double.valueOf(offset)); - } - } - return bounds; - } - - private static List makeFunctions(MultipleGradientPaint gradient) { - List colors = makeColors(gradient); - List functions = new ArrayList(); - 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 makeColors(MultipleGradientPaint gradient) { - Color[] svgColors = gradient.getColors(); - List gradientColors = new ArrayList(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 index 91101a324..000000000 --- a/src/java/org/apache/fop/render/shading/Pattern.java +++ /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 matrix; - - Pattern(int patternType, Shading shading, List 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 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 index 89b4added..000000000 --- a/src/java/org/apache/fop/render/shading/Shading.java +++ /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 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 bbox; - - /** - * Optional for Type 1: A transformation matrix - */ - private final List matrix; - - /** - * The background color. Since shading is opaque, - * this is very rarely used. - */ - private final List 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 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 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 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 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 getCoords() { - return coords; - } - - public Function getFunction() { - return function; - } - - public List getBBox() { - return bbox; - } - - public List getMatrix() { - return matrix; - } - - public List getBackground() { - return background; - } - - public List getDomain() { - return domain; - } - - public List getDecode() { - return decode; - } - - public List 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 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"); - } - } -} diff --git a/src/java/org/apache/fop/svg/PDFGraphics2D.java b/src/java/org/apache/fop/svg/PDFGraphics2D.java index 359c1c0aa..f8a480d83 100644 --- a/src/java/org/apache/fop/svg/PDFGraphics2D.java +++ b/src/java/org/apache/fop/svg/PDFGraphics2D.java @@ -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; /** *

PDF Graphics 2D.