001: /*
002: * $Id: PDFShader.java,v 1.3 2007/12/20 18:33:29 rbair Exp $
003: *
004: * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
005: * Santa Clara, California 95054, U.S.A. All rights reserved.
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this library; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
020: */
021:
022: package com.sun.pdfview.pattern;
023:
024: import java.awt.geom.Rectangle2D;
025: import java.io.IOException;
026: import java.util.Map;
027:
028: import com.sun.pdfview.PDFObject;
029: import com.sun.pdfview.PDFPaint;
030: import com.sun.pdfview.PDFParseException;
031: import com.sun.pdfview.colorspace.PDFColorSpace;
032:
033: /**
034: * <p>A PDFShader fills a given region with a shading, such as a gradient.</p>
035: *
036: * <p>
037: * Shading Dictionaries (section 4.6)<br>
038: * A shading dictionary specifies details of a particular gradient fill,
039: * including the type of shading to be used, the geometry of the area to
040: * be shaded, and the geometry of the gradient fill. Various shading types
041: * are available, depending on the value of the dictionary’s ShadingType entry:
042: *
043: * <li>Function-based shadings (type 1) define the color of every point in the
044: * domain using a mathematical function (not necessarily smooth or continuous).</li>
045: *
046: * <li>Axial shadings (type 2) define a color blend along a line between two
047: * points, optionally extended beyond the boundary points by continuing
048: * the boundary colors.</li>
049: *
050: * <li>Radial shadings (type 3) define a blend between two circles,
051: * optionally extended beyond the boundary circles by continuing the
052: * boundary colors. This type of shading is commonly used to represent
053: * three-dimensional spheres and cones.</li>
054: *
055: * <li>Free-form Gouraud-shaded triangle meshes (type 4) define a
056: * common construct used by many three-dimensional applications to
057: * represent complex colored and shaded shapes. Vertices are specified
058: * in free-form geometry.</li>
059: *
060: * <li>Lattice-form Gouraud-shaded triangle meshes (type 5) are based on
061: * the same geometrical construct as type 4 but with vertices specified
062: * as a pseudorectangular lattice.</li>
063: *
064: * <li>Coons patch meshes (type 6) construct a shading from one or more
065: * color patches, each bounded by four cubic Bézier curves.</li>
066: *
067: * <li>Tensor-product patch meshes (type 7) are similar to type 6 but
068: * with additional control points in each patch, affording greater
069: * control over color mapping.</li>
070: *
071: * Table 4.28 shows the entries that all shading dictionaries share
072: * in common; entries specific to particular shading types are
073: * described in the relevant sections below.</p>
074: */
075: public abstract class PDFShader {
076:
077: public final static int FUNCTION_SHADING = 1;
078: public final static int AXIAL_SHADING = 2;
079: public final static int RADIAL_SHADING = 3;
080: public final static int FREE_FORM_SHADING = 4;
081: public final static int LATTICE_SHADING = 5;
082: public final static int COONS_PATCH_MESH_SHADING = 6;
083: public final static int TENSOR_PRODUCTS_MESH_SHADING = 7;
084:
085: /** the type of the shading (1 through 7)*/
086: private int type;
087:
088: /** the colorspace */
089: private PDFColorSpace colorSpace;
090:
091: /** the background color */
092: private PDFPaint background;
093:
094: /** the bounding box of the pattern */
095: private Rectangle2D bbox;
096:
097: /** Creates a new instance of PDFShader */
098: protected PDFShader(int type) {
099: this .type = type;
100: }
101:
102: /**
103: * Parse a pdf shader into a shader object
104: */
105: public static PDFShader getShader(PDFObject shaderObj, Map resources)
106: throws IOException {
107: // first see if the shader is already cached
108: PDFShader shader = (PDFShader) shaderObj.getCache();
109: if (shader != null) {
110: return shader;
111: }
112:
113: // read the type (required)
114: PDFObject typeObj = shaderObj.getDictRef("ShadingType");
115: if (typeObj == null) {
116: throw new PDFParseException("No shader type defined!");
117: }
118: int type = typeObj.getIntValue();
119:
120: // create the shader
121: switch (type) {
122: case AXIAL_SHADING:
123: shader = new ShaderType2();
124: break;
125:
126: case FUNCTION_SHADING:
127: case RADIAL_SHADING:
128: case FREE_FORM_SHADING:
129: case LATTICE_SHADING:
130: case COONS_PATCH_MESH_SHADING:
131: case TENSOR_PRODUCTS_MESH_SHADING:
132: default:
133: throw new PDFParseException("Unsupported shader type: "
134: + type);
135: }
136:
137: // read the color space (required)
138: PDFObject csObj = shaderObj.getDictRef("ColorSpace");
139: if (csObj == null) {
140: throw new PDFParseException("No colorspace defined!");
141: }
142: PDFColorSpace cs = PDFColorSpace
143: .getColorSpace(csObj, resources);
144: shader.setColorSpace(cs);
145:
146: // read the background color (optional)
147: PDFObject bgObj = shaderObj.getDictRef("Background");
148: if (bgObj != null) {
149: PDFObject[] bgObjs = bgObj.getArray();
150: float[] bgArray = new float[bgObjs.length];
151: for (int i = 0; i < bgArray.length; i++) {
152: bgArray[i] = bgObjs[i].getFloatValue();
153: }
154: PDFPaint paint = cs.getPaint(bgArray);
155: shader.setBackground(paint);
156: }
157:
158: // read the bounding box (optional)
159: PDFObject bboxObj = shaderObj.getDictRef("BBox");
160: if (bboxObj != null) {
161: PDFObject[] rectObj = bboxObj.getArray();
162: float minX = rectObj[0].getFloatValue();
163: float minY = rectObj[1].getFloatValue();
164: float maxX = rectObj[2].getFloatValue();
165: float maxY = rectObj[3].getFloatValue();
166:
167: Rectangle2D bbox = new Rectangle2D.Float(minX, minY, maxX
168: - minX, maxY - minY);
169: shader.setBBox(bbox);
170: }
171:
172: // parse the shader-specific attributes
173: shader.parse(shaderObj);
174:
175: // set the cache
176: shaderObj.setCache(shader);
177:
178: return shader;
179: }
180:
181: /**
182: * Get the type
183: */
184: public int getType() {
185: return type;
186: }
187:
188: /**
189: * Get the color space
190: */
191: public PDFColorSpace getColorSpace() {
192: return colorSpace;
193: }
194:
195: /**
196: * Set the color space
197: */
198: protected void setColorSpace(PDFColorSpace colorSpace) {
199: this .colorSpace = colorSpace;
200: }
201:
202: /**
203: * Get the background color
204: */
205: public PDFPaint getBackground() {
206: return background;
207: }
208:
209: /**
210: * Set the background color
211: */
212: protected void setBackground(PDFPaint background) {
213: this .background = background;
214: }
215:
216: /**
217: * Get the bounding box
218: */
219: public Rectangle2D getBBox() {
220: return bbox;
221: }
222:
223: /**
224: * Set the bounding box
225: */
226: protected void setBBox(Rectangle2D bbox) {
227: this .bbox = bbox;
228: }
229:
230: /**
231: * Parse the shader-specific data
232: */
233: public abstract void parse(PDFObject shareObj) throws IOException;
234:
235: /**
236: * Returns paint that represents the selected shader
237: */
238: public abstract PDFPaint getPaint();
239: }
|