1
2 package org.freehep.graphicsio.pdf;
3
4 import java.awt.GradientPaint;
5 import java.awt.Paint;
6 import java.awt.TexturePaint;
7 import java.awt.geom.AffineTransform;
8 import java.awt.geom.Point2D;
9 import java.awt.image.BufferedImage;
10 import java.io.IOException;
11 import java.util.LinkedList;
12 import java.util.List;
13 import java.util.ListIterator;
14
15
16
17
18
19
20
21
22
23
24
25 public class PDFPaintDelayQueue {
26
27 private static int currentNumber = 0;
28
29 private class Entry {
30 private Paint paint;
31
32 private String name;
33
34 private AffineTransform trafo;
35
36 private String writeAs;
37
38 private boolean written;
39
40 private Entry(Paint paint, AffineTransform trafo, String writeAs) {
41 this.paint = paint;
42 this.trafo = trafo;
43 this.writeAs = writeAs;
44 this.name = "Paint" + (currentNumber++);
45 this.written = false;
46 }
47 }
48
49 private List paintList;
50
51 private PDFWriter pdf;
52
53
54
55 private AffineTransform pageMatrix;
56
57
58 public PDFPaintDelayQueue(PDFWriter pdf, PDFImageDelayQueue imageDelayQueue) {
59 this.pdf = pdf;
60 this.paintList = new LinkedList();
61
62 this.pageMatrix = new AffineTransform();
63 }
64
65
66
67
68
69
70
71 public void setPageMatrix(AffineTransform t) {
72 pageMatrix = new AffineTransform(t);
73 }
74
75 public PDFName delayPaint(Paint paint, AffineTransform transform,
76 String writeAs) {
77 Entry e = new Entry(paint, transform, writeAs);
78 paintList.add(e);
79 return pdf.name(e.name);
80 }
81
82
83 public void processAll() throws IOException {
84 ListIterator i = paintList.listIterator();
85 while (i.hasNext()) {
86 Entry e = (Entry) i.next();
87
88 if (!e.written) {
89 e.written = true;
90 if (e.paint instanceof GradientPaint) {
91 addGradientPaint(e);
92 } else if (e.paint instanceof TexturePaint) {
93 addTexturePaint(e);
94 } else {
95 System.err.println("PDFWriter: Paint of class '"
96 + e.paint.getClass() + "' not supported.");
97
98
99 }
100 }
101 }
102 }
103
104
105
106
107
108 public int addPatterns() throws IOException {
109 if (paintList.size() > 0) {
110 PDFDictionary patterns = pdf.openDictionary("Pattern");
111 ListIterator i = paintList.listIterator();
112 while (i.hasNext()) {
113 Entry e = (Entry) i.next();
114 patterns.entry(e.name, pdf.ref(e.name));
115 }
116 pdf.close(patterns);
117 }
118 return paintList.size();
119 }
120
121 private void addGradientPaint(Entry e) throws IOException {
122 GradientPaint gp = (GradientPaint) e.paint;
123
124
125 PDFDictionary pattern = pdf.openDictionary(e.name);
126 pattern.entry("Type", pdf.name("Pattern"));
127 pattern.entry("PatternType", 2);
128 setMatrix(pattern, e, 0, 0);
129
130
131 PDFDictionary shading = pattern.openDictionary("Shading");
132 shading.entry("ShadingType", 2);
133 shading.entry("ColorSpace", pdf.name("DeviceRGB"));
134 Point2D p1 = gp.getPoint1();
135 Point2D p2 = gp.getPoint2();
136 shading.entry("Coords", new double[] { p1.getX(), p1.getY(), p2.getX(),
137 p2.getY() });
138 double[] domain = new double[] { 0, 1 };
139 shading.entry("Domain", domain);
140
141
142
143 String functionRef = e.name + "Function";
144 shading.entry("Function", pdf.ref(functionRef));
145 shading.entry("Extend", new boolean[] { true, true });
146
147 pattern.close(shading);
148
149 pdf.close(pattern);
150
151
152 float[] col0 = new float[3];
153 gp.getColor1().getRGBColorComponents(col0);
154 double c0[] = new double[] { col0[0], col0[1], col0[2] };
155 float[] col1 = new float[3];
156 gp.getColor2().getRGBColorComponents(col1);
157 double c1[] = new double[] { col1[0], col1[1], col1[2] };
158 if (gp.isCyclic()) {
159
160
161
162 addLinearFunction(functionRef, c0, c1, domain);
163 } else {
164 addLinearFunction(functionRef, c0, c1, domain);
165 }
166 }
167
168
169 private void addLinearFunction(String functionRef, double[] c0,
170 double[] c1, double[] dom) throws IOException {
171 PDFDictionary function = pdf.openDictionary(functionRef);
172 function.entry("FunctionType", 2);
173 function.entry("Domain", dom);
174 function.entry("Range", new double[] { 0., 1., 0., 1., 0., 1. });
175 function.entry("C0", c0);
176 function.entry("C1", c1);
177 function.entry("N", 1);
178 pdf.close(function);
179 }
180
181
182
183
184
185
186 protected void addCyclicFunction(String functionRef, double[] c0,
187 double[] c1, double[] dom) throws IOException {
188
189
190 PDFStream function = pdf.openStream(functionRef);
191 function.entry("FunctionType", 4);
192
193 function.entry("Domain", dom);
194 function.entry("Range", new double[] { 0., 1., 0., 1., 0., 1. });
195 function.println("{");
196
197
198
199
200
201 for (int i = 0; i < 3; i++) {
202 if (i < 2)
203 function.println("dup");
204 function.println((c1[i] - c0[i]) + " mul");
205 function.println(c0[i] + " add");
206 if (i < 2)
207 function.println("exch");
208 }
209
210
211
212 function.println("}");
213 pdf.close(function);
214 }
215
216 private void addTexturePaint(Entry e) throws IOException {
217 TexturePaint tp = (TexturePaint) e.paint;
218
219
220 PDFStream pattern = pdf.openStream(e.name, null);
221 pattern.entry("Type", pdf.name("Pattern"));
222 pattern.entry("PatternType", 1);
223 pattern.entry("PaintType", 1);
224 BufferedImage image = tp.getImage();
225 pattern.entry("TilingType", 1);
226 double width = tp.getAnchorRect().getWidth();
227 double height = tp.getAnchorRect().getHeight();
228 double offsX = tp.getAnchorRect().getX();
229 double offsY = tp.getAnchorRect().getY();
230 pattern.entry("BBox", new double[] { 0, 0, width, height });
231 pattern.entry("XStep", width);
232 pattern.entry("YStep", height);
233 PDFDictionary resources = pattern.openDictionary("Resources");
234 resources.entry("ProcSet", new Object[] { pdf.name("PDF"),
235 pdf.name("ImageC") });
236 pattern.close(resources);
237 setMatrix(pattern, e, offsX, offsY);
238
239
240 pattern.matrix(width, 0, 0, -height, 0, height);
241
242 pattern.inlineImage(image, null, e.writeAs);
243 pdf.close(pattern);
244 }
245
246
247
248
249
250 private void setMatrix(PDFDictionary dict, Entry e, double translX,
251 double translY) throws IOException {
252
253 AffineTransform trafo = new AffineTransform(pageMatrix);
254 trafo.concatenate(e.trafo);
255 trafo.translate(translX, translY);
256 double[] matrix = new double[6];
257 trafo.getMatrix(matrix);
258 dict.entry("Matrix", new double[] { matrix[0], matrix[1], matrix[2],
259 matrix[3], matrix[4], matrix[5] });
260 }
261 }