aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache
diff options
context:
space:
mode:
authorVincent Hennebert <vhennebert@apache.org>2014-07-18 19:48:02 +0000
committerVincent Hennebert <vhennebert@apache.org>2014-07-18 19:48:02 +0000
commitcdf8be3d3a3f4fde67723863d368b1096c305de9 (patch)
tree1e761f8593c6e5aad411be786ad5f83b1a454c68 /src/java/org/apache
parentd8823a706376a572303ab86004c7370b12ef7d85 (diff)
parent27b9b2ecbfca055a3aad1eddeefd2c7f4aa62ad7 (diff)
downloadxmlgraphics-fop-cdf8be3d3a3f4fde67723863d368b1096c305de9.tar.gz
xmlgraphics-fop-cdf8be3d3a3f4fde67723863d368b1096c305de9.zip
Merged branch FOP-2393_gradient-rendering back into trunk
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1611783 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java/org/apache')
-rw-r--r--src/java/org/apache/fop/pdf/PDFFactory.java500
-rw-r--r--src/java/org/apache/fop/pdf/PDFFunction.java327
-rw-r--r--src/java/org/apache/fop/pdf/PDFPattern.java12
-rw-r--r--src/java/org/apache/fop/pdf/PDFShading.java531
-rw-r--r--src/java/org/apache/fop/render/gradient/Function.java399
-rw-r--r--src/java/org/apache/fop/render/gradient/GradientMaker.java168
-rw-r--r--src/java/org/apache/fop/render/gradient/Pattern.java (renamed from src/java/org/apache/fop/render/shading/Function.java)48
-rw-r--r--src/java/org/apache/fop/render/gradient/Shading.java263
-rw-r--r--src/java/org/apache/fop/render/ps/PSImageHandlerSVG.java15
-rw-r--r--src/java/org/apache/fop/render/ps/svg/PSFunction.java143
-rw-r--r--src/java/org/apache/fop/render/ps/svg/PSPattern.java103
-rw-r--r--src/java/org/apache/fop/render/ps/svg/PSSVGGraphics2D.java238
-rw-r--r--src/java/org/apache/fop/render/ps/svg/PSShading.java228
-rw-r--r--src/java/org/apache/fop/render/shading/FunctionDelegate.java451
-rw-r--r--src/java/org/apache/fop/render/shading/FunctionPattern.java363
-rw-r--r--src/java/org/apache/fop/render/shading/GradientFactory.java162
-rw-r--r--src/java/org/apache/fop/render/shading/GradientRegistrar.java45
-rw-r--r--src/java/org/apache/fop/render/shading/PDFGradientFactory.java76
-rw-r--r--src/java/org/apache/fop/render/shading/PSGradientFactory.java70
-rw-r--r--src/java/org/apache/fop/render/shading/Pattern.java22
-rw-r--r--src/java/org/apache/fop/render/shading/Shading.java26
-rw-r--r--src/java/org/apache/fop/render/shading/ShadingPattern.java105
-rw-r--r--src/java/org/apache/fop/svg/PDFGraphics2D.java230
23 files changed, 1105 insertions, 3420 deletions
diff --git a/src/java/org/apache/fop/pdf/PDFFactory.java b/src/java/org/apache/fop/pdf/PDFFactory.java
index b1e23f35f..cad0a405d 100644
--- a/src/java/org/apache/fop/pdf/PDFFactory.java
+++ b/src/java/org/apache/fop/pdf/PDFFactory.java
@@ -20,14 +20,12 @@
package org.apache.fop.pdf;
// Java
-import java.awt.Color;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Iterator;
@@ -41,7 +39,6 @@ import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.apache.xmlgraphics.java2d.color.ColorUtil;
import org.apache.xmlgraphics.java2d.color.NamedColorSpace;
import org.apache.xmlgraphics.xmp.Metadata;
@@ -244,188 +241,35 @@ public class PDFFactory {
/* ========================= functions ================================= */
/**
- * Make a Type 0 sampled function
- *
- * @param theDomain List objects of Double objects.
- * This is the domain of the function.
- * See page 264 of the PDF 1.3 Spec.
- * @param theRange List objects of Double objects.
- * This is the Range of the function.
- * See page 264 of the PDF 1.3 Spec.
- * @param theSize A List object of Integer objects.
- * This is the number of samples in each input dimension.
- * I can't imagine there being more or less than two input dimensions,
- * so maybe this should be an array of length 2.
- *
- * See page 265 of the PDF 1.3 Spec.
- * @param theBitsPerSample An int specifying the number of bits user
- * to represent each sample value.
- * Limited to 1,2,4,8,12,16,24 or 32.
- * See page 265 of the 1.3 PDF Spec.
- * @param theOrder The order of interpolation between samples.
- * Default is 1 (one). Limited
- * to 1 (one) or 3, which means linear or cubic-spline interpolation.
- *
- * This attribute is optional.
- *
- * See page 265 in the PDF 1.3 spec.
- * @param theEncode 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 optional.
- *
- * See page 265 in the PDF 1.3 spec.
- * @param theDecode List objects of Double objects.
- * This is a linear mapping of sample values into the range.
- * The default is just the range.
- *
- * This attribute is optional.
- * Read about it on page 265 of the PDF 1.3 spec.
- * @param theFunctionDataStream The sample values that specify
- * the function are provided in a stream.
- *
- * This is optional, but is almost always used.
- *
- * Page 265 of the PDF 1.3 spec has more.
- * @param theFilter This is a vector of String objects which
- * are the various filters that have are to be
- * applied to the stream to make sense of it.
- * Order matters, so watch out.
- *
- * This is not documented in the Function section of the PDF 1.3 spec,
- * it was deduced from samples that this is sometimes used, even if we may never
- * use it in FOP. It is added for completeness sake.
- * @param theFunctionType This is the type of function (0,2,3, or 4).
- * It should be 0 as this is the constructor for sampled functions.
- * @return the PDF function that was created
- */
- public PDFFunction makeFunction(int theFunctionType, List theDomain,
- List theRange, List theSize,
- int theBitsPerSample, int theOrder,
- List theEncode, List theDecode,
- StringBuffer theFunctionDataStream,
- List theFilter) {
- // Type 0 function
- PDFFunction function = new PDFFunction(theFunctionType, theDomain,
- theRange, theSize,
- theBitsPerSample, theOrder,
- theEncode, theDecode,
- theFunctionDataStream,
- theFilter);
-
- function = registerFunction(function);
- return (function);
- }
-
- /**
* make a type Exponential interpolation function
* (for shading usually)
- *
- * @param theDomain List objects of Double objects.
+ * @param domain List objects of Double objects.
* This is the domain of the function.
* See page 264 of the PDF 1.3 Spec.
- * @param theRange List of Doubles that is the Range of the function.
+ * @param range List of Doubles that is the Range of the function.
* See page 264 of the PDF 1.3 Spec.
- * @param theCZero This is a vector of Double objects which defines the function result
+ * @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 theCOne This is a vector of Double objects which defines the function result
+ * @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 theInterpolationExponentN This is the inerpolation exponent.
+ * @param interpolationExponentN This is the inerpolation exponent.
*
* This attribute is required.
* PDF Spec page 268
- * @param theFunctionType The type of the function, which should be 2.
- * @return the PDF function that was created
- */
- public PDFFunction makeFunction(int theFunctionType, List theDomain,
- List theRange, List theCZero,
- List theCOne,
- double theInterpolationExponentN) { // type 2
- PDFFunction function = new PDFFunction(theFunctionType, theDomain,
- theRange, theCZero, theCOne,
- theInterpolationExponentN);
- function = registerFunction(function);
- return (function);
- }
-
- /**
- * Make a Type 3 Stitching function
*
- * @param theDomain List objects of Double objects.
- * This is the domain of the function.
- * See page 264 of the PDF 1.3 Spec.
- * @param theRange List objects of Double objects.
- * This is the Range of the function.
- * See page 264 of the PDF 1.3 Spec.
- * @param theFunctions An 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 theBounds 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 theEncode 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.
- * @param theFunctionType This is the function type. It should be 3,
- * for a stitching function.
* @return the PDF function that was created
*/
- public PDFFunction makeFunction(int theFunctionType, List theDomain,
- List theRange, List theFunctions,
- List theBounds,
- List theEncode) {
- // Type 3
-
- PDFFunction function = new PDFFunction(theFunctionType, theDomain,
- theRange, theFunctions,
- theBounds, theEncode);
-
+ public PDFFunction makeFunction(List domain, List range, float[] cZero, float[] cOne,
+ double interpolationExponentN) {
+ PDFFunction function = new PDFFunction(domain, range, cZero, cOne, interpolationExponentN);
function = registerFunction(function);
- return (function);
- }
-
- /**
- * make a postscript calculator function
- *
- * @param theNumber the PDF object number
- * @param theFunctionType the type of function to make
- * @param theDomain the domain values
- * @param theRange the range values of the function
- * @param theFunctionDataStream a string containing the pdf drawing
- * @return the PDF function that was created
- */
- public PDFFunction makeFunction(int theNumber, int theFunctionType,
- List theDomain, List theRange,
- StringBuffer theFunctionDataStream) {
- // Type 4
- PDFFunction function = new PDFFunction(theFunctionType, theDomain,
- theRange,
- theFunctionDataStream);
-
- function = registerFunction(function);
- return (function);
-
+ return function;
}
/**
@@ -445,175 +289,6 @@ public class PDFFactory {
/* ========================= shadings ================================== */
/**
- * make a function based shading object
- *
- * @param res the PDF resource context to add the shading, may be null
- * @param theShadingType The type of shading object, which should be 1 for function
- * based shading.
- * @param theColorSpace The colorspace is 'DeviceRGB' or something similar.
- * @param theBackground An array of color components appropriate to the
- * colorspace key specifying a single color value.
- * This key is used by the f operator buy ignored by the sh operator.
- * @param theBBox List of double's representing a rectangle
- * in the coordinate space that is current at the
- * time of shading is imaged. Temporary clipping
- * boundary.
- * @param theAntiAlias Whether or not to anti-alias.
- * @param theDomain Optional vector of Doubles specifying the domain.
- * @param theMatrix List of Doubles specifying the matrix.
- * If it's a pattern, then the matrix maps it to pattern space.
- * If it's a shading, then it maps it to current user space.
- * It's optional, the default is the identity matrix
- * @param theFunction The PDF Function that maps an (x,y) location to a color
- * @return the PDF shading that was created
- */
- public PDFShading makeShading(PDFResourceContext res, int theShadingType,
- PDFDeviceColorSpace theColorSpace,
- List theBackground, List theBBox,
- boolean theAntiAlias, List theDomain,
- List theMatrix,
- PDFFunction theFunction) {
- // make Shading of Type 1
- PDFShading shading = new PDFShading(theShadingType,
- theColorSpace, theBackground,
- theBBox, theAntiAlias, theDomain,
- theMatrix, theFunction);
-
- shading = registerShading(res, shading);
- return (shading);
- }
-
- /**
- * Make an axial or radial shading object.
- *
- * @param res the PDF resource context to add the shading, may be null
- * @param theShadingType 2 or 3 for axial or radial shading
- * @param theColorSpace "DeviceRGB" or similar.
- * @param theBackground theBackground An array of color components appropriate to the
- * colorspace key specifying a single color value.
- * This key is used by the f operator buy ignored by the sh operator.
- * @param theBBox List of double's representing a rectangle
- * in the coordinate space that is current at the
- * time of shading is imaged. Temporary clipping
- * boundary.
- * @param theAntiAlias Default is false
- * @param theCoords List of four (type 2) or 6 (type 3) Double
- * @param theDomain List of Doubles specifying the domain
- * @param theFunction the Stitching (PDFfunction type 3) function,
- * even if it's stitching a single function
- * @param theExtend List of Booleans of whether to extend the
- * start and end colors past the start and end points
- * The default is [false, false]
- * @return the PDF shading that was created
- */
- public PDFShading makeShading(PDFResourceContext res, int theShadingType,
- PDFDeviceColorSpace theColorSpace,
- List theBackground, List theBBox,
- boolean theAntiAlias, List theCoords,
- List theDomain, PDFFunction theFunction,
- List theExtend) {
- // make Shading of Type 2 or 3
- PDFShading shading = new PDFShading(theShadingType,
- theColorSpace, theBackground,
- theBBox, theAntiAlias, theCoords,
- theDomain, theFunction,
- theExtend);
-
- shading = registerShading(res, shading);
-
- return (shading);
- }
-
- /**
- * Make a free-form gouraud shaded triangle mesh, coons patch mesh, or tensor patch mesh
- * shading object
- *
- * @param res the PDF resource context to add the shading, may be null
- * @param theShadingType 4, 6, or 7 depending on whether it's
- * Free-form gouraud-shaded triangle meshes, coons patch meshes,
- * or tensor product patch meshes, respectively.
- * @param theColorSpace "DeviceRGB" or similar.
- * @param theBackground theBackground An array of color components appropriate to the
- * colorspace key specifying a single color value.
- * This key is used by the f operator buy ignored by the sh operator.
- * @param theBBox List of double's representing a rectangle
- * in the coordinate space that is current at the
- * time of shading is imaged. Temporary clipping
- * boundary.
- * @param theAntiAlias Default is false
- * @param theBitsPerCoordinate 1,2,4,8,12,16,24 or 32.
- * @param theBitsPerComponent 1,2,4,8,12, and 16
- * @param theBitsPerFlag 2,4,8.
- * @param theDecode List of Doubles see PDF 1.3 spec pages 303 to 312.
- * @param theFunction the PDFFunction
- * @return the PDF shading that was created
- */
- public PDFShading makeShading(PDFResourceContext res, int theShadingType,
- PDFDeviceColorSpace theColorSpace,
- List theBackground, List theBBox,
- boolean theAntiAlias,
- int theBitsPerCoordinate,
- int theBitsPerComponent,
- int theBitsPerFlag, List theDecode,
- PDFFunction theFunction) {
- // make Shading of type 4,6 or 7
- PDFShading shading = new PDFShading(theShadingType,
- theColorSpace, theBackground,
- theBBox, theAntiAlias,
- theBitsPerCoordinate,
- theBitsPerComponent,
- theBitsPerFlag, theDecode,
- theFunction);
-
- shading = registerShading(res, shading);
-
- return (shading);
- }
-
- /**
- * make a Lattice-Form Gouraud mesh shading object
- *
- * @param res the PDF resource context to add the shading, may be null
- * @param theShadingType 5 for lattice-Form Gouraud shaded-triangle mesh
- * without spaces. "Shading1" or "Sh1" are good examples.
- * @param theColorSpace "DeviceRGB" or similar.
- * @param theBackground theBackground An array of color components appropriate to the
- * colorspace key specifying a single color value.
- * This key is used by the f operator buy ignored by the sh operator.
- * @param theBBox List of double's representing a rectangle
- * in the coordinate space that is current at the
- * time of shading is imaged. Temporary clipping
- * boundary.
- * @param theAntiAlias Default is false
- * @param theBitsPerCoordinate 1,2,4,8,12,16, 24, or 32
- * @param theBitsPerComponent 1,2,4,8,12,24,32
- * @param theDecode List of Doubles. See page 305 in PDF 1.3 spec.
- * @param theVerticesPerRow number of vertices in each "row" of the lattice.
- * @param theFunction The PDFFunction that's mapped on to this shape
- * @return the PDF shading that was created
- */
- public PDFShading makeShading(PDFResourceContext res, int theShadingType,
- PDFDeviceColorSpace theColorSpace,
- List theBackground, List theBBox,
- boolean theAntiAlias,
- int theBitsPerCoordinate,
- int theBitsPerComponent, List theDecode,
- int theVerticesPerRow,
- PDFFunction theFunction) {
- // make shading of Type 5
- PDFShading shading = new PDFShading(theShadingType,
- theColorSpace, theBackground,
- theBBox, theAntiAlias,
- theBitsPerCoordinate,
- theBitsPerComponent, theDecode,
- theVerticesPerRow, theFunction);
-
- shading = registerShading(res, shading);
-
- return (shading);
- }
-
- /**
* Registers a shading object against the document
* @param res The PDF resource context
* @param shading The shading object to be registered
@@ -697,148 +372,6 @@ public class PDFFactory {
return pattern;
}
- /**
- * Make a smooth shading pattern
- *
- * @param res the PDF resource context to add the shading, may be null
- * @param thePatternType the type of the pattern, which is 2, smooth shading
- * @param theShading the PDF Shading object that comprises this pattern
- * @param theXUID optional:the extended unique Identifier if used.
- * @param theExtGState optional: the extended graphics state, if used.
- * @param theMatrix Optional:List of Doubles that specify the matrix.
- * @return the PDF pattern that was created
- */
- public PDFPattern makePattern(PDFResourceContext res,
- int thePatternType, PDFShading theShading,
- List theXUID, StringBuffer theExtGState,
- List theMatrix) {
- PDFPattern pattern = new PDFPattern(2, theShading,
- theXUID, theExtGState, theMatrix);
-
- PDFPattern oldpatt = getDocument().findPattern(pattern);
- if (oldpatt == null) {
- getDocument().registerObject(pattern);
- } else {
- pattern = oldpatt;
- }
-
- if (res != null) {
- res.getPDFResources().addPattern(pattern);
- } else {
- getDocument().getResources().addPattern(pattern);
- }
-
- return (pattern);
- }
-
- /**
- * Make a gradient
- *
- * @param res the PDF resource context to add the shading, may be null
- * @param radial if true a radial gradient will be created
- * @param theColorspace the colorspace of the gradient
- * @param theColors the list of colors for the gradient
- * @param theBounds the list of bounds associated with the colors
- * @param theCoords the coordinates for the gradient
- * @param theMatrix the coordinate-transformation matrix
- * @return the PDF pattern that was created
- */
- public PDFPattern makeGradient(PDFResourceContext res, boolean radial,
- PDFDeviceColorSpace theColorspace,
- List theColors, List theBounds,
- List theCoords, List theMatrix) {
- PDFShading myShad;
- PDFFunction myfunky;
- PDFFunction myfunc;
- List theCzero;
- List theCone;
- PDFPattern myPattern;
- //PDFColorSpace theColorSpace;
- double interpolation = 1.000;
- List theFunctions = new ArrayList();
-
- int currentPosition;
- int lastPosition = theColors.size() - 1;
-
-
- // if 5 elements, the penultimate element is 3.
- // do not go beyond that, because you always need
- // to have a next color when creating the function.
-
- for (currentPosition = 0; currentPosition < lastPosition;
- currentPosition++) { // for every consecutive color pair
- Color currentColor = (Color)theColors.get(currentPosition);
- Color nextColor = (Color)theColors.get(currentPosition + 1);
-
- // colorspace must be consistent, so we simply convert to sRGB where necessary
- if (!currentColor.getColorSpace().isCS_sRGB()) {
- //Convert to sRGB
- currentColor = ColorUtil.toSRGBColor(currentColor);
- theColors.set(currentPosition, currentColor);
- }
- if (!nextColor.getColorSpace().isCS_sRGB()) {
- //Convert to sRGB
- nextColor = ColorUtil.toSRGBColor(nextColor);
- theColors.set(currentPosition + 1, nextColor);
- }
-
- theCzero = toColorVector(currentColor);
- theCone = toColorVector(nextColor);
-
- myfunc = makeFunction(2, null, null, theCzero, theCone,
- interpolation);
-
- theFunctions.add(myfunc);
-
- } // end of for every consecutive color pair
-
- myfunky = makeFunction(3, null, null, theFunctions, theBounds,
- null);
-
- if (radial) {
- if (theCoords.size() == 6) {
- myShad = makeShading(res, 3, getDocument().getPDFColorSpace(),
- null, null,
- false, theCoords, null, myfunky,
- null);
- } else { // if the center x, center y, and radius specifiy
- // the gradient, then assume the same center x, center y,
- // and radius of zero for the other necessary component
- List newCoords = new ArrayList();
- newCoords.add(theCoords.get(0));
- newCoords.add(theCoords.get(1));
- newCoords.add(theCoords.get(2));
- newCoords.add(theCoords.get(0));
- newCoords.add(theCoords.get(1));
- newCoords.add(new Double(0.0));
-
- myShad = makeShading(res, 3, getDocument().getPDFColorSpace(),
- null, null,
- false, newCoords, null, myfunky,
- null);
-
- }
- } else {
- myShad = makeShading(res, 2, getDocument().getPDFColorSpace(),
- null, null,
- false, theCoords, null, myfunky,
- null);
-
- }
-
- myPattern = makePattern(res, 2, myShad, null, null, theMatrix);
-
- return (myPattern);
- }
-
- private List toColorVector(Color nextColor) {
- List vector = new java.util.ArrayList();
- float[] comps = nextColor.getColorComponents(null);
- for (int i = 0, c = comps.length; i < c; i++) {
- vector.add(new Double(comps[i]));
- }
- return vector;
- }
/* ============= named destinations and the name dictionary ============ */
@@ -1866,16 +1399,11 @@ public class PDFFactory {
String colorName = ncs.getColorName();
final Double zero = new Double(0d);
final Double one = new Double(1d);
- List theDomain = Arrays.asList(new Double[] {zero, one});
- List theRange = Arrays.asList(new Double[] {zero, one, zero, one, zero, one});
- List theCZero = Arrays.asList(new Double[] {one, one, one});
- List theCOne = new ArrayList();
- float[] comps = ncs.getRGBColor().getColorComponents(null);
- for (int i = 0, c = comps.length; i < c; i++) {
- theCOne.add(new Double(comps[i]));
- }
- PDFFunction tintFunction = makeFunction(2, theDomain, theRange,
- theCZero, theCOne, 1.0d);
+ List domain = Arrays.asList(new Double[] {zero, one});
+ List range = Arrays.asList(new Double[] {zero, one, zero, one, zero, one});
+ float[] cZero = new float[] {1f, 1f, 1f};
+ float[] cOne = ncs.getRGBColor().getColorComponents(null);
+ PDFFunction tintFunction = makeFunction(domain, range, cZero, cOne, 1.0d);
PDFSeparationColorSpace cs = new PDFSeparationColorSpace(colorName, tintFunction);
getDocument().registerObject(cs);
if (res != null) {
diff --git a/src/java/org/apache/fop/pdf/PDFFunction.java b/src/java/org/apache/fop/pdf/PDFFunction.java
index 09cbd9708..3ce581d7f 100644
--- a/src/java/org/apache/fop/pdf/PDFFunction.java
+++ b/src/java/org/apache/fop/pdf/PDFFunction.java
@@ -19,12 +19,15 @@
package org.apache.fop.pdf;
-// Java...
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
-import org.apache.fop.render.shading.Function;
-import org.apache.fop.render.shading.FunctionDelegate;
-import org.apache.fop.render.shading.FunctionPattern;
+import org.apache.fop.render.gradient.Function;
+import org.apache.fop.render.gradient.Function.SubFunctionRenderer;
+import org.apache.fop.render.gradient.GradientMaker;
+import org.apache.fop.render.gradient.GradientMaker.DoubleFormatter;
/**
* class representing a PDF Function.
@@ -37,75 +40,11 @@ import org.apache.fop.render.shading.FunctionPattern;
*
* All PDF Functions have a FunctionType (0,2,3, or 4), a Domain, and a Range.
*/
-public class PDFFunction extends PDFObject implements Function {
+public class PDFFunction extends PDFObject {
- private FunctionDelegate delegate;
+ private final Function function;
- /**
- * create an complete Function object of Type 0, A Sampled function.
- *
- * Use null for an optional object parameter if you choose not to use it.
- * For optional int parameters, pass the default.
- *
- * @param theDomain List objects of Double objects.
- * This is the domain of the function.
- * See page 264 of the PDF 1.3 Spec.
- * @param theRange List objects of Double objects.
- * This is the Range of the function.
- * See page 264 of the PDF 1.3 Spec.
- * @param theSize A List object of Integer objects.
- * This is the number of samples in each input dimension.
- * I can't imagine there being more or less than two input dimensions,
- * so maybe this should be an array of length 2.
- *
- * See page 265 of the PDF 1.3 Spec.
- * @param theBitsPerSample An int specifying the number of bits
- used to represent each sample value.
- * Limited to 1,2,4,8,12,16,24 or 32.
- * See page 265 of the 1.3 PDF Spec.
- * @param theOrder The order of interpolation between samples. Default is 1 (one). Limited
- * to 1 (one) or 3, which means linear or cubic-spline interpolation.
- *
- * This attribute is optional.
- *
- * See page 265 in the PDF 1.3 spec.
- * @param theEncode 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 optional.
- *
- * See page 265 in the PDF 1.3 spec.
- * @param theDecode List objects of Double objects.
- * This is a linear mapping of sample values into the range.
- * The default is just the range.
- *
- * This attribute is optional.
- * Read about it on page 265 of the PDF 1.3 spec.
- * @param theFunctionDataStream The sample values that specify
- * the function are provided in a stream.
- *
- * This is optional, but is almost always used.
- *
- * Page 265 of the PDF 1.3 spec has more.
- * @param theFilter This is a vector of String objects which are the various filters that
- * have are to be applied to the stream to make sense of it. Order matters,
- * so watch out.
- *
- * This is not documented in the Function section of the PDF 1.3 spec,
- * it was deduced from samples that this is sometimes used, even if we may never
- * use it in FOP. It is added for completeness sake.
- * @param theFunctionType This is the type of function (0,2,3, or 4).
- * It should be 0 as this is the constructor for sampled functions.
- */
- public PDFFunction(int theFunctionType, List<Double> theDomain,
- List<Double> theRange, List<Double> theSize, int theBitsPerSample,
- int theOrder, List<Double> theEncode, List<Double> theDecode,
- StringBuffer theFunctionDataStream, List<String> theFilter) {
- delegate = new FunctionDelegate(this, theFunctionType, theDomain, theRange,
- theSize, theBitsPerSample, theOrder, theEncode, theDecode,
- theFunctionDataStream, theFilter);
- }
+ private final List<PDFFunction> pdfFunctions;
/**
* create an complete Function object of Type 2, an Exponential Interpolation function.
@@ -113,104 +52,44 @@ public class PDFFunction extends PDFObject implements Function {
* Use null for an optional object parameter if you choose not to use it.
* For optional int parameters, pass the default.
*
- * @param theDomain List objects of Double objects.
+ * @param domain List objects of Double objects.
* This is the domain of the function.
* See page 264 of the PDF 1.3 Spec.
- * @param theRange List of Doubles that is the Range of the function.
+ * @param range List of Doubles that is the Range of the function.
* See page 264 of the PDF 1.3 Spec.
- * @param theCZero This is a vector of Double objects which defines the function result
+ * @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 theCOne This is a vector of Double objects which defines the function result
+ * @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 theInterpolationExponentN This is the inerpolation exponent.
+ * @param interpolationExponentN This is the inerpolation exponent.
*
* This attribute is required.
* PDF Spec page 268
- * @param theFunctionType The type of the function, which should be 2.
*/
- public PDFFunction(int theFunctionType, List<Double> theDomain,
- List<Double> theRange, List<Double> theCZero, List<Double> theCOne,
- double theInterpolationExponentN) {
- delegate = new FunctionDelegate(this, theFunctionType, theDomain, theRange,
- theCZero, theCOne, theInterpolationExponentN);
+ public PDFFunction(List<Double> domain, List<Double> range, float[] cZero, float[] cOne,
+ double interpolationExponentN) {
+ this(new Function(domain, range, cZero, cOne, interpolationExponentN));
}
- /**
- * 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 theDomain List objects of Double objects.
- * This is the domain of the function.
- * See page 264 of the PDF 1.3 Spec.
- * @param theRange List objects of Double objects.
- * This is the Range of the function.
- * See page 264 of the PDF 1.3 Spec.
- * @param theFunctions 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 theBounds 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 theEncode 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.
- * @param theFunctionType This is the function type. It should be 3,
- * for a stitching function.
- */
- public PDFFunction(int theFunctionType, List<Double> theDomain,
- List<Double> theRange, List<Function> theFunctions,
- List<Double> theBounds, List<Double> theEncode) {
- delegate = new FunctionDelegate(this, theFunctionType, theDomain, theRange,
- theFunctions, theBounds, theEncode);
+ @SuppressWarnings("unchecked")
+ public PDFFunction(Function function) {
+ this(function, Collections.EMPTY_LIST);
+ }
+ public PDFFunction(Function function, List<PDFFunction> pdfFunctions) {
+ this.function = function;
+ this.pdfFunctions = pdfFunctions;
}
- /**
- * create an complete Function object of Type 4, a postscript calculator function.
- *
- * Use null for an optional object parameter if you choose not to use it.
- * For optional int parameters, pass the default.
- *
- * @param theDomain List object of Double objects.
- * This is the domain of the function.
- * See page 264 of the PDF 1.3 Spec.
- * @param theRange List object of Double objects.
- * This is the Range of the function.
- * See page 264 of the PDF 1.3 Spec.
- * @param theFunctionDataStream This is a stream of arithmetic,
- * boolean, and stack operators and boolean constants.
- * I end up enclosing it in the '{' and '}' braces for you, so don't do it
- * yourself.
- *
- * This attribute is required.
- * It's described on page 269 of the PDF 1.3 spec.
- * @param theFunctionType The type of function which should be 4, as this is
- * a Postscript calculator function
- */
- public PDFFunction(int theFunctionType, List<Double> theDomain,
- List<Double> theRange, StringBuffer theFunctionDataStream) {
- delegate = new FunctionDelegate(this, theFunctionType, theDomain, theRange,
- theFunctionDataStream);
+ public Function getFunction() {
+ return function;
}
/**
@@ -230,8 +109,25 @@ public class PDFFunction extends PDFObject implements Function {
public byte[] toByteString() {
- FunctionPattern pattern = new FunctionPattern(this);
- return encode(pattern.toWriteableString());
+ List<String> functionsStrings = new ArrayList<String>(function.getFunctions().size());
+ for (PDFFunction f : pdfFunctions) {
+ functionsStrings.add(f.referencePDF());
+ }
+ SubFunctionRenderer subFunctionRenderer = new SubFunctionRenderer() {
+
+ public void outputFunction(StringBuilder out, int functionIndex) {
+ out.append(pdfFunctions.get(functionIndex).referencePDF());
+ }
+ };
+ StringBuilder out = new StringBuilder();
+ GradientMaker.DoubleFormatter doubleFormatter = new DoubleFormatter() {
+
+ public String formatDouble(double d) {
+ return PDFNumber.doubleOut(d);
+ }
+ };
+ function.output(out, doubleFormatter, subFunctionRenderer);
+ return encode(out.toString());
}
/** {@inheritDoc} */
@@ -245,91 +141,51 @@ public class PDFFunction extends PDFObject implements Function {
if (!(obj instanceof PDFFunction)) {
return false;
}
- PDFFunction func = (PDFFunction)obj;
- if (delegate.getFunctionType() != func.getFunctionType()) {
+ Function func = ((PDFFunction) obj).function;
+ if (function.getFunctionType() != func.getFunctionType()) {
return false;
}
- if (delegate.getBitsPerSample() != func.getBitsPerSample()) {
+ if (function.getBitsPerSample() != func.getBitsPerSample()) {
return false;
}
- if (delegate.getOrder() != func.getOrder()) {
+ if (function.getOrder() != func.getOrder()) {
return false;
}
- if (delegate.getInterpolationExponentN() != func.getInterpolationExponentN()) {
+ if (function.getInterpolationExponentN() != func.getInterpolationExponentN()) {
return false;
}
- if (delegate.getDomain() != null) {
- if (!delegate.getDomain().equals(func.getDomain())) {
+ if (function.getDomain() != null) {
+ if (!function.getDomain().equals(func.getDomain())) {
return false;
}
} else if (func.getDomain() != null) {
return false;
}
- if (delegate.getRange() != null) {
- if (!delegate.getRange().equals(func.getRange())) {
+ if (function.getRange() != null) {
+ if (!function.getRange().equals(func.getRange())) {
return false;
}
} else if (func.getRange() != null) {
return false;
}
- if (delegate.getSize() != null) {
- if (!delegate.getSize().equals(func.getSize())) {
- return false;
- }
- } else if (func.getSize() != null) {
- return false;
- }
- if (delegate.getEncode() != null) {
- if (!delegate.getEncode().equals(func.getEncode())) {
+ if (function.getEncode() != null) {
+ if (!function.getEncode().equals(func.getEncode())) {
return false;
}
} else if (func.getEncode() != null) {
return false;
}
- if (delegate.getDecode() != null) {
- if (!delegate.getDecode().equals(func.getDecode())) {
- return false;
- }
- } else if (func.getDecode() != null) {
- return false;
- }
- if (delegate.getDataStream() != null) {
- if (!delegate.getDataStream().equals(func.getDataStream())) {
- return false;
- }
- } else if (func.getDataStream() != null) {
- return false;
- }
- if (delegate.getFilter() != null) {
- if (!delegate.getFilter().equals(func.getFilter())) {
- return false;
- }
- } else if (func.getFilter() != null) {
- return false;
- }
- if (delegate.getCZero() != null) {
- if (!delegate.getCZero().equals(func.getCZero())) {
- return false;
- }
- } else if (func.getCZero() != null) {
+ if (!Arrays.equals(function.getCZero(), func.getCZero())) {
return false;
}
- if (delegate.getCOne() != null) {
- if (!delegate.getCOne().equals(func.getCOne())) {
- return false;
- }
- } else if (func.getCOne() != null) {
+ if (!Arrays.equals(function.getCOne(), func.getCOne())) {
return false;
}
- if (delegate.getFunctions() != null) {
- if (!delegate.getFunctions().equals(func.getFunctions())) {
- return false;
- }
- } else if (func.getFunctions() != null) {
+ if (!pdfFunctions.equals(((PDFFunction) obj).pdfFunctions)) {
return false;
}
- if (delegate.getBounds() != null) {
- if (!delegate.getBounds().equals(func.getBounds())) {
+ if (function.getBounds() != null) {
+ if (!function.getBounds().equals(func.getBounds())) {
return false;
}
} else if (func.getBounds() != null) {
@@ -338,63 +194,4 @@ public class PDFFunction extends PDFObject implements Function {
return true;
}
- public int getFunctionType() {
- return delegate.getFunctionType();
- }
-
- public List<Double> getBounds() {
- return delegate.getBounds();
- }
-
- public List<Double> getDomain() {
- return delegate.getDomain();
- }
-
- public List<Double> getSize() {
- return delegate.getSize();
- }
-
- public List<String> getFilter() {
- return delegate.getFilter();
- }
-
- public List<Double> getEncode() {
- return delegate.getEncode();
- }
-
- public List<Function> getFunctions() {
- return delegate.getFunctions();
- }
-
- public int getBitsPerSample() {
- return delegate.getBitsPerSample();
- }
-
- public double getInterpolationExponentN() {
- return delegate.getInterpolationExponentN();
- }
-
- public int getOrder() {
- return delegate.getOrder();
- }
-
- public List<Double> getRange() {
- return delegate.getRange();
- }
-
- public List<Double> getDecode() {
- return delegate.getDecode();
- }
-
- public StringBuffer getDataStream() {
- return delegate.getDataStream();
- }
-
- public List<Double> getCZero() {
- return delegate.getCZero();
- }
-
- public List<Double> getCOne() {
- return delegate.getCOne();
- }
}
diff --git a/src/java/org/apache/fop/pdf/PDFPattern.java b/src/java/org/apache/fop/pdf/PDFPattern.java
index 9871d15dc..7acffa0c9 100644
--- a/src/java/org/apache/fop/pdf/PDFPattern.java
+++ b/src/java/org/apache/fop/pdf/PDFPattern.java
@@ -23,9 +23,6 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
-import org.apache.fop.render.shading.Pattern;
-import org.apache.fop.render.shading.Shading;
-
/**
* class representing a PDF Function.
*
@@ -36,7 +33,7 @@ import org.apache.fop.render.shading.Shading;
*
* All PDF Functions have a FunctionType (0,2,3, or 4), a Domain, and a Range.
*/
-public class PDFPattern extends PDFPathPaint implements Pattern {
+public class PDFPattern extends PDFPathPaint {
/**
* The resources associated with this pattern
@@ -144,19 +141,18 @@ public class PDFPattern extends PDFPathPaint implements Pattern {
* Create a type 2 pattern (smooth shading)
*
* @param thePatternType the type of the pattern, which is 2, smooth shading
- * @param theShading the PDF Shading object that comprises this pattern
+ * @param shading the Shading object that comprises this pattern
* @param theXUID optional:the extended unique Identifier if used.
* @param theExtGState optional: the extended graphics state, if used.
* @param theMatrix Optional:List of Doubles that specify the matrix.
*/
- public PDFPattern(int thePatternType, Shading theShading,
+ public PDFPattern(int thePatternType, PDFShading shading,
List theXUID, StringBuffer theExtGState,
List theMatrix) {
super();
this.patternType = 2; // thePatternType;
- assert theShading instanceof PDFShading;
- this.shading = (PDFShading)theShading;
+ this.shading = shading;
this.xUID = theXUID;
// this isn't really implemented, so it should always be null.
// I just don't want to have to add a new parameter once it is implemented.
diff --git a/src/java/org/apache/fop/pdf/PDFShading.java b/src/java/org/apache/fop/pdf/PDFShading.java
index eaef78fdd..c4ba5b089 100644
--- a/src/java/org/apache/fop/pdf/PDFShading.java
+++ b/src/java/org/apache/fop/pdf/PDFShading.java
@@ -19,12 +19,12 @@
package org.apache.fop.pdf;
-// Java...
import java.util.List;
-import org.apache.fop.render.shading.Function;
-import org.apache.fop.render.shading.Shading;
-import org.apache.fop.render.shading.ShadingPattern;
+import org.apache.fop.render.gradient.GradientMaker;
+import org.apache.fop.render.gradient.GradientMaker.DoubleFormatter;
+import org.apache.fop.render.gradient.Shading;
+
/**
* class representing a PDF Smooth Shading object.
@@ -36,7 +36,7 @@ import org.apache.fop.render.shading.ShadingPattern;
*
* All PDF Functions have a shadingType (0,2,3, or 4), a Domain, and a Range.
*/
-public class PDFShading extends PDFObject implements Shading {
+public class PDFShading extends PDFObject {
// Guts common to all function types
/**
@@ -44,266 +44,23 @@ public class PDFShading extends PDFObject implements Shading {
*/
protected String shadingName;
- /**
- * Required: The Type of shading (1,2,3,4,5,6,7)
- */
- protected int shadingType = 3; // Default
-
- /**
- * A ColorSpace representing the colorspace. "DeviceRGB" is an example.
- */
- protected PDFDeviceColorSpace colorSpace;
-
- /**
- * The background color. Since shading is opaque,
- * this is very rarely used.
- */
- protected List background;
-
- /**
- * Optional: A List specifying the clipping rectangle
- */
- protected List bBox;
-
- /**
- * Optional: A flag whether or not to filter the shading function
- * to prevent aliasing artifacts. Default is false.
- */
- protected boolean antiAlias;
-
- /**
- * 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.
- */
- protected List domain;
-
- /**
- * Optional for Type 1: A transformation matrix
- */
- protected List matrix;
-
- /**
- * 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.
- */
- protected PDFFunction function;
+ private final Shading shading;
- /**
- * 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.
- */
- protected List coords;
-
- /**
- * 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.
- */
- protected 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.
- */
- protected 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.
- */
- protected int bitsPerFlag;
-
- /**
- * 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
- */
- protected List decode;
-
- /**
- * 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
- */
- protected 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.
- */
- protected int verticesPerRow;
-
- /**
- * Constructor for type function based shading
- *
- * @param theShadingType The type of shading object, which should be 1 for function
- * based shading.
- * @param theColorSpace The colorspace is 'DeviceRGB' or something similar.
- * @param theBackground An array of color components appropriate to the
- * colorspace key specifying a single color value.
- * This key is used by the f operator buy ignored by the sh operator.
- * @param theBBox List of double's representing a rectangle
- * in the coordinate space that is current at the
- * time of shading is imaged. Temporary clipping
- * boundary.
- * @param theAntiAlias Whether or not to anti-alias.
- * @param theDomain Optional vector of Doubles specifying the domain.
- * @param theMatrix List of Doubles specifying the matrix.
- * If it's a pattern, then the matrix maps it to pattern space.
- * If it's a shading, then it maps it to current user space.
- * It's optional, the default is the identity matrix
- * @param theFunction The PDF Function that maps an (x,y) location to a color
- */
- public PDFShading(int theShadingType, PDFDeviceColorSpace theColorSpace,
- List theBackground, List theBBox,
- boolean theAntiAlias, List theDomain,
- List theMatrix, PDFFunction theFunction) {
- super();
- this.shadingType = theShadingType; // 1
- this.colorSpace = theColorSpace;
- this.background = theBackground;
- this.bBox = theBBox;
- this.antiAlias = theAntiAlias;
-
- this.domain = theDomain;
- this.matrix = theMatrix;
- this.function = theFunction;
-
- }
+ private final PDFFunction pdfFunction;
/**
* Constructor for Type 2 and 3
*
- * @param theShadingType 2 or 3 for axial or radial shading
- * @param theColorSpace "DeviceRGB" or similar.
- * @param theBackground theBackground An array of color components appropriate to the
- * colorspace key specifying a single color value.
- * This key is used by the f operator buy ignored by the sh operator.
- * @param theBBox List of double's representing a rectangle
- * in the coordinate space that is current at the
- * time of shading is imaged. Temporary clipping
- * boundary.
- * @param theAntiAlias Default is false
- * @param theCoords List of four (type 2) or 6 (type 3) Double
- * @param theDomain List of Doubles specifying the domain
- * @param theFunction the Stitching (PDFfunction type 3) function,
+ * @param shadingType 2 or 3 for axial or radial shading
+ * @param colorSpace "DeviceRGB" or similar.
+ * @param coords List of four (type 2) or 6 (type 3) Double
+ * @param pdfFunction the Stitching (PDFfunction type 3) function,
* even if it's stitching a single function
- * @param theExtend List of Booleans of whether to extend the start
- * and end colors past the start and end points
- * The default is [false, false]
*/
- public PDFShading(int theShadingType, PDFDeviceColorSpace theColorSpace,
- List theBackground, List theBBox,
- boolean theAntiAlias, List theCoords,
- List theDomain, Function theFunction,
- List theExtend) {
- super();
- this.shadingType = theShadingType; // 2 or 3
- this.colorSpace = theColorSpace;
- this.background = theBackground;
- this.bBox = theBBox;
- this.antiAlias = theAntiAlias;
-
- this.coords = theCoords;
- this.domain = theDomain;
- assert theFunction instanceof PDFFunction;
- this.function = (PDFFunction)theFunction;
- this.extend = theExtend;
-
- }
-
- /**
- * Constructor for Type 4,6, or 7
- *
- * @param theShadingType 4, 6, or 7 depending on whether it's
- * Free-form gouraud-shaded triangle meshes, coons patch meshes,
- * or tensor product patch meshes, respectively.
- * @param theColorSpace "DeviceRGB" or similar.
- * @param theBackground theBackground An array of color components appropriate to the
- * colorspace key specifying a single color value.
- * This key is used by the f operator buy ignored by the sh operator.
- * @param theBBox List of double's representing a rectangle
- * in the coordinate space that is current at the
- * time of shading is imaged. Temporary clipping
- * boundary.
- * @param theAntiAlias Default is false
- * @param theBitsPerCoordinate 1,2,4,8,12,16,24 or 32.
- * @param theBitsPerComponent 1,2,4,8,12, and 16
- * @param theBitsPerFlag 2,4,8.
- * @param theDecode List of Doubles see PDF 1.3 spec pages 303 to 312.
- * @param theFunction the PDFFunction
- */
- public PDFShading(int theShadingType, PDFDeviceColorSpace theColorSpace,
- List theBackground, List theBBox,
- boolean theAntiAlias, int theBitsPerCoordinate,
- int theBitsPerComponent, int theBitsPerFlag,
- List theDecode, PDFFunction theFunction) {
- super();
-
- this.shadingType = theShadingType; // 4,6 or 7
- this.colorSpace = theColorSpace;
- this.background = theBackground;
- this.bBox = theBBox;
- this.antiAlias = theAntiAlias;
-
- this.bitsPerCoordinate = theBitsPerCoordinate;
- this.bitsPerComponent = theBitsPerComponent;
- this.bitsPerFlag = theBitsPerFlag;
- this.decode = theDecode;
- this.function = theFunction;
- }
-
- /**
- * Constructor for type 5
- *
- * @param theShadingType 5 for lattice-Form Gouraud shaded-triangle mesh
- * @param theColorSpace "DeviceRGB" or similar.
- * @param theBackground theBackground An array of color components appropriate to the
- * colorspace key specifying a single color value.
- * This key is used by the f operator buy ignored by the sh operator.
- * @param theBBox List of double's representing a rectangle
- * in the coordinate space that is current at the
- * time of shading is imaged. Temporary clipping
- * boundary.
- * @param theAntiAlias Default is false
- * @param theBitsPerCoordinate 1,2,4,8,12,16, 24, or 32
- * @param theBitsPerComponent 1,2,4,8,12,24,32
- * @param theDecode List of Doubles. See page 305 in PDF 1.3 spec.
- * @param theVerticesPerRow number of vertices in each "row" of the lattice.
- * @param theFunction The PDFFunction that's mapped on to this shape
- */
- public PDFShading(int theShadingType, PDFDeviceColorSpace theColorSpace,
- List theBackground, List theBBox,
- boolean theAntiAlias, int theBitsPerCoordinate,
- int theBitsPerComponent, List theDecode,
- int theVerticesPerRow, PDFFunction theFunction) {
- super();
- this.shadingType = theShadingType; // 5
- this.colorSpace = theColorSpace;
- this.background = theBackground;
- this.bBox = theBBox;
- this.antiAlias = theAntiAlias;
-
- this.bitsPerCoordinate = theBitsPerCoordinate;
- this.bitsPerComponent = theBitsPerComponent;
- this.decode = theDecode;
- this.verticesPerRow = theVerticesPerRow;
- this.function = theFunction;
-
+ public PDFShading(int shadingType, PDFDeviceColorSpace colorSpace,
+ List coords, PDFFunction pdfFunction) {
+ shading = new Shading(shadingType, colorSpace, coords, pdfFunction.getFunction());
+ this.pdfFunction = pdfFunction;
}
/**
@@ -340,8 +97,21 @@ public class PDFShading extends PDFObject implements Shading {
* @return the PDF string.
*/
public String toPDFString() {
- ShadingPattern pattern = new ShadingPattern(this);
- return pattern.toString(colorSpace, shadingType, background, bBox, antiAlias);
+ Shading.FunctionRenderer functionRenderer = new Shading.FunctionRenderer() {
+
+ public void outputFunction(StringBuilder out) {
+ out.append(pdfFunction.referencePDF());
+ }
+ };
+ StringBuilder out = new StringBuilder();
+ GradientMaker.DoubleFormatter doubleFormatter = new DoubleFormatter() {
+
+ public String formatDouble(double d) {
+ return PDFNumber.doubleOut(d);
+ }
+ };
+ shading.output(out, doubleFormatter, functionRenderer);
+ return out.toString();
}
/** {@inheritDoc} */
@@ -355,257 +125,54 @@ public class PDFShading extends PDFObject implements Shading {
if (!(obj instanceof PDFShading)) {
return false;
}
- PDFShading shad = (PDFShading)obj;
- if (shadingType != shad.shadingType) {
- return false;
- }
- if (antiAlias != shad.antiAlias) {
- return false;
- }
- if (bitsPerCoordinate != shad.bitsPerCoordinate) {
+ Shading other = ((PDFShading) obj).shading;
+ if (shading.getShadingType() != other.getShadingType()) {
return false;
}
- if (bitsPerFlag != shad.bitsPerFlag) {
+ if (shading.isAntiAlias() != other.isAntiAlias()) {
return false;
}
- if (bitsPerComponent != shad.bitsPerComponent) {
+ if (shading.getBitsPerCoordinate() != other.getBitsPerCoordinate()) {
return false;
}
- if (verticesPerRow != shad.verticesPerRow) {
+ if (shading.getBitsPerFlag() != other.getBitsPerFlag()) {
return false;
}
- if (colorSpace != null) {
- if (!colorSpace.equals(shad.colorSpace)) {
- return false;
- }
- } else if (shad.colorSpace != null) {
- return false;
- }
- if (background != null) {
- if (!background.equals(shad.background)) {
- return false;
- }
- } else if (shad.background != null) {
+ if (shading.getBitsPerComponent() != other.getBitsPerComponent()) {
return false;
}
- if (bBox != null) {
- if (!bBox.equals(shad.bBox)) {
- return false;
- }
- } else if (shad.bBox != null) {
+ if (shading.getVerticesPerRow() != other.getVerticesPerRow()) {
return false;
}
- if (domain != null) {
- if (!domain.equals(shad.domain)) {
+ if (shading.getColorSpace() != null) {
+ if (!shading.getColorSpace().equals(other.getColorSpace())) {
return false;
}
- } else if (shad.domain != null) {
+ } else if (other.getColorSpace() != null) {
return false;
}
- if (matrix != null) {
- if (!matrix.equals(shad.matrix)) {
+ if (shading.getCoords() != null) {
+ if (!shading.getCoords().equals(other.getCoords())) {
return false;
}
- } else if (shad.matrix != null) {
+ } else if (other.getCoords() != null) {
return false;
}
- if (coords != null) {
- if (!coords.equals(shad.coords)) {
+ if (shading.getExtend() != null) {
+ if (!shading.getExtend().equals(other.getExtend())) {
return false;
}
- } else if (shad.coords != null) {
+ } else if (other.getExtend() != null) {
return false;
}
- if (extend != null) {
- if (!extend.equals(shad.extend)) {
+ if (shading.getFunction() != null) {
+ if (!shading.getFunction().equals(other.getFunction())) {
return false;
}
- } else if (shad.extend != null) {
- return false;
- }
- if (decode != null) {
- if (!decode.equals(shad.decode)) {
- return false;
- }
- } else if (shad.decode != null) {
- return false;
- }
- if (function != null) {
- if (!function.equals(shad.function)) {
- return false;
- }
- } else if (shad.function != null) {
+ } else if (other.getFunction() != null) {
return false;
}
return true;
}
- /**
- * A method to write a type 1 shading object
- * @param p The StringBuffer to write the shading object
- * @return Returns the StringBuffer to which the shading object was written
- */
- public StringBuffer handleShadingType1(StringBuffer p) {
- if (this.domain != null) {
- p.append("/Domain [ ");
- for (int domainIndex = 0; domainIndex < domain.size(); domainIndex++) {
- p.append(PDFNumber.doubleOut((Double)this.domain.get(domainIndex))
- + " ");
- }
- p.append("] \n");
- } else {
- p.append("/Domain [ 0 1 ] \n");
- }
-
- if (this.matrix != null) {
- p.append("/Matrix [ ");
- for (int matrixIndex = 0; matrixIndex < matrix.size(); matrixIndex++) {
- p.append(PDFNumber.doubleOut((Double)this.matrix.get(matrixIndex))
- + " ");
- }
- p.append("] \n");
- }
-
- if (this.function != null) {
- p.append("/Function ");
- p.append(this.function.referencePDF() + " \n");
- }
- return p;
- }
-
- /**
- * A method to write a type 2 or 3 shading object
- * @param p The StringBuffer to write the shading object
- * @return Returns the StringBuffer to which the shading object was written
- */
- public StringBuffer handleShadingType2or3(StringBuffer p) {
- // 3 is radial shading (circular gradient)
- if (this.coords != null) {
- p.append("/Coords [ ");
- for (int coordIndex = 0; coordIndex < coords.size(); coordIndex++) {
- p.append(PDFNumber.doubleOut((Double)this.coords.get(coordIndex))
- + " ");
- }
- p.append("] \n");
- }
-
- // DOMAIN
- if (this.domain != null) {
- p.append("/Domain [ ");
- for (int domainIndex = 0; domainIndex < domain.size(); domainIndex++) {
- p.append(PDFNumber.doubleOut((Double)this.domain.get(domainIndex))
- + " ");
- }
- p.append("] \n");
- } else {
- p.append("/Domain [ 0 1 ] \n");
- }
-
- if (this.extend != null) {
- p.append("/Extend [ ");
- for (int extendIndex = 0; extendIndex < extend.size(); extendIndex++) {
- p.append((this.extend.get(extendIndex)) + " ");
- }
-
- p.append("] \n");
- } else {
- p.append("/Extend [ true true ] \n");
- }
-
-
- if (this.function != null) {
- p.append("/Function ");
- p.append(this.function.referencePDF() + " \n");
- }
-
- return p;
- }
-
- /**
- * A method to write a type 4, 6 or 7 shading object
- * @param p The StringBuffer to write the shading object
- * @return Returns the StringBuffer to which the shading object was written
- */
- public StringBuffer handleShadingType4or6or7(StringBuffer p) {
- // 6:coons patch meshes
- // 7://tensor product patch meshes (which no one ever uses)
- if (this.bitsPerCoordinate > 0) {
- p.append("/BitsPerCoordinate " + this.bitsPerCoordinate
- + " \n");
- } else {
- p.append("/BitsPerCoordinate 1 \n");
- }
-
- if (this.bitsPerComponent > 0) {
- p.append("/BitsPerComponent " + this.bitsPerComponent
- + " \n");
- } else {
- p.append("/BitsPerComponent 1 \n");
- }
-
- if (this.bitsPerFlag > 0) {
- p.append("/BitsPerFlag " + this.bitsPerFlag + " \n");
- } else {
- p.append("/BitsPerFlag 2 \n");
- }
-
- if (this.decode != null) {
- p.append("/Decode [ ");
- for (int decodeIndex = 0; decodeIndex < decode.size(); decodeIndex++) {
- p.append((this.decode.get(decodeIndex)) + " ");
- }
-
- p.append("] \n");
- }
-
- if (this.function != null) {
- p.append("/Function ");
- p.append(this.function.referencePDF() + " \n");
- }
-
- return p;
- }
-
- /**
- * A method to write a type 5 shading object
- * @param p The StringBuffer to write the shading object
- * @return Returns the StringBuffer to which the shading object was written
- */
- public StringBuffer handleShadingType5(StringBuffer p) {
- if (this.bitsPerCoordinate > 0) {
- p.append("/BitsPerCoordinate " + this.bitsPerCoordinate
- + " \n");
- } else {
- p.append("/BitsPerCoordinate 1 \n");
- }
-
- if (this.bitsPerComponent > 0) {
- p.append("/BitsPerComponent " + this.bitsPerComponent
- + " \n");
- } else {
- p.append("/BitsPerComponent 1 \n");
- }
-
- if (this.decode != null) {
- p.append("/Decode [ ");
- for (int decodeIndex = 0; decodeIndex < decode.size(); decodeIndex++) {
- p.append((this.decode.get(decodeIndex)) + " ");
- }
-
- p.append("] \n");
- }
-
- if (this.function != null) {
- p.append("/Function ");
- p.append(this.function.referencePDF() + " \n");
- }
-
- if (this.verticesPerRow > 0) {
- p.append("/VerticesPerRow " + this.verticesPerRow + " \n");
- } else {
- p.append("/VerticesPerRow 2 \n");
- }
-
- return p;
- }
}
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..5099fce96
--- /dev/null
+++ b/src/java/org/apache/fop/render/gradient/Function.java
@@ -0,0 +1,399 @@
+/*
+ * 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.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.fop.render.gradient.GradientMaker.DoubleFormatter;
+
+public class Function {
+
+ public interface SubFunctionRenderer {
+
+ void outputFunction(StringBuilder out, int functionIndex);
+ }
+
+ /**
+ * 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;
+
+ /**
+ * 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;
+
+ /* *************************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<Float> 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 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(List<Double> domain, List<Double> range, float[] cZero, float[] cOne,
+ double interpolationExponentN) {
+ this(2, domain, range);
+ this.cZero = cZero;
+ this.cOne = cOne;
+ this.interpolationExponentN = interpolationExponentN;
+ }
+
+ /**
+ * 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 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(List<Double> domain, List<Double> range, List<Function> functions,
+ List<Float> bounds, List<Double> encode) {
+ this(3, domain, range);
+ this.functions = functions;
+ this.bounds = bounds;
+ this.encode = makeEncode(encode);
+ }
+
+ private List<Double> makeEncode(List<Double> encode) {
+ if (encode != null) {
+ return encode;
+ } else {
+ encode = new ArrayList<Double>(functions.size() * 2);
+ for (int i = 0; i < functions.size(); i++) {
+ encode.add(0.0);
+ encode.add(1.0);
+ }
+ return encode;
+ }
+ }
+
+ private Function(int functionType, List<Double> domain, List<Double> range) {
+ this.functionType = functionType;
+ this.domain = (domain == null) ? Arrays.asList(0.0, 1.0) : domain;
+ this.range = range;
+ }
+
+ /**
+ * Gets the function type
+ */
+ public int getFunctionType() {
+ return functionType;
+ }
+
+ /**
+ * Gets the function bounds
+ */
+ public List<Float> getBounds() {
+ return bounds;
+ }
+
+ /**
+ * The function domain
+ */
+ public List<Double> getDomain() {
+ return domain;
+ }
+
+ /**
+ * 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 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 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 output(StringBuilder out, DoubleFormatter doubleFormatter,
+ SubFunctionRenderer subFunctionRenderer) {
+ out.append("<<\n/FunctionType " + functionType + "\n");
+ outputDomain(out, doubleFormatter);
+ if (this.functionType == 0) {
+ outputEncode(out, doubleFormatter);
+ outputBitsPerSample(out);
+ outputOrder(out);
+ outputRange(out, doubleFormatter);
+ out.append(">>");
+ } else if (functionType == 2) {
+ outputRange(out, doubleFormatter);
+ outputCZero(out, doubleFormatter);
+ outputCOne(out, doubleFormatter);
+ outputInterpolationExponentN(out, doubleFormatter);
+ out.append(">>");
+ } else if (functionType == 3) {
+ outputRange(out, doubleFormatter);
+ if (!functions.isEmpty()) {
+ out.append("/Functions [ ");
+ for (int i = 0; i < functions.size(); i++) {
+ subFunctionRenderer.outputFunction(out, i);
+ out.append(' ');
+ }
+ out.append("]\n");
+ }
+ outputEncode(out, doubleFormatter);
+ out.append("/Bounds ");
+ if (bounds != null) {
+ GradientMaker.outputDoubles(out, doubleFormatter, 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 = doubleFormatter.formatDouble(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, doubleFormatter);
+ out.append(">>");
+ }
+ return out.toString();
+ }
+
+ private void outputDomain(StringBuilder p, DoubleFormatter doubleFormatter) {
+ p.append("/Domain ");
+ GradientMaker.outputDoubles(p, doubleFormatter, domain);
+ p.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, DoubleFormatter doubleFormatter) {
+ if (range != null) {
+ out.append("/Range ");
+ GradientMaker.outputDoubles(out, doubleFormatter, range);
+ out.append("\n");
+ }
+ }
+
+ private void outputEncode(StringBuilder out, DoubleFormatter doubleFormatter) {
+ out.append("/Encode ");
+ GradientMaker.outputDoubles(out, doubleFormatter, encode);
+ out.append("\n");
+ }
+
+ private void outputCZero(StringBuilder out, DoubleFormatter doubleFormatter) {
+ if (cZero != null) {
+ out.append("/C0 [ ");
+ for (float c : cZero) {
+ out.append(doubleFormatter.formatDouble(c));
+ out.append(" ");
+ }
+ out.append("]\n");
+ }
+ }
+
+ private void outputCOne(StringBuilder out, DoubleFormatter doubleFormatter) {
+ if (cOne != null) {
+ out.append("/C1 [ ");
+ for (float c : cOne) {
+ out.append(doubleFormatter.formatDouble(c));
+ out.append(" ");
+ }
+ out.append("]\n");
+ }
+ }
+
+ private void outputInterpolationExponentN(StringBuilder out, DoubleFormatter doubleFormatter) {
+ out.append("/N ");
+ out.append(doubleFormatter.formatDouble(interpolationExponentN));
+ out.append("\n");
+ }
+
+}
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..3c847a843
--- /dev/null
+++ b/src/java/org/apache/fop/render/gradient/GradientMaker.java
@@ -0,0 +1,168 @@
+/*
+ * 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 {
+
+ public interface DoubleFormatter {
+
+ String formatDouble(double d);
+ }
+
+ 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(Double.valueOf(startPoint.getX()));
+ coords.add(Double.valueOf(startPoint.getY()));
+ coords.add(Double.valueOf(endPoint.getX()));
+ coords.add(Double.valueOf(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 focal 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<Float> 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(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<Float> makeBounds(MultipleGradientPaint gradient) {
+ float[] fractions = gradient.getFractions();
+ List<Float> bounds = new java.util.ArrayList<Float>(fractions.length);
+ for (float offset : fractions) {
+ if (0f < offset && offset < 1f) {
+ bounds.add(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(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;
+ }
+
+ static void outputDoubles(StringBuilder out, DoubleFormatter doubleFormatter,
+ List<? extends Number> numbers) {
+ out.append("[ ");
+ for (Number n : numbers) {
+ out.append(doubleFormatter.formatDouble(n.doubleValue()));
+ out.append(" ");
+ }
+ out.append("]");
+ }
+
+}
diff --git a/src/java/org/apache/fop/render/shading/Function.java b/src/java/org/apache/fop/render/gradient/Pattern.java
index 5bd44087e..cc244f58c 100644
--- a/src/java/org/apache/fop/render/shading/Function.java
+++ b/src/java/org/apache/fop/render/gradient/Pattern.java
@@ -15,25 +15,37 @@
* limitations under the License.
*/
-package org.apache.fop.render.shading;
+package org.apache.fop.render.gradient;
import java.util.List;
-public interface Function {
- int getFunctionType();
- List<Double> getBounds();
- List<Double> getDomain();
- List<Double> getSize();
- List<String> getFilter();
- List<Double> getEncode();
- List<Function> getFunctions();
- int getBitsPerSample();
- double getInterpolationExponentN();
- int getOrder();
- List<Double> getRange();
- List<Double> getDecode();
- StringBuffer getDataStream();
- List<Double> getCZero();
- List<Double> getCOne();
- byte[] toByteString();
+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
index 000000000..843081b4a
--- /dev/null
+++ b/src/java/org/apache/fop/render/gradient/Shading.java
@@ -0,0 +1,263 @@
+/*
+ * 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.Arrays;
+import java.util.List;
+
+import org.apache.fop.pdf.PDFDeviceColorSpace;
+import org.apache.fop.render.gradient.GradientMaker.DoubleFormatter;
+
+
+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;
+
+ /**
+ * 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.antiAlias = false;
+ this.coords = coords;
+ this.function = function;
+ this.extend = Arrays.asList(true, true);
+ 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<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, DoubleFormatter doubleFormatter, FunctionRenderer functionRenderer) {
+ out.append("<<\n/ShadingType " + shadingType + "\n");
+ if (colorSpace != null) {
+ out.append("/ColorSpace /" + colorSpace.getName() + "\n");
+ }
+
+ if (antiAlias) {
+ out.append("/AntiAlias " + antiAlias + "\n");
+ }
+
+ switch (shadingType) {
+ // Function based shading
+ case 1: outputShadingType1(out, doubleFormatter, functionRenderer); break;
+ // Axial shading
+ case 2:
+ // Radial shading
+ case 3: outputShadingType2or3(out, doubleFormatter, functionRenderer); break;
+ // Free-form Gouraud-shaded triangle meshes
+ case 4:
+ // Coons patch meshes
+ case 6:
+ // Tensor product patch meshes
+ case 7: outputShadingType4or6or7(out, doubleFormatter, functionRenderer); break;
+ // Lattice Free form gouraud-shaded triangle mesh
+ case 5: outputShadingType5(out, doubleFormatter, functionRenderer); break;
+ default: throw new UnsupportedOperationException("Shading type " + shadingType);
+ }
+
+ out.append(">>");
+ }
+
+ private void outputShadingType1(StringBuilder out, DoubleFormatter doubleFormatter,
+ Shading.FunctionRenderer functionRenderer) {
+ outputFunction(out, functionRenderer);
+ }
+
+ private void outputShadingType2or3(StringBuilder out, DoubleFormatter doubleFormatter,
+ Shading.FunctionRenderer functionRenderer) {
+ if (coords != null) {
+ out.append("/Coords ");
+ GradientMaker.outputDoubles(out, doubleFormatter, coords);
+ out.append("\n");
+ }
+
+ out.append("/Extend [ ");
+ for (Boolean b : extend) {
+ out.append(b);
+ out.append(" ");
+ }
+ out.append("]\n");
+
+ outputFunction(out, functionRenderer);
+ }
+
+ private void outputShadingType4or6or7(StringBuilder out, DoubleFormatter doubleFormatter,
+ 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");
+ }
+
+ outputFunction(out, functionRenderer);
+ }
+
+ private void outputShadingType5(StringBuilder out, DoubleFormatter doubleFormatter,
+ 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");
+ }
+
+ 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/PSImageHandlerSVG.java b/src/java/org/apache/fop/render/ps/PSImageHandlerSVG.java
index 4d215926b..be479ec31 100644
--- a/src/java/org/apache/fop/render/ps/PSImageHandlerSVG.java
+++ b/src/java/org/apache/fop/render/ps/PSImageHandlerSVG.java
@@ -33,8 +33,6 @@ import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import javax.imageio.ImageIO;
@@ -314,19 +312,6 @@ public class PSImageHandlerSVG implements ImageHandler {
}
}
String nodeName = curNode.getLocalName();
- //Special case where rasterization needed for radial gradients
- if (nodeName != null && nodeName.equals("ellipse")) {
- String found = "";
- String ellipseFill = curNode.getAttributes().getNamedItem("fill").getNodeValue();
- Pattern pattern = Pattern.compile("#(.*?)\\)");
- Matcher matcher = pattern.matcher(ellipseFill);
- if (matcher.find()) {
- found = matcher.group(1);
- }
- if (gradientsFound.get(found) != null) {
- return true;
- }
- }
boolean inMatch = false;
if (!isMatched) {
inMatch = nodeName != null && gradMatches.contains(nodeName);
diff --git a/src/java/org/apache/fop/render/ps/svg/PSFunction.java b/src/java/org/apache/fop/render/ps/svg/PSFunction.java
deleted file mode 100644
index b03e0b590..000000000
--- a/src/java/org/apache/fop/render/ps/svg/PSFunction.java
+++ /dev/null
@@ -1,143 +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.ps.svg;
-
-import java.io.UnsupportedEncodingException;
-import java.util.List;
-
-import org.apache.fop.render.shading.Function;
-import org.apache.fop.render.shading.FunctionDelegate;
-import org.apache.fop.render.shading.FunctionPattern;
-
-public class PSFunction implements Function {
-
- private FunctionDelegate delegate;
-
- /**
- * Creates a Postscript function dictionary
- * @param theFunctionType The function type (0 = Sampled, 2 = Exponential
- * Interpolation, 3 = Stitching)
- * @param theDomain The function domain
- * @param theRange Range used for clipping
- * @param theFunctions An array of sub-functions such as determining the
- * colour values used in a gradient.
- * @param theBounds Bounds determines where each boundary exists for whatever
- * the function is mean't. In a gradient case, it would be the point between
- * colours.
- * @param theEncode The function encoding
- */
- public PSFunction(int theFunctionType, List<Double> theDomain,
- List<Double> theRange, List<Function> theFunctions,
- List<Double> theBounds, List<Double> theEncode) {
- delegate = new FunctionDelegate(this, theFunctionType, theDomain, theRange, theFunctions,
- theBounds, theEncode);
- }
-
- /**
- * Creates a Postscript function dictionary
- * @param theFunctionType The function type (0 = Sampled, 2 = Exponential
- * Interpolation, 3 = Stitching)
- * @param theDomain The function domain
- * @param theRange Range used for clipping
- * @param theCZero In a gradient, this would be the first colour
- * @param theCOne In a gradient, this would be the second colour
- * @param theInterpolationExponentN Determines the number of values
- * the function returns.
- */
- public PSFunction(int theFunctionType, List<Double> theDomain,
- List<Double> theRange, List<Double> theCZero, List<Double> theCOne,
- double theInterpolationExponentN) {
- delegate = new FunctionDelegate(this, theFunctionType, theDomain, theRange, theCZero,
- theCOne, theInterpolationExponentN);
- }
-
- /**
- * Outputs the function to a byte array
- */
- public byte[] toByteString() {
- FunctionPattern pattern = new FunctionPattern(this);
- try {
- return pattern.toWriteableString().getBytes("UTF-8");
- } catch (UnsupportedEncodingException ex) {
- //This should have been made an enum type to avoid throwing exceptions.
- return new byte[0];
- }
- }
-
- public int getFunctionType() {
- return delegate.getFunctionType();
- }
-
- public List<Double> getBounds() {
- return delegate.getBounds();
- }
-
- public List<Double> getDomain() {
- return delegate.getDomain();
- }
-
- public List<Double> getSize() {
- return delegate.getSize();
- }
-
- public List<String> getFilter() {
- return delegate.getFilter();
- }
-
- public List<Double> getEncode() {
- return delegate.getEncode();
- }
-
- public List<Function> getFunctions() {
- return delegate.getFunctions();
- }
-
- public int getBitsPerSample() {
- return delegate.getBitsPerSample();
- }
-
- public double getInterpolationExponentN() {
- return delegate.getInterpolationExponentN();
- }
-
- public int getOrder() {
- return delegate.getOrder();
- }
-
- public List<Double> getRange() {
- return delegate.getRange();
- }
-
- public List<Double> getDecode() {
- return delegate.getDecode();
- }
-
- public StringBuffer getDataStream() {
- return delegate.getDataStream();
- }
-
- public List<Double> getCZero() {
- return delegate.getCZero();
- }
-
- public List<Double> getCOne() {
- return delegate.getCOne();
- }
-}
diff --git a/src/java/org/apache/fop/render/ps/svg/PSPattern.java b/src/java/org/apache/fop/render/ps/svg/PSPattern.java
deleted file mode 100644
index 57a5ad355..000000000
--- a/src/java/org/apache/fop/render/ps/svg/PSPattern.java
+++ /dev/null
@@ -1,103 +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.ps.svg;
-
-import java.util.List;
-
-import org.apache.fop.render.shading.Pattern;
-import org.apache.fop.render.shading.Shading;
-
-public class PSPattern implements Pattern {
-
- /**
- * Either one (1) for tiling, or two (2) for shading.
- */
- protected int patternType = 2; // Default
-
- /**
- * The Shading object comprising the Type 2 pattern
- */
- protected PSShading shading;
-
- /**
- * List of Integers represetning the Extended unique Identifier
- */
- protected List xUID;
-
- /**
- * TODO use PDFGState
- * String representing the extended Graphics state.
- * Probably will never be used like this.
- */
- protected StringBuffer extGState;
-
- /**
- * Creates a radial or axial shading pattern
- * @param thePatternType The pattern type which will be 3 for radial and 2 for axial
- * @param theShading The shading object to determine how the gradient
- * is drawn
- * @param theXUID The XUID
- * @param theExtGState The exit state
- */
- public PSPattern(int thePatternType, Shading theShading, List theXUID,
- StringBuffer theExtGState) {
- this.patternType = 2; // thePatternType;
- assert theShading instanceof PSShading;
- this.shading = (PSShading)theShading;
- this.xUID = theXUID;
- this.extGState = theExtGState; // always null
- }
-
- /**
- * Outputs the radial or axial pattern as a string dictionary to insert
- * into a postscript document.
- */
- public String toString() {
- int vectorSize = 0;
- int tempInt = 0;
- StringBuffer p = new StringBuffer(64);
- p.append("/Pattern setcolorspace\n");
- p.append("<< \n/Type /Pattern \n");
-
- p.append("/PatternType " + this.patternType + " \n");
-
- if (this.shading != null) {
- p.append("/Shading " + this.shading.toString() + " \n");
- }
-
- if (this.xUID != null) {
- vectorSize = this.xUID.size();
- p.append("/XUID [ ");
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append((this.xUID.get(tempInt)) + " ");
- }
- p.append("] \n");
- }
-
- if (this.extGState != null) {
- p.append("/ExtGState " + this.extGState + " \n");
- }
-
- p.append(">> \n");
- p.append("matrix makepattern setcolor\n");
-
- return p.toString();
- }
-}
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 1c15e569b..28fa4ec9c 100644
--- a/src/java/org/apache/fop/render/ps/svg/PSSVGGraphics2D.java
+++ b/src/java/org/apache/fop/render/ps/svg/PSSVGGraphics2D.java
@@ -19,34 +19,29 @@
package org.apache.fop.render.ps.svg;
-import java.awt.Color;
import java.awt.Graphics;
import java.awt.Paint;
import java.awt.geom.AffineTransform;
import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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.ps.PSGraphics2D;
import org.apache.xmlgraphics.ps.PSGenerator;
-import org.apache.fop.pdf.PDFDeviceColorSpace;
-import org.apache.fop.render.shading.Function;
-import org.apache.fop.render.shading.GradientFactory;
-import org.apache.fop.render.shading.GradientRegistrar;
-import org.apache.fop.render.shading.PSGradientFactory;
-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.Function.SubFunctionRenderer;
+import org.apache.fop.render.gradient.GradientMaker;
+import org.apache.fop.render.gradient.GradientMaker.DoubleFormatter;
+import org.apache.fop.render.gradient.Pattern;
+import org.apache.fop.render.gradient.Shading;
-public class PSSVGGraphics2D extends PSGraphics2D implements GradientRegistrar {
+public class PSSVGGraphics2D extends PSGraphics2D {
private static final Log LOG = LogFactory.getLog(PSSVGGraphics2D.class);
@@ -79,167 +74,72 @@ public class PSSVGGraphics2D extends PSGraphics2D implements GradientRegistrar {
protected void applyPaint(Paint paint, boolean fill) {
super.applyPaint(paint, fill);
- if (paint instanceof RadialGradientPaint) {
- RadialGradientPaint rgp = (RadialGradientPaint)paint;
+ if (paint instanceof LinearGradientPaint) {
+ Pattern pattern = GradientMaker.makeLinearGradient((LinearGradientPaint) paint,
+ getBaseTransform(), getTransform());
try {
- handleRadialGradient(rgp, gen);
+ gen.write(outputPattern(pattern));
} catch (IOException ioe) {
handleIOException(ioe);
}
- } else if (paint instanceof LinearGradientPaint) {
- LinearGradientPaint lgp = (LinearGradientPaint)paint;
+ } else if (paint instanceof RadialGradientPaint) {
+ Pattern pattern = GradientMaker.makeRadialGradient((RadialGradientPaint) paint,
+ getBaseTransform(), getTransform());
try {
- handleLinearGradient(lgp, gen);
+ gen.write(outputPattern(pattern));
} catch (IOException ioe) {
handleIOException(ioe);
}
}
}
- private void handleLinearGradient(LinearGradientPaint lgp, PSGenerator gen) throws IOException {
- MultipleGradientPaint.CycleMethodEnum cycle = lgp.getCycleMethod();
- if (cycle != MultipleGradientPaint.NO_CYCLE) {
- return;
- }
- float[] fractions = lgp.getFractions();
- Color[] cols = lgp.getColors();
-
- AffineTransform transform = new AffineTransform(getBaseTransform());
- transform.concatenate(getTransform());
- transform.concatenate(lgp.getTransform());
-
- List theMatrix = new ArrayList();
- double [] mat = new double[6];
- transform.getMatrix(mat);
- for (int idx = 0; idx < mat.length; idx++) {
- theMatrix.add(Double.valueOf(mat[idx]));
- }
-
-
- List<Double> theCoords = new java.util.ArrayList<Double>();
-
-
- AffineTransform start = applyTransform(lgp.getTransform(),
- lgp.getStartPoint().getX(), lgp.getStartPoint().getY());
- AffineTransform end = applyTransform(lgp.getTransform(), lgp.getEndPoint().getX(), lgp.getEndPoint().getY());
- double startX = start.getTranslateX();
- double startY = start.getTranslateY();
- double endX = end.getTranslateX();
- double endY = end.getTranslateY();
-
- double width = endX - startX;
- double height = endY - startY;
-
- startX = startX + width * fractions[0];
- endX = endX - width * (1 - fractions[fractions.length - 1]);
- startY = startY + (height * fractions[0]);
- endY = endY - height * (1 - fractions[fractions.length - 1]);
-
- theCoords.add(startX);
- theCoords.add(startY);
- theCoords.add(endX);
- theCoords.add(endY);
+ private String outputPattern(Pattern pattern) {
+ StringBuilder p = new StringBuilder(64);
+ p.append("/Pattern setcolorspace\n");
+ p.append("<< \n/Type /Pattern \n");
+ p.append("/PatternType " + pattern.getPatternType() + " \n");
- List<Color> someColors = new java.util.ArrayList<Color>();
- for (int count = 0; count < cols.length; count++) {
- Color c1 = cols[count];
- if (c1.getAlpha() != 255) {
- LOG.warn("Opacity is not currently supported for Postscript output");
- }
- someColors.add(c1);
+ if (pattern.getShading() != null) {
+ p.append("/Shading ");
+ outputShading(p, pattern.getShading());
+ p.append(" \n");
}
- List<Double> theBounds = new java.util.ArrayList<Double>();
- for (int count = 1; count < fractions.length - 1; count++) {
- float offset = fractions[count];
- theBounds.add(Double.valueOf(offset));
+ p.append(">> \n");
+ p.append("[ ");
+ for (double m : pattern.getMatrix()) {
+ p.append(getPSGenerator().formatDouble(m));
+ p.append(" ");
}
- PDFDeviceColorSpace colSpace;
- colSpace = new PDFDeviceColorSpace(PDFDeviceColorSpace.DEVICE_RGB);
-
- PSGradientFactory gradientFactory = (PSGradientFactory)GradientFactory.newInstance(this);
- PSPattern myPattern = gradientFactory.createGradient(false, colSpace,
- someColors, theBounds, theCoords, theMatrix);
-
- gen.write(myPattern.toString());
+ p.append("] ");
+ p.append("makepattern setcolor\n");
+ return p.toString();
}
+ private void outputShading(StringBuilder out, Shading shading) {
+ final GradientMaker.DoubleFormatter doubleFormatter = new DoubleFormatter() {
-
- private void handleRadialGradient(RadialGradientPaint rgp, PSGenerator gen) throws IOException {
- MultipleGradientPaint.CycleMethodEnum cycle = rgp.getCycleMethod();
- if (cycle != MultipleGradientPaint.NO_CYCLE) {
- return;
- }
-
- AffineTransform transform;
- transform = new AffineTransform(getBaseTransform());
- transform.concatenate(getTransform());
- transform.concatenate(rgp.getTransform());
-
- AffineTransform resultCentre = applyTransform(rgp.getTransform(),
- rgp.getCenterPoint().getX(), rgp.getCenterPoint().getY());
- AffineTransform resultFocus = applyTransform(rgp.getTransform(),
- rgp.getFocusPoint().getX(), rgp.getFocusPoint().getY());
- double scale = Math.sqrt(rgp.getTransform().getDeterminant());
- double radius = rgp.getRadius() * scale;
- double centreX = resultCentre.getTranslateX();
- double centreY = resultCentre.getTranslateY();
- double focusX = resultFocus.getTranslateX();
- double focusY = resultFocus.getTranslateY();
-
- List<Double> theMatrix = new java.util.ArrayList<Double>();
- double [] mat = new double[6];
- transform.getMatrix(mat);
- for (int idx = 0; idx < mat.length; idx++) {
- theMatrix.add(Double.valueOf(mat[idx]));
- }
-
- List<Double> theCoords = new java.util.ArrayList<Double>();
- float[] fractions = rgp.getFractions();
-
- theCoords.add(centreX);
- theCoords.add(centreY);
- theCoords.add(radius * rgp.getFractions()[0]);
- theCoords.add(focusX);
- theCoords.add(focusY);
- theCoords.add(radius * fractions[fractions.length - 1]);
-
- Color[] cols = rgp.getColors();
- List<Color> someColors = new java.util.ArrayList<Color>();
- for (int count = 0; count < cols.length; count++) {
- Color cc = cols[count];
- if (cc.getAlpha() != 255) {
- /* This should never happen because radial gradients with opacity should now
- * be rasterized in the PSImageHandlerSVG class. Please see the shouldRaster()
- * method for more information. */
- LOG.warn("Opacity is not currently supported for Postscript output");
+ public String formatDouble(double d) {
+ return getPSGenerator().formatDouble(d);
}
-
- someColors.add(cc);
- }
-
- List<Double> theBounds = new java.util.ArrayList<Double>();
- for (int count = 1; count < fractions.length - 1; count++) {
- float offset = fractions[count];
- theBounds.add(Double.valueOf(offset));
- }
- PDFDeviceColorSpace colSpace;
- colSpace = new PDFDeviceColorSpace(PDFDeviceColorSpace.DEVICE_RGB);
-
- PSGradientFactory gradientFactory = (PSGradientFactory)GradientFactory.newInstance(this);
- PSPattern myPattern = gradientFactory.createGradient(true, colSpace,
- someColors, theBounds, theCoords, theMatrix);
-
- gen.write(myPattern.toString());
- }
-
- private AffineTransform applyTransform(AffineTransform base, double posX, double posY) {
- AffineTransform result = AffineTransform.getTranslateInstance(posX, posY);
- AffineTransform orig = base;
- orig.concatenate(result);
- return orig;
+ };
+ final Function function = shading.getFunction();
+ Shading.FunctionRenderer functionRenderer = new Shading.FunctionRenderer() {
+
+ public void outputFunction(StringBuilder out) {
+ SubFunctionRenderer subFunctionRenderer = new Function.SubFunctionRenderer() {
+
+ public void outputFunction(StringBuilder out, int functionIndex) {
+ Function subFunction = function.getFunctions().get(functionIndex);
+ assert subFunction.getFunctions().isEmpty();
+ subFunction.output(out, doubleFormatter, null);
+ }
+ };
+ function.output(out, doubleFormatter, subFunctionRenderer);
+ }
+ };
+ shading.output(out, doubleFormatter, functionRenderer);
}
protected AffineTransform getBaseTransform() {
@@ -259,36 +159,4 @@ public class PSSVGGraphics2D extends PSGraphics2D implements GradientRegistrar {
return new PSSVGGraphics2D(this);
}
- /**
- * Registers a function object against the output format document
- * @param function The function object to register
- * @return Returns either the function which has already been registered
- * or the current new registered object.
- */
- public Function registerFunction(Function function) {
- //Objects aren't needed to be registered in Postscript
- return function;
- }
-
- /**
- * Registers a shading object against the otuput format document
- * @param shading The shading object to register
- * @return Returs either the shading which has already been registered
- * or the current new registered object
- */
- public Shading registerShading(Shading shading) {
- //Objects aren't needed to be registered in Postscript
- return shading;
- }
-
- /**
- * Registers a pattern object against the output format document
- * @param pattern The pattern object to register
- * @return Returns either the pattern which has already been registered
- * or the current new registered object
- */
- public Pattern registerPattern(Pattern pattern) {
- // TODO Auto-generated method stub
- return pattern;
- }
}
diff --git a/src/java/org/apache/fop/render/ps/svg/PSShading.java b/src/java/org/apache/fop/render/ps/svg/PSShading.java
deleted file mode 100644
index e6eba11ad..000000000
--- a/src/java/org/apache/fop/render/ps/svg/PSShading.java
+++ /dev/null
@@ -1,228 +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.ps.svg;
-
-import java.io.UnsupportedEncodingException;
-import java.util.List;
-
-import org.apache.fop.pdf.PDFDeviceColorSpace;
-import org.apache.fop.pdf.PDFNumber;
-import org.apache.fop.render.shading.Function;
-import org.apache.fop.render.shading.Shading;
-import org.apache.fop.render.shading.ShadingPattern;
-
-public class PSShading implements Shading {
-
- /**
- * Required: The Type of shading (1,2,3,4,5,6,7)
- */
- protected int shadingType = 3; // Default
-
- /**
- * A ColorSpace representing the colorspace. "DeviceRGB" is an example.
- */
- protected PDFDeviceColorSpace colorSpace;
-
- /**
- * The background color. Since shading is opaque,
- * this is very rarely used.
- */
- protected List background;
-
- /**
- * Optional: A List specifying the clipping rectangle
- */
- protected List bBox;
-
- /**
- * Optional: A flag whether or not to filter the shading function
- * to prevent aliasing artifacts. Default is false.
- */
- protected boolean antiAlias;
-
- /**
- * 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.
- */
- protected List domain;
-
- /**
- * 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.
- */
- protected PSFunction function;
-
- /**
- * 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.
- */
- protected List coords;
-
- /**
- * 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.
- */
- protected List extend;
-
- /**
- * Constructor for Type 2 and 3
- *
- * @param theShadingType 2 or 3 for axial or radial shading
- * @param theColorSpace "DeviceRGB" or similar.
- * @param theBackground theBackground An array of color components appropriate to the
- * colorspace key specifying a single color value.
- * This key is used by the f operator buy ignored by the sh operator.
- * @param theBBox List of double's representing a rectangle
- * in the coordinate space that is current at the
- * time of shading is imaged. Temporary clipping
- * boundary.
- * @param theAntiAlias Default is false
- * @param theCoords List of four (type 2) or 6 (type 3) Double
- * @param theDomain List of Doubles specifying the domain
- * @param theFunction the Stitching (PDFfunction type 3) function,
- * even if it's stitching a single function
- * @param theExtend List of Booleans of whether to extend the start
- * and end colors past the start and end points
- * The default is [false, false]
- */
- public PSShading(int theShadingType, PDFDeviceColorSpace theColorSpace,
- List<Double> theBackground, List<Double> theBBox,
- boolean theAntiAlias, List<Double> theCoords,
- List<Double> theDomain, Function theFunction,
- List<Integer> theExtend) {
- this.shadingType = theShadingType; // 2 or 3
- this.colorSpace = theColorSpace;
- this.background = theBackground;
- this.bBox = theBBox;
- this.antiAlias = theAntiAlias;
-
- this.coords = theCoords;
- this.domain = theDomain;
- assert theFunction instanceof PSFunction;
- this.function = (PSFunction)theFunction;
- this.extend = theExtend;
- }
-
- /**
- * represent as PS. Whatever the shadingType is, the correct
- * representation spits out. The sets of required and optional
- * attributes are different for each type, but if a required
- * attribute's object was constructed as null, then no error
- * is raised. Instead, the malformed PS that was requested
- * by the construction is dutifully output.
- * This policy should be reviewed.
- *
- * @return the PDF string.
- */
- public String toString() {
- ShadingPattern pattern = new ShadingPattern(this);
- return pattern.toString(colorSpace, shadingType, background, bBox, antiAlias);
- }
-
- /**
- * A method to write a type 2 or 3 shading object
- * @param p The StringBuffer to write the shading object
- * @return Returns the StringBuffer to which the shading object was written
- */
- public StringBuffer handleShadingType2or3(StringBuffer p) {
- if (this.coords != null) {
- p.append("\t/Coords [ ");
- for (int coordIndex = 0; coordIndex < coords.size(); coordIndex++) {
- p.append(PDFNumber.doubleOut((Double)this.coords.get(coordIndex))
- + " ");
- }
- p.append("] \n");
- }
-
- // DOMAIN
- if (this.domain != null) {
- p.append("\t/Domain [ ");
- for (int domainIndex = 0; domainIndex < domain.size(); domainIndex++) {
- p.append(PDFNumber.doubleOut((Double)this.domain.get(domainIndex))
- + " ");
- }
- p.append("] \n");
- } else {
- p.append("\t/Domain [ 0 1 ] \n");
- }
-
- if (this.extend != null) {
- p.append("\t/Extend [ ");
- for (int extendIndex = 0; extendIndex < extend.size(); extendIndex++) {
- p.append((this.extend.get(extendIndex)) + " ");
- }
-
- p.append("] \n");
- } else {
- p.append("\t/Extend [ true true ] \n");
- }
-
-
- if (this.function != null) {
- p.append("\t/Function ");
- try {
- p.append(new String(this.function.toByteString(), "UTF-8") + " \n");
- } catch (UnsupportedEncodingException ex) {
- //This should have been made an enum type to avoid throwing exceptions.
- }
- }
- return p;
- }
-
- /**
- * A method to write a type 1 shading object
- * @param p The StringBuffer to write the shading object
- * @return Returns the StringBuffer to which the shading object was written
- */
- public StringBuffer handleShadingType1(StringBuffer p) {
- // TODO Auto-generated method stub
- return null;
- }
-
- /**
- * A method to write a type 4, 6 or 7 shading object
- * @param p The StringBuffer to write the shading object
- * @return Returns the StringBuffer to which the shading object was written
- */
- public StringBuffer handleShadingType4or6or7(StringBuffer p) {
- // TODO Auto-generated method stub
- return null;
- }
-
- /**
- * A method to write a type 5 shading object
- * @param p The StringBuffer to write the shading object
- * @return Returns the StringBuffer to which the shading object was written
- */
- public StringBuffer handleShadingType5(StringBuffer p) {
- // TODO Auto-generated method stub
- return null;
- }
-}
diff --git a/src/java/org/apache/fop/render/shading/FunctionDelegate.java b/src/java/org/apache/fop/render/shading/FunctionDelegate.java
deleted file mode 100644
index 66a8db9ed..000000000
--- a/src/java/org/apache/fop/render/shading/FunctionDelegate.java
+++ /dev/null
@@ -1,451 +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 FunctionDelegate implements Function {
-
- private Function parentFunction;
-
- /**
- * Required: The Type of function (0,2,3,4) default is 0.
- */
- protected int functionType; // Default
-
- /**
- * Required: 2 * m Array of Double numbers which are possible inputs to the function
- */
- protected List<Double> domain;
-
- /**
- * Required: 2 * n Array of Double numbers which are possible outputs to the function
- */
- protected 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
- */
- protected int bitsPerSample = 1;
-
- /**
- * Optional for Type 0: order of interpolation between samples.
- * Limited to linear (1) or cubic (3). Default is 1
- */
- protected int order = 1;
-
- /**
- * Optional for Type 0: A 2 * m array of Doubles which provides a
- * linear mapping of input values to the domain.
- *
- * Required for Type 3: A 2 * k array of Doubles that, taken
- * in pairs, map each subset of the domain defined by Domain
- * and the Bounds array to the domain of the corresponding function.
- * Should be two values per function, usually (0,1),
- * as in [0 1 0 1] for 2 functions.
- */
- protected List<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.
- */
- protected 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
- */
- protected 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.
- */
- protected List<String> filter;
- /* *************************TYPE 2************************** */
-
- /**
- * Required For Type 2: An Array of n Doubles defining
- * the function result when x=0. Default is [0].
- */
- protected List<Double> cZero;
-
- /**
- * Required For Type 2: An Array of n Doubles defining
- * the function result when x=1. Default is [1].
- */
- protected List<Double> cOne;
-
- /**
- * Required for Type 2: The interpolation exponent.
- * Each value x will return n results.
- * Must be greater than 0.
- */
- protected double interpolationExponentN = 1;
-
- /* *************************TYPE 3************************** */
-
- /**
- * Required for Type 3: An vector of PDFFunctions which
- * form an array of k single input functions making up
- * the stitching function.
- */
- protected List<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.
- */
- protected List<Double> bounds;
-
- /**
- * create an complete Function object of Type 0, A Sampled function.
- *
- * Use null for an optional object parameter if you choose not to use it.
- * For optional int parameters, pass the default.
- *
- * @param theDomain List objects of Double objects.
- * This is the domain of the function.
- * See page 264 of the PDF 1.3 Spec.
- * @param theRange List objects of Double objects.
- * This is the Range of the function.
- * See page 264 of the PDF 1.3 Spec.
- * @param theSize A List object of Integer objects.
- * This is the number of samples in each input dimension.
- * I can't imagine there being more or less than two input dimensions,
- * so maybe this should be an array of length 2.
- *
- * See page 265 of the PDF 1.3 Spec.
- * @param theBitsPerSample An int specifying the number of bits
- used to represent each sample value.
- * Limited to 1,2,4,8,12,16,24 or 32.
- * See page 265 of the 1.3 PDF Spec.
- * @param theOrder The order of interpolation between samples. Default is 1 (one). Limited
- * to 1 (one) or 3, which means linear or cubic-spline interpolation.
- *
- * This attribute is optional.
- *
- * See page 265 in the PDF 1.3 spec.
- * @param theEncode 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 optional.
- *
- * See page 265 in the PDF 1.3 spec.
- * @param theDecode List objects of Double objects.
- * This is a linear mapping of sample values into the range.
- * The default is just the range.
- *
- * This attribute is optional.
- * Read about it on page 265 of the PDF 1.3 spec.
- * @param theFunctionDataStream The sample values that specify
- * the function are provided in a stream.
- *
- * This is optional, but is almost always used.
- *
- * Page 265 of the PDF 1.3 spec has more.
- * @param theFilter This is a vector of String objects which are the various filters that
- * have are to be applied to the stream to make sense of it. Order matters,
- * so watch out.
- *
- * This is not documented in the Function section of the PDF 1.3 spec,
- * it was deduced from samples that this is sometimes used, even if we may never
- * use it in FOP. It is added for completeness sake.
- * @param theFunctionType This is the type of function (0,2,3, or 4).
- * It should be 0 as this is the constructor for sampled functions.
- */
- public FunctionDelegate(Function parentFunction, int theFunctionType, List<Double> theDomain,
- List<Double> theRange, List<Double> theSize, int theBitsPerSample,
- int theOrder, List<Double> theEncode, List<Double> theDecode,
- StringBuffer theFunctionDataStream, List<String> theFilter) {
- this.parentFunction = parentFunction;
- this.functionType = 0; // dang well better be 0;
- this.size = theSize;
- this.bitsPerSample = theBitsPerSample;
- this.order = theOrder; // int
- this.encode = theEncode; // vector of int
- this.decode = theDecode; // vector of int
- this.functionDataStream = theFunctionDataStream;
- this.filter = theFilter; // vector of Strings
-
- // the domain and range are actually two dimensional arrays.
- // so if there's not an even number of items, bad stuff
- // happens.
- this.domain = theDomain;
- this.range = theRange;
- }
-
- /**
- * 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 theDomain List objects of Double objects.
- * This is the domain of the function.
- * See page 264 of the PDF 1.3 Spec.
- * @param theRange List of Doubles that is the Range of the function.
- * See page 264 of the PDF 1.3 Spec.
- * @param theCZero 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 theCOne 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 theInterpolationExponentN This is the inerpolation exponent.
- *
- * This attribute is required.
- * PDF Spec page 268
- * @param theFunctionType The type of the function, which should be 2.
- */
- public FunctionDelegate(Function parentFunction, int theFunctionType, List<Double> theDomain,
- List<Double> theRange, List<Double> theCZero, List<Double> theCOne,
- double theInterpolationExponentN) {
- this.parentFunction = parentFunction;
- this.functionType = 2; // dang well better be 2;
-
- this.cZero = theCZero;
- this.cOne = theCOne;
- this.interpolationExponentN = theInterpolationExponentN;
-
- this.domain = theDomain;
- this.range = theRange;
-
- }
-
- /**
- * 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 theDomain List objects of Double objects.
- * This is the domain of the function.
- * See page 264 of the PDF 1.3 Spec.
- * @param theRange List objects of Double objects.
- * This is the Range of the function.
- * See page 264 of the PDF 1.3 Spec.
- * @param theFunctions 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 theBounds 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 theEncode 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.
- * @param theFunctionType This is the function type. It should be 3,
- * for a stitching function.
- */
- public FunctionDelegate(Function parentFunction, int theFunctionType, List<Double> theDomain,
- List<Double> theRange, List<Function> theFunctions,
- List<Double> theBounds, List<Double> theEncode) {
- this.parentFunction = parentFunction;
- this.functionType = 3; // dang well better be 3;
-
- this.functions = theFunctions;
- this.bounds = theBounds;
- this.encode = theEncode;
- this.domain = theDomain;
- this.range = theRange;
-
- }
-
- /**
- * create an complete Function object of Type 4, a postscript calculator function.
- *
- * Use null for an optional object parameter if you choose not to use it.
- * For optional int parameters, pass the default.
- *
- * @param theDomain List object of Double objects.
- * This is the domain of the function.
- * See page 264 of the PDF 1.3 Spec.
- * @param theRange List object of Double objects.
- * This is the Range of the function.
- * See page 264 of the PDF 1.3 Spec.
- * @param theFunctionDataStream This is a stream of arithmetic,
- * boolean, and stack operators and boolean constants.
- * I end up enclosing it in the '{' and '}' braces for you, so don't do it
- * yourself.
- *
- * This attribute is required.
- * It's described on page 269 of the PDF 1.3 spec.
- * @param theFunctionType The type of function which should be 4, as this is
- * a Postscript calculator function
- */
- public FunctionDelegate(Function parentFunction, int theFunctionType, List<Double> theDomain,
- List<Double> theRange, StringBuffer theFunctionDataStream) {
- this.parentFunction = parentFunction;
- this.functionType = 4; // dang well better be 4;
- this.functionDataStream = theFunctionDataStream;
-
- this.domain = theDomain;
-
- this.range = theRange;
-
- }
-
- /**
- * 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() {
- 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 List<Double> getCZero() {
- return cZero;
- }
-
- /**
- * Gets the function C1 value (color for gradient)
- */
- public List<Double> getCOne() {
- return cOne;
- }
-
- public byte[] toByteString() {
- return parentFunction.toByteString();
- }
-}
diff --git a/src/java/org/apache/fop/render/shading/FunctionPattern.java b/src/java/org/apache/fop/render/shading/FunctionPattern.java
deleted file mode 100644
index 044053a8b..000000000
--- a/src/java/org/apache/fop/render/shading/FunctionPattern.java
+++ /dev/null
@@ -1,363 +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.io.UnsupportedEncodingException;
-
-import org.apache.fop.pdf.PDFFunction;
-import org.apache.fop.pdf.PDFNumber;
-import org.apache.fop.render.ps.svg.PSFunction;
-
-/**
- * A class for writing function objects for different output formats
- */
-public class FunctionPattern {
-
- private Function function;
-
- /**
- * Constructor
- * @param function The function from which to write the output
- */
- public FunctionPattern(Function function) {
- this.function = function;
- }
-
- /**
- * Outputs the function to a byte array
- */
- public String toWriteableString() {
- int vectorSize = 0;
- int numberOfFunctions = 0;
- int tempInt = 0;
- StringBuffer p = new StringBuffer(256);
- p.append("<< \n/FunctionType " + function.getFunctionType() + " \n");
-
- // FunctionType 0
- if (this.function.getFunctionType() == 0) {
- if (function.getDomain() != null) {
- // DOMAIN
- p.append("/Domain [ ");
- vectorSize = function.getDomain().size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut(function.getDomain().get(tempInt))
- + " ");
- }
-
- p.append("] \n");
- } else {
- p.append("/Domain [ 0 1 ] \n");
- }
-
- // SIZE
- if (function.getSize() != null) {
- p.append("/Size [ ");
- vectorSize = function.getSize().size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut(function.getSize().get(tempInt))
- + " ");
- }
- p.append("] \n");
- }
- // ENCODE
- if (function.getEncode() != null) {
- p.append("/Encode [ ");
- vectorSize = function.getEncode().size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut(function.getEncode().get(tempInt))
- + " ");
- }
- p.append("] \n");
- } else {
- p.append("/Encode [ ");
- vectorSize = function.getFunctions().size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append("0 1 ");
- }
- p.append("] \n");
-
- }
-
- // BITSPERSAMPLE
- p.append("/BitsPerSample " + function.getBitsPerSample());
-
- // ORDER (optional)
- if (function.getOrder() == 1 || function.getOrder() == 3) {
- p.append(" \n/Order " + function.getOrder() + " \n");
- }
-
- // RANGE
- if (function.getRange() != null) {
- p.append("/Range [ ");
- vectorSize = function.getRange().size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut(function.getRange().get(tempInt))
- + " ");
- }
-
- p.append("] \n");
- }
-
- // DECODE
- if (function.getDecode() != null) {
- p.append("/Decode [ ");
- vectorSize = function.getDecode().size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut(function.getDecode().get(tempInt))
- + " ");
- }
-
- p.append("] \n");
- }
-
- // LENGTH
- if (function.getDataStream() != null) {
- p.append("/Length " + (function.getDataStream().length() + 1)
- + " \n");
- }
-
- // FILTER?
- if (function.getFilter() != null) { // if there's a filter
- vectorSize = function.getFilter().size();
- p.append("/Filter ");
- if (vectorSize == 1) {
- p.append("/" + (function.getFilter().get(0))
- + " \n");
- } else {
- p.append("[ ");
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append("/" + (function.getFilter().get(0))
- + " ");
- }
- p.append("] \n");
- }
- }
- p.append(">>");
-
- // stream representing the function
- if (function.getDataStream() != null) {
- p.append("\nstream\n" + function.getDataStream()
- + "\nendstream");
- }
-
- // end of if FunctionType 0
-
- } else if (function.getFunctionType() == 2) {
- // DOMAIN
- if (function.getDomain() != null) {
- p.append("/Domain [ ");
- vectorSize = function.getDomain().size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut(function.getDomain().get(tempInt))
- + " ");
- }
-
- p.append("] \n");
- } else {
- p.append("/Domain [ 0 1 ] \n");
- }
-
-
- // RANGE
- if (function.getRange() != null) {
- p.append("/Range [ ");
- vectorSize = function.getRange().size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut(function.getRange().get(tempInt))
- + " ");
- }
-
- p.append("] \n");
- }
-
- // FunctionType, C0, C1, N are required in PDF
-
- // C0
- if (function.getCZero() != null) {
- p.append("/C0 [ ");
- vectorSize = function.getCZero().size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut(function.getCZero().get(tempInt))
- + " ");
- }
- p.append("] \n");
- }
-
- // C1
- if (function.getCOne() != null) {
- p.append("/C1 [ ");
- vectorSize = function.getCOne().size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut(function.getCOne().get(tempInt))
- + " ");
- }
- p.append("] \n");
- }
-
- // N: The interpolation Exponent
- p.append("/N "
- + PDFNumber.doubleOut(Double.valueOf(function.getInterpolationExponentN()))
- + " \n");
-
- p.append(">>");
-
- } else if (function.getFunctionType()
- == 3) { // fix this up when my eyes uncross
- // DOMAIN
- if (function.getDomain() != null) {
- p.append("/Domain [ ");
- vectorSize = function.getDomain().size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut(function.getDomain().get(tempInt))
- + " ");
- }
- p.append("] \n");
- } else {
- p.append("/Domain [ 0 1 ] \n");
- }
-
- // RANGE
- if (function.getRange() != null) {
- p.append("/Range [ ");
- vectorSize = function.getRange().size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut(function.getRange().get(tempInt))
- + " ");
- }
-
- p.append("] \n");
- }
-
- // FUNCTIONS
- if (function.getFunctions() != null) {
- p.append("/Functions [ ");
- numberOfFunctions = function.getFunctions().size();
- for (tempInt = 0; tempInt < numberOfFunctions; tempInt++) {
- try {
- if (function instanceof PSFunction) {
- p.append(new String(function.getFunctions().get(tempInt).toByteString(), "UTF-8")
- + " ");
- } else {
- p.append(((PDFFunction)function.getFunctions().get(tempInt)).referencePDF()
- + " ");
- }
- } catch (UnsupportedEncodingException ex) {
- //This should have been made an enum type to avoid throwing exceptions.
- }
- }
- p.append("] \n");
- }
-
-
- // ENCODE
- if (function.getEncode() != null) {
- p.append("/Encode [ ");
- vectorSize = function.getEncode().size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut(function.getEncode().get(tempInt))
- + " ");
- }
-
- p.append("] \n");
- } else {
- p.append("/Encode [ ");
- vectorSize = function.getFunctions().size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append("0 1 ");
- }
- p.append("] \n");
-
- }
-
-
- // BOUNDS, required, but can be empty
- p.append("/Bounds [ ");
- if (function.getBounds() != null) {
-
- vectorSize = function.getBounds().size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut(function.getBounds().get(tempInt))
- + " ");
- }
-
- } else {
- if (function.getFunctions() != null) {
- // if there are n functions,
- // there must be n-1 bounds.
- // so let each function handle an equal portion
- // of the whole. e.g. if there are 4, then [ 0.25 0.25 0.25 ]
-
- String functionsFraction = PDFNumber.doubleOut(Double.valueOf(1.0
- / (numberOfFunctions)));
-
- for (tempInt = 0; tempInt + 1 < numberOfFunctions;
- tempInt++) {
-
- p.append(functionsFraction + " ");
- }
- }
-
- }
- p.append("]\n>>");
- } else if (function.getFunctionType()
- == 4) { // fix this up when my eyes uncross
- // DOMAIN
- if (function.getDomain() != null) {
- p.append("/Domain [ ");
- vectorSize = function.getDomain().size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut(function.getDomain().get(tempInt))
- + " ");
- }
-
- p.append("] \n");
- } else {
- p.append("/Domain [ 0 1 ] \n");
- }
-
- // RANGE
- if (function.getRange() != null) {
- p.append("/Range [ ");
- vectorSize = function.getRange().size();
- for (tempInt = 0; tempInt < vectorSize; tempInt++) {
- p.append(PDFNumber.doubleOut(function.getRange().get(tempInt))
- + " ");
- }
-
- p.append("] \n");
- }
-
- // LENGTH
- if (function.getDataStream() != null) {
- p.append("/Length " + (function.getDataStream().length() + 1)
- + " \n");
- }
-
- p.append(">>");
-
- // stream representing the function
- if (function.getDataStream() != null) {
- p.append("\nstream\n{ " + function.getDataStream()
- + " }\nendstream");
- }
- }
- return p.toString();
- }
-}
diff --git a/src/java/org/apache/fop/render/shading/GradientFactory.java b/src/java/org/apache/fop/render/shading/GradientFactory.java
deleted file mode 100644
index 87ac11c83..000000000
--- a/src/java/org/apache/fop/render/shading/GradientFactory.java
+++ /dev/null
@@ -1,162 +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.util.ArrayList;
-import java.util.List;
-
-import org.apache.xmlgraphics.java2d.color.ColorUtil;
-
-import org.apache.fop.pdf.PDFDeviceColorSpace;
-import org.apache.fop.render.ps.svg.PSSVGGraphics2D;
-
-public abstract class GradientFactory {
-
- static GradientRegistrar registrar;
-
- /**
- * Constructor
- * @param registrar The object used to register new embedded objects in the
- * output format.
- */
- public static GradientFactory newInstance(GradientRegistrar theRegistrar) {
- registrar = theRegistrar;
- if (registrar instanceof PSSVGGraphics2D) {
- return new PSGradientFactory();
- } else {
- return new PDFGradientFactory();
- }
- }
-
- /**
- * Creates a new gradient
- * @param radial Determines whether the gradient is radial
- * @param theColorspace The colorspace used in PDF and Postscript
- * @param theColors The colors to be used in the gradient
- * @param theBounds The bounds of each color
- * @param theCoords The co-ordinates of the gradient
- * @param theMatrix The matrix for any transformations
- * @return Returns the Pattern object of the gradient
- */
- public abstract Pattern createGradient(boolean radial,
- PDFDeviceColorSpace theColorspace, List<Color> theColors, List<Double> theBounds,
- List<Double> theCoords, List<Double> theMatrix);
-
- protected Pattern makeGradient(boolean radial, PDFDeviceColorSpace theColorspace,
- List<Color> theColors, List<Double> theBounds,
- List<Double> theCoords, List<Double> theMatrix) {
- Shading myShad;
- Function myfunky;
- Function myfunc;
- List<Double> theCzero;
- List<Double> theCone;
- double interpolation = 1.000;
- List<Function> theFunctions = new ArrayList<Function>();
-
- int currentPosition;
- int lastPosition = theColors.size() - 1;
-
-
- // if 5 elements, the penultimate element is 3.
- // do not go beyond that, because you always need
- // to have a next color when creating the function.
-
- for (currentPosition = 0; currentPosition < lastPosition;
- currentPosition++) { // for every consecutive color pair
- Color currentColor = theColors.get(currentPosition);
- Color nextColor = theColors.get(currentPosition + 1);
-
- // colorspace must be consistent, so we simply convert to sRGB where necessary
- if (!currentColor.getColorSpace().isCS_sRGB()) {
- //Convert to sRGB
- currentColor = ColorUtil.toSRGBColor(currentColor);
- theColors.set(currentPosition, currentColor);
- }
- if (!nextColor.getColorSpace().isCS_sRGB()) {
- //Convert to sRGB
- nextColor = ColorUtil.toSRGBColor(nextColor);
- theColors.set(currentPosition + 1, nextColor);
- }
-
- theCzero = toColorVector(currentColor);
- theCone = toColorVector(nextColor);
-
- myfunc = makeFunction(2, null, null, theCzero, theCone,
- interpolation);
-
- theFunctions.add(myfunc);
-
- } // end of for every consecutive color pair
-
- myfunky = makeFunction(3, null, null, theFunctions, theBounds,
- null);
-
- if (radial) {
- if (theCoords.size() == 6) {
- // make Shading of Type 2 or 3
- myShad = makeShading(3, theColorspace, null, null, false, theCoords,
- null, myfunky, null);
- } else { // if the center x, center y, and radius specifiy
- // the gradient, then assume the same center x, center y,
- // and radius of zero for the other necessary component
- List<Double> newCoords = new ArrayList<Double>();
- newCoords.add(theCoords.get(0));
- newCoords.add(theCoords.get(1));
- newCoords.add(theCoords.get(2));
- newCoords.add(theCoords.get(0));
- newCoords.add(theCoords.get(1));
- newCoords.add(Double.valueOf(0.0));
-
- myShad = makeShading(3, theColorspace, null, null, false, newCoords,
- null, myfunky, null);
- }
- } else {
- myShad = makeShading(2, theColorspace, null, null, false, theCoords,
- null, myfunky, null);
- }
- return makePattern(2, myShad, null, null, theMatrix);
- }
-
- public abstract Function makeFunction(int functionType, List<Double> theDomain,
- List<Double> theRange, List<Function> theFunctions,
- List<Double> theBounds, List<Double> theEncode);
-
- public abstract Function makeFunction(int functionType, List<Double> theDomain,
- List<Double> theRange, List<Double> theCZero, List<Double> theCOne,
- double theInterpolationExponentN);
-
- public abstract Shading makeShading(int theShadingType,
- PDFDeviceColorSpace theColorSpace, List<Double> theBackground, List<Double> theBBox,
- boolean theAntiAlias, List<Double> theCoords, List<Double> theDomain,
- Function theFunction, List<Integer> theExtend);
-
- public abstract Pattern makePattern(int thePatternType, Shading theShading, List theXUID,
- StringBuffer theExtGState, List<Double> theMatrix);
-
- private List<Double> toColorVector(Color nextColor) {
- List<Double> vector = new java.util.ArrayList<Double>();
- float[] comps = nextColor.getColorComponents(null);
- for (int i = 0, c = comps.length; i < c; i++) {
- vector.add(Double.valueOf(comps[i]));
- }
- return vector;
- }
-}
diff --git a/src/java/org/apache/fop/render/shading/GradientRegistrar.java b/src/java/org/apache/fop/render/shading/GradientRegistrar.java
deleted file mode 100644
index 617fcd4fb..000000000
--- a/src/java/org/apache/fop/render/shading/GradientRegistrar.java
+++ /dev/null
@@ -1,45 +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;
-
-public interface GradientRegistrar {
-
- /**
- * Registers a function object against the output format document
- * @param function The function object to register
- * @return Returns either the function which has already been registered
- * or the current new registered object.
- */
- Function registerFunction(Function function);
-
- /**
- * Registers a shading object against the output format document
- * @param shading The shading object to register
- * @return Returns either the shading which has already been registered
- * or the current new registered object
- */
- Shading registerShading(Shading shading);
-
- /**
- * Registers a pattern object against the output format document
- * @param pattern The pattern object to register
- * @return Returns either the pattern which has already been registered
- * or the current new registered object
- */
- Pattern registerPattern(Pattern pattern);
-}
diff --git a/src/java/org/apache/fop/render/shading/PDFGradientFactory.java b/src/java/org/apache/fop/render/shading/PDFGradientFactory.java
deleted file mode 100644
index 3b3dcab75..000000000
--- a/src/java/org/apache/fop/render/shading/PDFGradientFactory.java
+++ /dev/null
@@ -1,76 +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.awt.Color;
-import java.util.List;
-
-import org.apache.fop.pdf.PDFDeviceColorSpace;
-import org.apache.fop.pdf.PDFFunction;
-import org.apache.fop.pdf.PDFPattern;
-import org.apache.fop.pdf.PDFShading;
-
-public class PDFGradientFactory extends GradientFactory {
-
- @Override
- public PDFPattern createGradient(boolean radial, PDFDeviceColorSpace theColorspace, List<Color> theColors,
- List<Double> theBounds, List<Double> theCoords, List<Double> theMatrix) {
- return (PDFPattern)makeGradient(radial, theColorspace, theColors, theBounds,
- theCoords, theMatrix);
- }
-
- @Override
- public Function makeFunction(int functionType, List<Double> theDomain,
- List<Double> theRange, List<Function> theFunctions,
- List<Double> theBounds, List<Double> theEncode) {
- Function newFunction = new PDFFunction(functionType, theDomain, theRange, theFunctions,
- theBounds, theEncode);
- newFunction = registrar.registerFunction(newFunction);
- return newFunction;
- }
-
- public Function makeFunction(int functionType, List<Double> theDomain,
- List<Double> theRange, List<Double> theCZero, List<Double> theCOne,
- double theInterpolationExponentN) {
- Function newFunction = new PDFFunction(functionType, theDomain, theRange, theCZero,
- theCOne, theInterpolationExponentN);
- newFunction = registrar.registerFunction(newFunction);
- return newFunction;
- }
-
- @Override
- public Shading makeShading(int theShadingType,
- PDFDeviceColorSpace theColorSpace, List<Double> theBackground, List<Double> theBBox,
- boolean theAntiAlias, List<Double> theCoords, List<Double> theDomain,
- Function theFunction, List<Integer> theExtend) {
- Shading newShading = new PDFShading(theShadingType, theColorSpace, theBackground,
- theBBox, theAntiAlias, theCoords, theDomain, theFunction, theExtend);
- newShading = registrar.registerShading(newShading);
- return newShading;
- }
-
- @Override
- public Pattern makePattern(int thePatternType, Shading theShading, List theXUID,
- StringBuffer theExtGState, List<Double> theMatrix) {
- Pattern newPattern = new PDFPattern(thePatternType, theShading, theXUID, theExtGState,
- theMatrix);
- newPattern = registrar.registerPattern(newPattern);
- return newPattern;
- }
-
-}
diff --git a/src/java/org/apache/fop/render/shading/PSGradientFactory.java b/src/java/org/apache/fop/render/shading/PSGradientFactory.java
deleted file mode 100644
index cd47de93a..000000000
--- a/src/java/org/apache/fop/render/shading/PSGradientFactory.java
+++ /dev/null
@@ -1,70 +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.awt.Color;
-import java.util.List;
-
-import org.apache.fop.pdf.PDFDeviceColorSpace;
-import org.apache.fop.render.ps.svg.PSFunction;
-import org.apache.fop.render.ps.svg.PSPattern;
-import org.apache.fop.render.ps.svg.PSShading;
-
-public class PSGradientFactory extends GradientFactory {
-
- @Override
- public PSPattern createGradient(boolean radial, PDFDeviceColorSpace theColorspace,
- List<Color> theColors, List<Double> theBounds, List<Double> theCoords,
- List<Double> theMatrix) {
- return (PSPattern)makeGradient(radial, theColorspace, theColors, theBounds,
- theCoords, theMatrix);
- }
-
- public Function makeFunction(int functionType, List<Double> theDomain,
- List<Double> theRange, List<Function> theFunctions,
- List<Double> theBounds, List<Double> theEncode) {
- Function newFunction = new PSFunction(functionType, theDomain, theRange, theFunctions,
- theBounds, theEncode);
- return newFunction;
- }
-
- @Override
- public Function makeFunction(int functionType, List<Double> theDomain,
- List<Double> theRange, List<Double> theCZero, List<Double> theCOne,
- double theInterpolationExponentN) {
- Function newFunction = new PSFunction(functionType, theDomain, theRange, theCZero,
- theCOne, theInterpolationExponentN);
- return newFunction;
- }
-
- @Override
- public Shading makeShading(int theShadingType,
- PDFDeviceColorSpace theColorSpace, List<Double> theBackground, List<Double> theBBox,
- boolean theAntiAlias, List<Double> theCoords, List<Double> theDomain,
- Function theFunction, List<Integer> theExtend) {
- Shading newShading = new PSShading(theShadingType, theColorSpace, theBackground, theBBox,
- theAntiAlias, theCoords, theDomain, theFunction, theExtend);
- return newShading;
- }
-
- @Override
- public Pattern makePattern(int thePatternType, Shading theShading, List theXUID,
- StringBuffer theExtGState, List<Double> theMatrix) {
- return new PSPattern(thePatternType, theShading, theXUID, theExtGState);
- }
-}
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 b66926e53..000000000
--- a/src/java/org/apache/fop/render/shading/Pattern.java
+++ /dev/null
@@ -1,22 +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;
-
-public interface Pattern {
-
-}
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 385cb112b..000000000
--- a/src/java/org/apache/fop/render/shading/Shading.java
+++ /dev/null
@@ -1,26 +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;
-
-
-public interface Shading {
- StringBuffer handleShadingType1(StringBuffer p);
- StringBuffer handleShadingType2or3(StringBuffer p);
- StringBuffer handleShadingType4or6or7(StringBuffer p);
- StringBuffer handleShadingType5(StringBuffer p);
-}
diff --git a/src/java/org/apache/fop/render/shading/ShadingPattern.java b/src/java/org/apache/fop/render/shading/ShadingPattern.java
deleted file mode 100644
index 6dac65f55..000000000
--- a/src/java/org/apache/fop/render/shading/ShadingPattern.java
+++ /dev/null
@@ -1,105 +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;
-
-/**
- * A class for writing shading objects for different output formats
- */
-public class ShadingPattern {
-
- private Shading shading;
-
- /**
- * Constructor
- * @param shading The shading object from which to write the output
- */
- public ShadingPattern(Shading shading) {
- this.shading = shading;
- }
-
- /**
- * Outputs the given shading object to a String
- * @param colorSpace The Colospace (PDF and Postscript)
- * @param shadingType The shading type
- * @param background The background
- * @param bBox The bounding box
- * @param antiAlias Anti-aliasing
- * @return Returns the output string
- */
- public String toString(PDFDeviceColorSpace colorSpace, int shadingType, List background,
- List bBox, boolean antiAlias) {
- StringBuffer p = new StringBuffer(128);
- p.append("<<\n/ShadingType " + shadingType + " \n");
- if (colorSpace != null) {
- p.append("/ColorSpace /"
- + colorSpace.getName() + " \n");
- }
-
- if (background != null) {
- p.append("/Background [ ");
- for (int bgIndex = 0; bgIndex < background.size(); bgIndex++) {
- p.append(PDFNumber.doubleOut((Double)background.get(bgIndex))
- + " ");
- }
- p.append("] \n");
- }
-
- if (bBox
- != null) { // I've never seen an example, so I guess this is right.
- p.append("/BBox [ ");
- for (int bboxIndex = 0; bboxIndex < bBox.size(); bboxIndex++) {
- p.append(PDFNumber.doubleOut((Double)bBox.get(bboxIndex))
- + " ");
- }
- p.append("] \n");
- }
-
- if (antiAlias) {
- p.append("/AntiAlias " + antiAlias + " \n");
- }
-
- // Here's where we differentiate based on what type it is.
- switch (shadingType) {
- //Function based shading
- case 1: p = shading.handleShadingType1(p); break;
- //Axial shading
- case 2:
- //Radial shading
- case 3: p = shading.handleShadingType2or3(p); break;
- //Free-form Gouraud-shaded triangle meshes
- case 4:
- //Coons patch meshes
- case 6:
- //Tensor product patch meshes
- case 7: p = shading.handleShadingType4or6or7(p); break;
- //Lattice Free form gouraud-shaded triangle mesh
- case 5: p = shading.handleShadingType5(p); break;
- default: //Shading pattern outside expecting values
- break;
- }
-
- p.append(">>");
-
- return (p.toString());
- }
-}
diff --git a/src/java/org/apache/fop/svg/PDFGraphics2D.java b/src/java/org/apache/fop/svg/PDFGraphics2D.java
index 6344e37e6..c9ec79d0d 100644
--- a/src/java/org/apache/fop/svg/PDFGraphics2D.java
+++ b/src/java/org/apache/fop/svg/PDFGraphics2D.java
@@ -36,7 +36,6 @@ import java.awt.Stroke;
import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.geom.PathIterator;
-import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
@@ -50,6 +49,7 @@ import java.awt.image.renderable.RenderableImage;
import java.io.IOException;
import java.io.OutputStream;
import java.io.StringWriter;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -93,15 +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.GradientFactory;
-import org.apache.fop.render.shading.GradientRegistrar;
-import org.apache.fop.render.shading.PDFGradientFactory;
-import org.apache.fop.render.shading.Pattern;
-import org.apache.fop.render.shading.Shading;
/**
* <p>PDF Graphics 2D.
@@ -112,7 +110,7 @@ import org.apache.fop.render.shading.Shading;
*
* @see org.apache.batik.ext.awt.g2d.AbstractGraphics2D
*/
-public class PDFGraphics2D extends AbstractGraphics2D implements NativeImageHandler, GradientRegistrar {
+public class PDFGraphics2D extends AbstractGraphics2D implements NativeImageHandler {
private static final AffineTransform IDENTITY_TRANSFORM = new AffineTransform();
/** The number of decimal places. */
@@ -818,159 +816,18 @@ public class PDFGraphics2D extends AbstractGraphics2D implements NativeImageHand
new Color[] {gpaint.getColor1(), gpaint.getColor2()},
gpaint.isCyclic() ? LinearGradientPaint.REPEAT : LinearGradientPaint.NO_CYCLE);
}
- if (paint instanceof LinearGradientPaint) {
- LinearGradientPaint gp = (LinearGradientPaint)paint;
-
- // This code currently doesn't support 'repeat'.
- // For linear gradients it is possible to construct
- // a 'tile' that is repeated with a PDF pattern, but
- // it would be very tricky as you would have to rotate
- // the coordinate system so the repeat was axially
- // aligned. At this point I'm just going to rasterize it.
- MultipleGradientPaint.CycleMethodEnum cycle = gp.getCycleMethod();
- if (cycle != MultipleGradientPaint.NO_CYCLE) {
- return false;
- }
-
- Color[] cols = gp.getColors();
- float[] fractions = gp.getFractions();
-
- // Build proper transform from gradient space to page space
- // ('Patterns' don't get userspace transform).
- AffineTransform transform;
- transform = new AffineTransform(getBaseTransform());
- transform.concatenate(getTransform());
- transform.concatenate(gp.getTransform());
-
- List<Double> theMatrix = new java.util.ArrayList<Double>();
- double [] mat = new double[6];
- transform.getMatrix(mat);
- for (int idx = 0; idx < mat.length; idx++) {
- theMatrix.add(new Double(mat[idx]));
- }
-
- Point2D p1 = gp.getStartPoint();
- Point2D p2 = gp.getEndPoint();
- List<Double> theCoords = new java.util.ArrayList<Double>();
- theCoords.add(new Double(p1.getX()));
- theCoords.add(new Double(p1.getY()));
- theCoords.add(new Double(p2.getX()));
- theCoords.add(new Double(p2.getY()));
-
- List<Boolean> theExtend = new java.util.ArrayList<Boolean>();
- theExtend.add(Boolean.TRUE);
- theExtend.add(Boolean.TRUE);
-
- List<Double> theDomain = new java.util.ArrayList<Double>();
- theDomain.add(new Double(0));
- theDomain.add(new Double(1));
-
- List<Double> theEncode = new java.util.ArrayList<Double>();
- theEncode.add(new Double(0));
- theEncode.add(new Double(1));
- theEncode.add(new Double(0));
- theEncode.add(new Double(1));
-
- List<Double> theBounds = new java.util.ArrayList<Double>();
-
- List<Color> someColors = new java.util.ArrayList<Color>();
-
- for (int count = 0; count < cols.length; count++) {
- Color c1 = cols[count];
- if (c1.getAlpha() != 255) {
- return false; // PDF can't do alpha
- }
-
- //PDFColor color1 = new PDFColor(c1.getRed(), c1.getGreen(),
- // c1.getBlue());
- someColors.add(c1);
- if (count > 0 && count < cols.length - 1) {
- theBounds.add(new Double(fractions[count]));
- }
- }
-
- //Gradients are currently restricted to sRGB
- PDFDeviceColorSpace colSpace = new PDFDeviceColorSpace(PDFDeviceColorSpace.DEVICE_RGB);
- PDFGradientFactory gradientFactory = (PDFGradientFactory)GradientFactory.newInstance(this);
- PDFPattern myPat = gradientFactory.createGradient(false, colSpace, someColors, theBounds,
- theCoords, theMatrix);
- currentStream.write(myPat.getColorSpaceOut(fill));
-
+ if (paint instanceof LinearGradientPaint && gradientSupported((LinearGradientPaint) paint)) {
+ Pattern pattern = GradientMaker.makeLinearGradient((LinearGradientPaint) paint,
+ getBaseTransform(), getTransform());
+ PDFPattern pdfPattern = createPDFPattern(pattern);
+ currentStream.write(pdfPattern.getColorSpaceOut(fill));
return true;
}
- if (paint instanceof RadialGradientPaint) {
- RadialGradientPaint rgp = (RadialGradientPaint)paint;
-
- // There is essentially no way to support repeats
- // in PDF for radial gradients (the one option would
- // be to 'grow' the outer circle until it fully covered
- // the bounds and then grow the stops accordingly, the
- // problem is that this may require an extremely large
- // number of stops for cases where the focus is near
- // the edge of the outer circle). so we rasterize.
- MultipleGradientPaint.CycleMethodEnum cycle = rgp.getCycleMethod();
- if (cycle != MultipleGradientPaint.NO_CYCLE) {
- return false;
- }
-
- AffineTransform transform;
- transform = new AffineTransform(getBaseTransform());
- transform.concatenate(getTransform());
- transform.concatenate(rgp.getTransform());
-
- List<Double> theMatrix = new java.util.ArrayList<Double>();
- double [] mat = new double[6];
- transform.getMatrix(mat);
- for (int idx = 0; idx < mat.length; idx++) {
- theMatrix.add(new Double(mat[idx]));
- }
-
- double ar = rgp.getRadius();
- Point2D ac = rgp.getCenterPoint();
- Point2D af = rgp.getFocusPoint();
-
- List<Double> theCoords = new java.util.ArrayList<Double>();
- double dx = af.getX() - ac.getX();
- double dy = af.getY() - ac.getY();
- double d = Math.sqrt(dx * dx + dy * dy);
- if (d > ar) {
- // the center point af must be within the circle with
- // radius ar centered at ac so limit it to that.
- double scale = (ar * .9999) / d;
- dx = dx * scale;
- dy = dy * scale;
- }
-
- theCoords.add(new Double(ac.getX() + dx)); // Fx
- theCoords.add(new Double(ac.getY() + dy)); // Fy
- theCoords.add(new Double(0));
- theCoords.add(new Double(ac.getX()));
- theCoords.add(new Double(ac.getY()));
- theCoords.add(new Double(ar));
-
- Color[] cols = rgp.getColors();
- List<Color> someColors = new java.util.ArrayList<Color>();
- for (int count = 0; count < cols.length; count++) {
- Color cc = cols[count];
- if (cc.getAlpha() != 255) {
- return false; // PDF can't do alpha
- }
-
- someColors.add(cc);
- }
-
- float[] fractions = rgp.getFractions();
- List<Double> theBounds = new java.util.ArrayList<Double>();
- for (int count = 1; count < fractions.length - 1; count++) {
- float offset = fractions[count];
- theBounds.add(new Double(offset));
- }
- PDFDeviceColorSpace colSpace = new PDFDeviceColorSpace(PDFDeviceColorSpace.DEVICE_RGB);
- PDFGradientFactory gradientFactory = (PDFGradientFactory) GradientFactory.newInstance(this);
- PDFPattern myPat = gradientFactory.createGradient(true, colSpace, someColors, theBounds,
- theCoords, theMatrix);
- currentStream.write(myPat.getColorSpaceOut(fill));
-
+ if (paint instanceof RadialGradientPaint && gradientSupported((RadialGradientPaint) paint)) {
+ Pattern pattern = GradientMaker.makeRadialGradient((RadialGradientPaint) paint,
+ getBaseTransform(), getTransform());
+ PDFPattern pdfPattern = createPDFPattern(pattern);
+ currentStream.write(pdfPattern.getColorSpaceOut(fill));
return true;
}
if (paint instanceof PatternPaint) {
@@ -980,6 +837,47 @@ public class PDFGraphics2D extends AbstractGraphics2D implements NativeImageHand
return false; // unknown paint
}
+ private PDFPattern createPDFPattern(Pattern pattern) {
+ Shading shading = pattern.getShading();
+ Function function = shading.getFunction();
+ List<PDFFunction> pdfFunctions = new ArrayList<PDFFunction>(function.getFunctions().size());
+ for (Function f : function.getFunctions()) {
+ pdfFunctions.add(registerFunction(new PDFFunction(f)));
+ }
+ PDFFunction pdfFunction = registerFunction(new PDFFunction(function, pdfFunctions));
+ PDFShading pdfShading = new PDFShading(shading.getShadingType(), shading.getColorSpace(), shading.getCoords(),
+ pdfFunction);
+ pdfShading = registerShading(pdfShading);
+ PDFPattern pdfPattern = new PDFPattern(pattern.getPatternType(), pdfShading, null, null, pattern.getMatrix());
+ return registerPattern(pdfPattern);
+ }
+
+ private boolean gradientSupported(MultipleGradientPaint gradient) {
+ return !(gradientContainsTransparency(gradient) || gradientIsRepeated(gradient));
+ }
+
+ private boolean gradientContainsTransparency(MultipleGradientPaint gradient) {
+ for (Color color : gradient.getColors()) {
+ if (color.getAlpha() != 255) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean gradientIsRepeated(MultipleGradientPaint gradient) {
+ // For linear gradients it is possible to construct a 'tile' that is repeated with
+ // a PDF pattern, but it would be very tricky as the coordinate system would have
+ // to be rotated so the repeat is axially aligned.
+
+ // For radial gradients there is essentially no way to support repeats in PDF (the
+ // one option would be to 'grow' the outer circle until it fully covers the
+ // bounds and then grow the stops accordingly, the problem is that this may
+ // require an extremely large number of stops for cases where the focus is near
+ // the edge of the outer circle).
+ return (gradient.getCycleMethod() != MultipleGradientPaint.NO_CYCLE);
+ }
+
private boolean createPattern(PatternPaint pp, boolean fill) {
preparePainting();
@@ -1883,8 +1781,8 @@ public class PDFGraphics2D extends AbstractGraphics2D implements NativeImageHand
* @return Returns either the function which has already been registered
* or the current new registered object.
*/
- public Function registerFunction(Function function) {
- return pdfDoc.getFactory().registerFunction((PDFFunction)function);
+ public PDFFunction registerFunction(PDFFunction function) {
+ return pdfDoc.getFactory().registerFunction(function);
}
/**
@@ -1893,9 +1791,8 @@ public class PDFGraphics2D extends AbstractGraphics2D implements NativeImageHand
* @return Returs either the shading which has already been registered
* or the current new registered object
*/
- public Shading registerShading(Shading shading) {
- assert shading instanceof PDFShading;
- return pdfDoc.getFactory().registerShading(resourceContext, (PDFShading)shading);
+ public PDFShading registerShading(PDFShading shading) {
+ return pdfDoc.getFactory().registerShading(resourceContext, shading);
}
/**
@@ -1904,9 +1801,8 @@ public class PDFGraphics2D extends AbstractGraphics2D implements NativeImageHand
* @return Returns either the pattern which has already been registered
* or the current new registered object
*/
- public Pattern registerPattern(Pattern pattern) {
- assert pattern instanceof PDFPattern;
- return pdfDoc.getFactory().registerPattern(resourceContext, (PDFPattern)pattern);
+ public PDFPattern registerPattern(PDFPattern pattern) {
+ return pdfDoc.getFactory().registerPattern(resourceContext, pattern);
}
}