From: arved Date: Tue, 21 Mar 2000 10:50:51 +0000 (+0000) Subject: NEW: Adds smooth shading X-Git-Tag: pre-columns~558 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=6fd1fb1c41e7b2c33d498ab66186afbb1fc5c9d2;p=xmlgraphics-fop.git NEW: Adds smooth shading git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@193306 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/org/apache/fop/pdf/PDFShading.java b/src/org/apache/fop/pdf/PDFShading.java new file mode 100644 index 000000000..27fa6402c --- /dev/null +++ b/src/org/apache/fop/pdf/PDFShading.java @@ -0,0 +1,631 @@ +/*-- $Id$ -- + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Fop" and "Apache Software Foundation" must not be used to + endorse or promote products derived from this software without prior + written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation and was originally created by + James Tauber . For more information on the Apache + Software Foundation, please see . + + */ + +package org.apache.fop.pdf; + +//Java... +import java.util.Vector; + +/** + * class representing a PDF Smooth Shading object. + * + * PDF Functions represent parameterized mathematical formulas and sampled representations with + * arbitrary resolution. Functions are used in two areas: device-dependent + * rasterization information for halftoning and transfer + * functions, and color specification for smooth shading (a PDF 1.3 feature). + * + * All PDF Functions have a shadingType (0,2,3, or 4), a Domain, and a Range. + */ +public class PDFShading extends PDFObject { + //Guts common to all function types + /** The name of the Shading e.g. "Shading1" */ + protected String shadingName = null; + + /** + * Required: The Type of shading (1,2,3,4,5,6,7) + */ + protected int shadingType = 3; //Default + + /** + * A String representing the colorspace. "DeviceRGB" is an example. + */ + protected StringBuffer colorSpace = null; + + /** + * The background color. Since shading is opaque, + * this is very rarely used. + */ + protected Vector background = null; + /** + * Optional: A Vector specifying the clipping rectangle + */ + protected Vector 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 Vector domain = null; + + /** Optional for Type 1: A transformation matrix */ + protected Vector 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; + + /** 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 Vector 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 Vector 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 Vector 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 theNumber The object number of this PDF object + * @param theShadingName The name of the shading pattern. Can be anything + * without spaces. "Shading1" or "Sh1" are good examples. + * @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 Vector 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 Vector 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 theNumber, String theShadingName, int theShadingType, StringBuffer theColorSpace, + Vector theBackground, Vector theBBox, boolean theAntiAlias, + Vector theDomain, Vector theMatrix, PDFFunction theFunction) + { + super(theNumber); + this.shadingName = theShadingName; + 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; + + } + + /** + * Constructor for Type 2 and 3 + * + * @param theNumber The object number of this PDF object. + * @param theShadingName The name of the shading pattern. Can be anything + * without spaces. "Shading1" or "Sh1" are good examples. + * @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 Vector 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 Vector of four (type 2) or 6 (type 3) Double + * @param theDomain Vector of Doubles specifying the domain + * @param theFunction the Stitching (PDFfunction type 3) function, even if it's stitching a single function + * @param theExtend Vector of Booleans of whether to extend teh start and end colors past the start and end points + * The default is [false, false] + */ + public PDFShading(int theNumber, String theShadingName, int theShadingType, StringBuffer theColorSpace, + Vector theBackground, Vector theBBox, boolean theAntiAlias, + Vector theCoords, Vector theDomain, PDFFunction theFunction, + Vector theExtend) + { + super(theNumber); + this.shadingName = theShadingName; + 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 theNumber The object number of this PDF object. + * @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 theShadingName The name of the shading pattern. Can be anything + * 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 Vector 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 Vector of Doubles see PDF 1.3 spec pages 303 to 312. + * @param theFunction the PDFFunction + */ + public PDFShading(int theNumber, String theShadingName, int theShadingType, StringBuffer theColorSpace, + Vector theBackground, Vector theBBox, boolean theAntiAlias, + int theBitsPerCoordinate, int theBitsPerComponent, + int theBitsPerFlag, Vector theDecode, PDFFunction theFunction) + { + super(theNumber); + + 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 theShadingName The name of the shading pattern. Can be anything + * 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 Vector 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 Vector 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 + * @param theNumber the object number of this PDF object. + */ + public PDFShading(int theNumber, String theShadingName, int theShadingType, StringBuffer theColorSpace, + Vector theBackground, Vector theBBox, boolean theAntiAlias, + int theBitsPerCoordinate, int theBitsPerComponent, + Vector theDecode, int theVerticesPerRow, PDFFunction theFunction) + { + super(theNumber); + this.shadingName = theShadingName; + 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 String getName() { + return (this.shadingName); + } + public String doubleOut(Double doubleDown) + { + StringBuffer p = new StringBuffer(); + double trouble = doubleDown.doubleValue() % 1; + if(trouble > 0.950) + { + p.append(doubleDown.intValue()+1); + } + else if (trouble < 0.050) + { + p.append(doubleDown.intValue()); + } + else + { + String doubleString = new String(doubleDown+""); + int decimal = doubleString.indexOf("."); + p.append(doubleString.substring(0, decimal)); + + if ((doubleString.length() - decimal) > 6) + { + p.append(doubleString.substring(decimal,decimal+6)); + } + else + { + p.append(doubleString.substring(decimal)); + } + } + return(p.toString()); + } + + /** + * represent as PDF. 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 PDF that was requested + * by the construction is dutifully output. + * This policy should be reviewed. + * + * @return the PDF string. + */ + public String toPDF() { + int vectorSize; + int tempInt; + StringBuffer p = new StringBuffer(); + p.append(this.number + " " + this.generation + + " obj\n<< \n/ShadingType "+this.shadingType+" \n"); + if(this.colorSpace != null) + { + p.append("/ColorSpace /"+this.colorSpace+" \n"); + } + + if(this.background != null) + { + p.append("/Background [ "); + vectorSize = this.background.size(); + for(tempInt=0; tempInt < vectorSize; tempInt++) + { + p.append(this.doubleOut( + (Double)this.background.elementAt(tempInt)) +" "); + } + p.append("] \n"); + } + + if(this.bBox != null) + {//I've never seen an example, so I guess this is right. + p.append("/BBox [ "); + vectorSize = this.bBox.size(); + for(tempInt=0; tempInt < vectorSize; tempInt++) + { + p.append(this.doubleOut( + (Double)this.bBox.elementAt(tempInt)) +" "); + } + p.append("] \n"); + } + + if(this.antiAlias) + { + p.append("/AntiAlias "+this.antiAlias+" \n"); + } + + //Here's where we differentiate based on what type it is. + if(this.shadingType == 1) + {//function based shading + if(this.domain != null) + { + p.append("/Domain [ "); + vectorSize = this.domain.size(); + for(tempInt=0; tempInt < vectorSize; tempInt++) + { + p.append(this.doubleOut( + (Double)this.domain.elementAt(tempInt)) +" "); + } + p.append("] \n"); + } + + if(this.matrix != null) + { + p.append("/Matrix [ "); + vectorSize = this.matrix.size(); + for(tempInt=0; tempInt < vectorSize; tempInt++) + { + p.append(this.doubleOut( + (Double)this.matrix.elementAt(tempInt)) +" "); + } + p.append("] \n"); + } + + if(this.function != null) + { + p.append("/Function "); + p.append(this.function.referencePDF()+" \n"); + } + } + else if((this.shadingType == 2) + || (this.shadingType == 3)) + {//2 is axial shading (linear gradient) + //3 is radial shading (circular gradient) + if(this.coords != null) + { + p.append("/Coords [ "); + vectorSize = this.coords.size(); + for(tempInt=0; tempInt < vectorSize; tempInt++) + { + p.append(this.doubleOut( + (Double)this.coords.elementAt(tempInt)) +" "); + } + p.append("] \n"); + } + + if(this.domain != null) + { + p.append("/Domain [ "); + vectorSize = this.domain.size(); + for(tempInt=0; tempInt < vectorSize; tempInt++) + { + p.append(this.doubleOut( + (Double)this.domain.elementAt(tempInt)) +" "); + } + p.append("] \n"); + } + + if(this.extend != null) + { + p.append("/Extend [ "); + vectorSize = this.extend.size(); + for(tempInt=0; tempInt < vectorSize; tempInt++) + { + p.append(((Boolean)this.extend.elementAt(tempInt)) +" "); + } + + p.append("] \n"); + } + + + if(this.function != null) + { + p.append("/Function "); + p.append(this.function.referencePDF()+" \n"); + } + else if(true) + { + + //FunctionType 2 /Domain [ 0 1 ] /N 1.048 /C0 [ 0.929 0.357 1 0.298 ] /C1 [ 0.631 0.278 1 0.027 ] >> \n" + //+"<< /FunctionType 2 /Domain [ 0 1 ] /N 1.374 /C0 [ 0.929 0.357 1 0.298 ] /C1 [ 0.941 0.4 1 0.102 ] + + p.append("/Function << /FunctionType 3 /Domain [ 0 1 ] /Functions [ << /FunctionType 2 /Domain [ 0 1 ] /C0 [ 0 0 0 0 ] /C1 [ 0.506 0.306 0 0 ] /N 1 >> ] /Encode [ 0 1 ] /Bounds [ ] >> \n"); + } + else if(true) + {//RGB function + p.append("/Function << /FunctionType 3 /Domain [ 0 1 ] /Encode [ 1 0 1 0 ] /Functions [ << /FunctionType 2 /Domain [ 0 1 ] /N 1.49834 /C0 [ 0 0.73332 0.98038 ] \n" ++"/C1 [ 0 0.38039 0.50587 ] >> \n" ++"<< /FunctionType 2 /Domain [ 0 1 ] /N 1 /C0 [ 0.37254 0.8196 0.96861 ] \n" ++"/C1 [ 0 0.73332 0.98038 ] >> \n" ++"] \n" ++"/Bounds [ 0.61581 ] >> "); + + } + else + { + + p.append("/Function << /FunctionType 3 /Domain [ 0 1 ] /Encode [ 1 0 ] /Functions [ << /FunctionType 2 /Domain [ 0 1 ] /N 1 /C0 [ 0.81175 0 0 ] /C1 [ 1 1 1 ] >> \n" + +"] \n" + +"/Bounds [ ] >> \n"); + } + + + + + } + + else if ((this.shadingType == 4) || + (this.shadingType == 6) || + (this.shadingType == 7)) + {//4:Free-form Gouraud-shaded triangle meshes + // 6:coons patch meshes + // 7://tensor product patch meshes (which no one ever uses) + if(this.bitsPerCoordinate > 0) + { + p.append("/BitsPerCoordinate "+this.bitsPerCoordinate+" \n"); + } + else + { + p.append("/BitsPerCoordinate 1 \n"); + } + + if(this.bitsPerComponent > 0) + { + p.append("/BitsPerComponent "+this.bitsPerComponent+" \n"); + } + else + { + p.append("/BitsPerComponent 1 \n"); + } + + if(this.bitsPerFlag > 0) + { + p.append("/BitsPerFlag "+this.bitsPerFlag+" \n"); + } + else + { + p.append("/BitsPerFlag 2 \n"); + } + + if(this.decode != null) + { + p.append("/Decode [ "); + vectorSize = this.decode.size(); + for(tempInt=0; tempInt < vectorSize; tempInt++) + { + p.append(((Boolean)this.decode.elementAt(tempInt)) +" "); + } + + p.append("] \n"); + } + + if(this.function != null) + { + p.append("/Function "); + p.append(this.function.referencePDF()+" \n"); + } + + } + + else if (this.shadingType == 5) + { //Lattice Free form gouraud-shaded triangle mesh + + if(this.bitsPerCoordinate > 0) + { + p.append("/BitsPerCoordinate "+this.bitsPerCoordinate+" \n"); + } + else + { + p.append("/BitsPerCoordinate 1 \n"); + } + + if(this.bitsPerComponent > 0) + { + p.append("/BitsPerComponent "+this.bitsPerComponent+" \n"); + } + else + { + p.append("/BitsPerComponent 1 \n"); + } + + if(this.decode != null) + { + p.append("/Decode [ "); + vectorSize = this.decode.size(); + for(tempInt=0; tempInt < vectorSize; tempInt++) + { + p.append(((Boolean)this.decode.elementAt(tempInt)) +" "); + } + + p.append("] \n"); + } + + if(this.function != null) + { + p.append("/Function "); + p.append(this.function.referencePDF()+" \n"); + } + + if(this.verticesPerRow > 0) + { + p.append("/VerticesPerRow "+this.verticesPerRow+" \n"); + } + else + { + p.append("/VerticesPerRow 2 \n"); + } + + } + + p.append(">> \nendobj\n"); + + return(p.toString()); + } +}