From b7b8ba98b4579c9925f6107170799253c65371da Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Fri, 11 Jul 2014 18:03:42 +0000 Subject: [PATCH] Factorized shading code that was common to PDF and PostScript git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/FOP-2393_gradient-rendering@1609759 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/pdf/PDFFactory.java | 34 -- src/java/org/apache/fop/pdf/PDFPattern.java | 8 +- src/java/org/apache/fop/pdf/PDFShading.java | 519 ++---------------- .../fop/render/pdf/svg/PDFGradientMaker.java | 17 +- .../fop/render/ps/svg/PSGradientMaker.java | 8 - .../apache/fop/render/ps/svg/PSPattern.java | 44 +- .../apache/fop/render/ps/svg/PSShading.java | 233 -------- .../fop/render/shading/GradientMaker.java | 7 +- .../apache/fop/render/shading/Shading.java | 193 ++++++- .../fop/render/shading/ShadingPattern.java | 175 +++++- 10 files changed, 470 insertions(+), 768 deletions(-) delete mode 100644 src/java/org/apache/fop/render/ps/svg/PSShading.java diff --git a/src/java/org/apache/fop/pdf/PDFFactory.java b/src/java/org/apache/fop/pdf/PDFFactory.java index d7d08ce25..adbe8a52e 100644 --- a/src/java/org/apache/fop/pdf/PDFFactory.java +++ b/src/java/org/apache/fop/pdf/PDFFactory.java @@ -377,40 +377,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); - } - /* ============= named destinations and the name dictionary ============ */ diff --git a/src/java/org/apache/fop/pdf/PDFPattern.java b/src/java/org/apache/fop/pdf/PDFPattern.java index df4b0233d..a449c8f60 100644 --- a/src/java/org/apache/fop/pdf/PDFPattern.java +++ b/src/java/org/apache/fop/pdf/PDFPattern.java @@ -24,7 +24,6 @@ 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. @@ -144,19 +143,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 09c46f846..a262f4d29 100644 --- a/src/java/org/apache/fop/pdf/PDFShading.java +++ b/src/java/org/apache/fop/pdf/PDFShading.java @@ -19,11 +19,13 @@ 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.shading.ShadingPattern.ShadingRenderer; + /** * class representing a PDF Smooth Shading object. @@ -35,7 +37,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 /** @@ -43,265 +45,23 @@ public class PDFShading extends PDFObject implements Shading { */ protected String shadingName = null; - /** - * 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 = null; - - /** - * The background color. Since shading is opaque, - * this is very rarely used. - */ - protected List background = null; - - /** - * Optional: A List specifying the clipping rectangle - */ - protected List bBox = null; - - /** - * Optional: A flag whether or not to filter the shading function - * to prevent aliasing artifacts. Default is false. - */ - protected boolean antiAlias = false; - - /** - * 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 = null; - - /** - * Optional for Type 1: A transformation matrix - */ - protected List matrix = null; - - /** - * 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 = null; + 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 = null; - - /** - * 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 = null; - - /** - * 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 = 0; - - /** - * 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 = 0; - - /** - * 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 = null; - - /** - * 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 = 0; - - /** - * 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 = 0; - - /** - * 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, PDFFunction 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; - this.function = 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; } /** @@ -338,8 +98,19 @@ 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); + final ShadingRenderer shadingRenderer = new ShadingRenderer() { + + public void outputFunction(StringBuffer out) { + Function function = shading.getFunction(); + if (function != null) { + out.append("/Function "); + out.append(pdfFunction.referencePDF() + " \n"); + } + } + }; + ShadingPattern pattern = new ShadingPattern(shading, shadingRenderer); + return pattern.toString(shading.getColorSpace(), shading.getShadingType(), shading.getBackground(), + shading.getBBox(), shading.isAntiAlias()); } /** {@inheritDoc} */ @@ -353,257 +124,89 @@ public class PDFShading extends PDFObject implements Shading { if (!(obj instanceof PDFShading)) { return false; } - PDFShading shad = (PDFShading)obj; - if (shadingType != shad.shadingType) { + Shading other = ((PDFShading) obj).shading; + if (shading.getShadingType() != other.getShadingType()) { return false; } - if (antiAlias != shad.antiAlias) { + if (shading.isAntiAlias() != other.isAntiAlias()) { return false; } - if (bitsPerCoordinate != shad.bitsPerCoordinate) { + if (shading.getBitsPerCoordinate() != other.getBitsPerCoordinate()) { return false; } - if (bitsPerFlag != shad.bitsPerFlag) { + if (shading.getBitsPerFlag() != other.getBitsPerFlag()) { return false; } - if (bitsPerComponent != shad.bitsPerComponent) { + if (shading.getBitsPerComponent() != other.getBitsPerComponent()) { return false; } - if (verticesPerRow != shad.verticesPerRow) { + if (shading.getVerticesPerRow() != other.getVerticesPerRow()) { return false; } - if (colorSpace != null) { - if (!colorSpace.equals(shad.colorSpace)) { + if (shading.getColorSpace() != null) { + if (!shading.getColorSpace().equals(other.getColorSpace())) { return false; } - } else if (shad.colorSpace != null) { + } else if (other.getColorSpace() != null) { return false; } - if (background != null) { - if (!background.equals(shad.background)) { + if (shading.getBackground() != null) { + if (!shading.getBackground().equals(other.getBackground())) { return false; } - } else if (shad.background != null) { + } else if (other.getBackground() != null) { return false; } - if (bBox != null) { - if (!bBox.equals(shad.bBox)) { + if (shading.getBBox() != null) { + if (!shading.getBBox().equals(other.getBBox())) { return false; } - } else if (shad.bBox != null) { + } else if (other.getBBox() != null) { return false; } - if (domain != null) { - if (!domain.equals(shad.domain)) { + if (shading.getDomain() != null) { + if (!shading.getDomain().equals(other.getDomain())) { return false; } - } else if (shad.domain != null) { + } else if (other.getDomain() != null) { return false; } - if (matrix != null) { - if (!matrix.equals(shad.matrix)) { + if (shading.getMatrix() != null) { + if (!shading.getMatrix().equals(other.getMatrix())) { return false; } - } else if (shad.matrix != null) { + } else if (other.getMatrix() != null) { return false; } - if (coords != null) { - if (!coords.equals(shad.coords)) { + if (shading.getCoords() != null) { + if (!shading.getCoords().equals(other.getCoords())) { return false; } - } else if (shad.coords != null) { + } else if (other.getCoords() != null) { return false; } - if (extend != null) { - if (!extend.equals(shad.extend)) { + if (shading.getExtend() != null) { + if (!shading.getExtend().equals(other.getExtend())) { return false; } - } else if (shad.extend != null) { + } else if (other.getExtend() != null) { return false; } - if (decode != null) { - if (!decode.equals(shad.decode)) { + if (shading.getDecode() != null) { + if (!shading.getDecode().equals(other.getDecode())) { return false; } - } else if (shad.decode != null) { + } else if (other.getDecode() != null) { return false; } - if (function != null) { - if (!function.equals(shad.function)) { + if (shading.getFunction() != null) { + if (!shading.getFunction().equals(other.getFunction())) { 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/pdf/svg/PDFGradientMaker.java b/src/java/org/apache/fop/render/pdf/svg/PDFGradientMaker.java index dca2801a2..f34a61d19 100644 --- a/src/java/org/apache/fop/render/pdf/svg/PDFGradientMaker.java +++ b/src/java/org/apache/fop/render/pdf/svg/PDFGradientMaker.java @@ -20,7 +20,6 @@ package org.apache.fop.render.pdf.svg; import java.util.ArrayList; 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; @@ -38,21 +37,17 @@ public class PDFGradientMaker extends GradientMaker { } @Override - protected Shading makeShading(int shadingType, PDFDeviceColorSpace colorSpace, - List coords, Function function) { + protected PDFPattern makePattern(int patternType, Shading shading, List matrix) { + Function function = shading.getFunction(); List pdfFunctions = new ArrayList(function.getFunctions().size()); for (Function f : function.getFunctions()) { pdfFunctions.add(graphics2D.registerFunction(new PDFFunction(f))); } PDFFunction pdfFunction = graphics2D.registerFunction(new PDFFunction(function, pdfFunctions)); - PDFShading shading = new PDFShading(shadingType, colorSpace, null, null, false, - coords, null, pdfFunction, null); - return graphics2D.registerShading(shading); - } - - @Override - protected PDFPattern makePattern(int patternType, Shading shading, List matrix) { - PDFPattern pattern = new PDFPattern(patternType, shading, null, null, matrix); + PDFShading pdfShading = new PDFShading(shading.getShadingType(), shading.getColorSpace(), shading.getCoords(), + pdfFunction); + pdfShading = graphics2D.registerShading(pdfShading); + PDFPattern pattern = new PDFPattern(patternType, pdfShading, null, null, matrix); return graphics2D.registerPattern(pattern); } diff --git a/src/java/org/apache/fop/render/ps/svg/PSGradientMaker.java b/src/java/org/apache/fop/render/ps/svg/PSGradientMaker.java index c66cd8c24..5c75fdbed 100644 --- a/src/java/org/apache/fop/render/ps/svg/PSGradientMaker.java +++ b/src/java/org/apache/fop/render/ps/svg/PSGradientMaker.java @@ -19,19 +19,11 @@ package org.apache.fop.render.ps.svg; import java.util.List; -import org.apache.fop.pdf.PDFDeviceColorSpace; -import org.apache.fop.render.shading.Function; import org.apache.fop.render.shading.GradientMaker; import org.apache.fop.render.shading.Shading; public class PSGradientMaker extends GradientMaker { - @Override - protected Shading makeShading(int shadingType, - PDFDeviceColorSpace colorSpace, List coords, Function function) { - return new PSShading(shadingType, colorSpace, null, null, false, coords, null, function, null); - } - @Override protected PSPattern makePattern(int patternType, Shading shading, List matrix) { return new PSPattern(patternType, shading, null, null, matrix); diff --git a/src/java/org/apache/fop/render/ps/svg/PSPattern.java b/src/java/org/apache/fop/render/ps/svg/PSPattern.java index d29c84674..3418a5740 100644 --- a/src/java/org/apache/fop/render/ps/svg/PSPattern.java +++ b/src/java/org/apache/fop/render/ps/svg/PSPattern.java @@ -19,10 +19,15 @@ package org.apache.fop.render.ps.svg; +import java.util.ArrayList; import java.util.List; +import org.apache.fop.render.shading.Function; +import org.apache.fop.render.shading.FunctionPattern; import org.apache.fop.render.shading.Pattern; import org.apache.fop.render.shading.Shading; +import org.apache.fop.render.shading.ShadingPattern; +import org.apache.fop.render.shading.ShadingPattern.ShadingRenderer; public class PSPattern implements Pattern { @@ -34,7 +39,7 @@ public class PSPattern implements Pattern { /** * The Shading object comprising the Type 2 pattern */ - protected PSShading shading = null; + protected Shading shading; /** * List of Integers represetning the Extended unique Identifier @@ -61,8 +66,7 @@ public class PSPattern implements Pattern { public PSPattern(int thePatternType, Shading theShading, List theXUID, StringBuffer theExtGState, List matrix) { this.patternType = 2; // thePatternType; - assert theShading instanceof PSShading; - this.shading = (PSShading)theShading; + this.shading = theShading; this.xUID = theXUID; this.extGState = theExtGState; // always null this.matrix = matrix; @@ -82,7 +86,9 @@ public class PSPattern implements Pattern { p.append("/PatternType " + this.patternType + " \n"); if (this.shading != null) { - p.append("/Shading " + this.shading.toString() + " \n"); + p.append("/Shading "); + outputShading(p); + p.append(" \n"); } if (this.xUID != null) { @@ -109,4 +115,34 @@ public class PSPattern implements Pattern { return p.toString(); } + + private void outputShading(StringBuffer out) { + final Function function = shading.getFunction(); + final ShadingRenderer shadingRenderer = new ShadingRenderer() { + + public void outputFunction(StringBuffer out) { + out.append("/Function "); + FunctionPattern pattern = new FunctionPattern(function); + List functionsStrings = new ArrayList(function.getFunctions().size()); + for (Function f : function.getFunctions()) { + functionsStrings.add(functionToString(f)); + } + out.append(pattern.toWriteableString(functionsStrings)); + out.append("\n"); + } + }; + ShadingPattern pattern = new ShadingPattern(shading, shadingRenderer); + out.append(pattern.toString(shading.getColorSpace(), shading.getShadingType(), shading.getBackground(), + shading.getBBox(), shading.isAntiAlias())); + } + + private String functionToString(Function function) { + FunctionPattern pattern = new FunctionPattern(function); + List functionsStrings = new ArrayList(function.getFunctions().size()); + for (Function f : function.getFunctions()) { + functionsStrings.add(functionToString(f)); + } + return pattern.toWriteableString(functionsStrings); + } + } 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 68be4fcd8..000000000 --- a/src/java/org/apache/fop/render/ps/svg/PSShading.java +++ /dev/null @@ -1,233 +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.ArrayList; -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.FunctionPattern; -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 = null; - - /** - * The background color. Since shading is opaque, - * this is very rarely used. - */ - protected List background = null; - - /** - * Optional: A List specifying the clipping rectangle - */ - protected List bBox = null; - - /** - * Optional: A flag whether or not to filter the shading function - * to prevent aliasing artifacts. Default is false. - */ - protected boolean antiAlias = false; - - /** - * 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 = null; - - /** - * 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 Function 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 = null; - - /** - * 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 = null; - - /** - * 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 theBackground, List theBBox, - boolean theAntiAlias, List theCoords, - List theDomain, Function theFunction, - List 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; - this.function = 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 "); - p.append(functionToString(function) + " \n"); - } - return p; - } - - private String functionToString(Function function) { - FunctionPattern pattern = new FunctionPattern(function); - List functionsStrings = new ArrayList(function.getFunctions().size()); - for (Function f : function.getFunctions()) { - functionsStrings.add(functionToString(f)); - } - return pattern.toWriteableString(functionsStrings); - } - - /** - * 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/GradientMaker.java b/src/java/org/apache/fop/render/shading/GradientMaker.java index 62eab6a48..99afe1f08 100644 --- a/src/java/org/apache/fop/render/shading/GradientMaker.java +++ b/src/java/org/apache/fop/render/shading/GradientMaker.java @@ -80,8 +80,8 @@ public abstract class GradientMaker

{ // Gradients are currently restricted to sRGB PDFDeviceColorSpace colorSpace = new PDFDeviceColorSpace(PDFDeviceColorSpace.DEVICE_RGB); Function function = new Function(3, null, null, functions, bounds, null); - Shading shading = makeShading(gradient instanceof LinearGradientPaint ? 2 : 3, colorSpace, - coords, function); + int shadingType = gradient instanceof LinearGradientPaint ? 2 : 3; + Shading shading = new Shading(shadingType, colorSpace, coords, function); return makePattern(2, shading, matrix); } @@ -149,9 +149,6 @@ public abstract class GradientMaker

{ return gradientColors; } - protected abstract Shading makeShading(int shadingType, PDFDeviceColorSpace colorSpace, - List coords, Function function); - protected abstract P makePattern(int patternType, Shading shading, List matrix); } diff --git a/src/java/org/apache/fop/render/shading/Shading.java b/src/java/org/apache/fop/render/shading/Shading.java index 385cb112b..e27b61a7d 100644 --- a/src/java/org/apache/fop/render/shading/Shading.java +++ b/src/java/org/apache/fop/render/shading/Shading.java @@ -17,10 +17,193 @@ package org.apache.fop.render.shading; +import java.util.List; + +import org.apache.fop.pdf.PDFDeviceColorSpace; + + +public class Shading { + + /** + * Required: The Type of shading (1,2,3,4,5,6,7) + */ + private final int shadingType; + + /** + * A ColorSpace representing the colorspace. "DeviceRGB" is an example. + */ + private final PDFDeviceColorSpace colorSpace; + + /** + * Required for Type 2: An Array of four numbers specifying + * the starting and ending coordinate pairs + * Required for Type 3: An Array of six numbers [x0,y0,r0,x1,y1,r1] + * specifying the centers and radii of + * the starting and ending circles. + */ + private final List coords; + + /** + * Required for Type 1, 2, and 3: + * The object of the color mapping function (usually type 2 or 3). + * Optional for Type 4,5,6, and 7: When it's nearly the same thing. + */ + private final Function function; + + /** + * Optional: A List specifying the clipping rectangle + */ + private final List bbox; + + /** + * Optional for Type 1: A transformation matrix + */ + private final List matrix; + + /** + * The background color. Since shading is opaque, + * this is very rarely used. + */ + private final List background; + + /** + * Optional for Type 1: Array of four numbers, xmin, xmax, ymin, ymax. + * Default is [0 1 0 1] + * Optional for Type 2: An array of two numbers between which the blend + * varies between start and end points. Default is 0, 1. + * Optional for Type 3: An array of two numbers between which the blend + * varies between start and end points. Default is 0, 1. + */ + private final List domain; + + /** + * Required for Type 4,5,6, and 7: Array of Doubles which specifies + * how to decode coordinate and color component values. + * Each type has a differing number of decode array members, so check + * the spec. + * Page 303 in PDF Spec 1.3 + */ + private final List decode; + + /** + * Required for Type 2+3: An Array of two boolean values specifying + * whether to extend the start and end colors past the start + * and end points, respectively. + * Default is false, false. + */ + private final List extend; + + /** + * Required for Type 4,5,6, and 7: Specifies the number of bits used + * to represent each vertex coordinate. + * Allowed to be 1,2,4,8,12,16,24, or 32. + */ + private final int bitsPerCoordinate; + + /** + * Required for Type 4,5,6, and 7: Specifies the number of bits used + * to represent the edge flag for each vertex. + * Allowed to be 2,4,or 8, while the Edge flag itself is allowed to + * be 0,1 or 2. + */ + private final int bitsPerFlag; + + /** + * Optional: A flag whether or not to filter the shading function + * to prevent aliasing artifacts. Default is false. + */ + private final boolean antiAlias; + + /** + * Required for Type 4,5,6, and 7: Specifies the number of bits used + * to represent each color coordinate. + * Allowed to be 1,2,4,8,12, or 16 + */ + private final int bitsPerComponent; + + /** + * Required for Type 5:The number of vertices in each "row" of + * the lattice; it must be greater than or equal to 2. + */ + private final int verticesPerRow; + + public Shading(int shadingType, PDFDeviceColorSpace colorSpace, + List coords, Function function) { + this.shadingType = shadingType; + this.colorSpace = colorSpace; + this.background = null; + this.bbox = null; + this.antiAlias = false; + this.coords = coords; + this.domain = null; + this.function = function; + this.extend = null; + this.matrix = null; + this.decode = null; + this.bitsPerCoordinate = 0; + this.bitsPerFlag = 0; + this.bitsPerComponent = 0; + this.verticesPerRow = 0; + } + + public int getShadingType() { + return shadingType; + } + + public PDFDeviceColorSpace getColorSpace() { + return colorSpace; + } + + public List getCoords() { + return coords; + } + + public Function getFunction() { + return function; + } + + public List getBBox() { + return bbox; + } + + public List getMatrix() { + return matrix; + } + + public List getBackground() { + return background; + } + + public List getDomain() { + return domain; + } + + public List getDecode() { + return decode; + } + + public List getExtend() { + return extend; + } + + public int getBitsPerCoordinate() { + return bitsPerCoordinate; + } + + public int getBitsPerFlag() { + return bitsPerFlag; + } + + public boolean isAntiAlias() { + return antiAlias; + } + + public int getBitsPerComponent() { + return bitsPerComponent; + } + + public int getVerticesPerRow() { + return verticesPerRow; + } -public 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 index 6dac65f55..43e030bc8 100644 --- a/src/java/org/apache/fop/render/shading/ShadingPattern.java +++ b/src/java/org/apache/fop/render/shading/ShadingPattern.java @@ -27,14 +27,22 @@ import org.apache.fop.pdf.PDFNumber; */ public class ShadingPattern { + public interface ShadingRenderer { + + void outputFunction(StringBuffer out); + } + private Shading shading; + private final ShadingRenderer shadingRenderer; + /** * Constructor * @param shading The shading object from which to write the output */ - public ShadingPattern(Shading shading) { + public ShadingPattern(Shading shading, ShadingRenderer shadingRenderer) { this.shading = shading; + this.shadingRenderer = shadingRenderer; } /** @@ -81,19 +89,19 @@ public class ShadingPattern { // Here's where we differentiate based on what type it is. switch (shadingType) { //Function based shading - case 1: p = shading.handleShadingType1(p); break; + case 1: p = handleShadingType1(p); break; //Axial shading case 2: //Radial shading - case 3: p = shading.handleShadingType2or3(p); break; + case 3: p = 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; + case 7: p = handleShadingType4or6or7(p); break; //Lattice Free form gouraud-shaded triangle mesh - case 5: p = shading.handleShadingType5(p); break; + case 5: p = handleShadingType5(p); break; default: //Shading pattern outside expecting values break; } @@ -102,4 +110,161 @@ public class ShadingPattern { return (p.toString()); } + + + /** + * 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 (shading.getDomain() != null) { + p.append("/Domain [ "); + for (int domainIndex = 0; domainIndex < shading.getDomain().size(); domainIndex++) { + p.append(PDFNumber.doubleOut((Double)shading.getDomain().get(domainIndex)) + + " "); + } + p.append("] \n"); + } else { + p.append("/Domain [ 0 1 ] \n"); + } + + if (shading.getMatrix() != null) { + p.append("/Matrix [ "); + for (int matrixIndex = 0; matrixIndex < shading.getMatrix().size(); matrixIndex++) { + p.append(PDFNumber.doubleOut((Double)shading.getMatrix().get(matrixIndex)) + + " "); + } + p.append("] \n"); + } + shadingRenderer.outputFunction(p); + 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 (shading.getCoords() != null) { + p.append("/Coords [ "); + for (int coordIndex = 0; coordIndex < shading.getCoords().size(); coordIndex++) { + p.append(PDFNumber.doubleOut((Double)shading.getCoords().get(coordIndex)) + + " "); + } + p.append("] \n"); + } + + // DOMAIN + if (shading.getDomain() != null) { + p.append("/Domain [ "); + for (int domainIndex = 0; domainIndex < shading.getDomain().size(); domainIndex++) { + p.append(PDFNumber.doubleOut((Double)shading.getDomain().get(domainIndex)) + + " "); + } + p.append("] \n"); + } else { + p.append("/Domain [ 0 1 ] \n"); + } + + if (shading.getExtend() != null) { + p.append("/Extend [ "); + for (int extendIndex = 0; extendIndex < shading.getExtend().size(); extendIndex++) { + p.append((shading.getExtend().get(extendIndex)) + " "); + } + + p.append("] \n"); + } else { + p.append("/Extend [ true true ] \n"); + } + + shadingRenderer.outputFunction(p); + + 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 (shading.getBitsPerCoordinate() > 0) { + p.append("/BitsPerCoordinate " + shading.getBitsPerCoordinate() + + " \n"); + } else { + p.append("/BitsPerCoordinate 1 \n"); + } + + if (shading.getBitsPerComponent() > 0) { + p.append("/BitsPerComponent " + shading.getBitsPerComponent() + + " \n"); + } else { + p.append("/BitsPerComponent 1 \n"); + } + + if (shading.getBitsPerFlag() > 0) { + p.append("/BitsPerFlag " + shading.getBitsPerFlag() + " \n"); + } else { + p.append("/BitsPerFlag 2 \n"); + } + + if (shading.getDecode() != null) { + p.append("/Decode [ "); + for (int decodeIndex = 0; decodeIndex < shading.getDecode().size(); decodeIndex++) { + p.append((shading.getDecode().get(decodeIndex)) + " "); + } + + p.append("] \n"); + } + + shadingRenderer.outputFunction(p); + + 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 (shading.getBitsPerCoordinate() > 0) { + p.append("/BitsPerCoordinate " + shading.getBitsPerCoordinate() + + " \n"); + } else { + p.append("/BitsPerCoordinate 1 \n"); + } + + if (shading.getBitsPerComponent() > 0) { + p.append("/BitsPerComponent " + shading.getBitsPerComponent() + + " \n"); + } else { + p.append("/BitsPerComponent 1 \n"); + } + + if (shading.getDecode() != null) { + p.append("/Decode [ "); + for (int decodeIndex = 0; decodeIndex < shading.getDecode().size(); decodeIndex++) { + p.append((shading.getDecode().get(decodeIndex)) + " "); + } + + p.append("] \n"); + } + + shadingRenderer.outputFunction(p); + + if (shading.getVerticesPerRow() > 0) { + p.append("/VerticesPerRow " + shading.getVerticesPerRow() + " \n"); + } else { + p.append("/VerticesPerRow 2 \n"); + } + + return p; + } + } -- 2.39.5