author | jgodinez |
Tue, 04 Aug 2009 17:25:36 -0700 | |
changeset 3927 | d717df90e151 |
parent 2391 | 3397fe90e591 |
child 5506 | 202f599c92aa |
permissions | -rw-r--r-- |
2 | 1 |
/* |
2 |
* Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. |
|
3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
7 |
* published by the Free Software Foundation. Sun designates this |
|
8 |
* particular file as subject to the "Classpath" exception as provided |
|
9 |
* by Sun in the LICENSE file that accompanied this code. |
|
10 |
* |
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
21 |
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
22 |
* CA 95054 USA or visit www.sun.com if you need additional information or |
|
23 |
* have any questions. |
|
24 |
*/ |
|
25 |
||
26 |
package sun.java2d.pisces; |
|
27 |
||
28 |
import java.awt.Shape; |
|
29 |
import java.awt.BasicStroke; |
|
30 |
import java.awt.geom.Path2D; |
|
31 |
import java.awt.geom.AffineTransform; |
|
32 |
import java.awt.geom.PathIterator; |
|
33 |
||
34 |
import sun.awt.geom.PathConsumer2D; |
|
35 |
import sun.java2d.pipe.Region; |
|
36 |
import sun.java2d.pipe.RenderingEngine; |
|
37 |
import sun.java2d.pipe.AATileGenerator; |
|
38 |
||
39 |
public class PiscesRenderingEngine extends RenderingEngine { |
|
40 |
public static Transform4 IdentT4 = new Transform4(); |
|
41 |
public static double defaultFlat = 0.1; |
|
42 |
||
43 |
static int FloatToS15_16(float flt) { |
|
44 |
flt = flt * 65536f + 0.5f; |
|
45 |
if (flt <= -(65536f * 65536f)) { |
|
46 |
return Integer.MIN_VALUE; |
|
47 |
} else if (flt >= (65536f * 65536f)) { |
|
48 |
return Integer.MAX_VALUE; |
|
49 |
} else { |
|
50 |
return (int) Math.floor(flt); |
|
51 |
} |
|
52 |
} |
|
53 |
||
54 |
static float S15_16ToFloat(int fix) { |
|
55 |
return (fix / 65536f); |
|
56 |
} |
|
57 |
||
58 |
/** |
|
59 |
* Create a widened path as specified by the parameters. |
|
60 |
* <p> |
|
61 |
* The specified {@code src} {@link Shape} is widened according |
|
62 |
* to the specified attribute parameters as per the |
|
63 |
* {@link BasicStroke} specification. |
|
64 |
* |
|
65 |
* @param src the source path to be widened |
|
66 |
* @param width the width of the widened path as per {@code BasicStroke} |
|
67 |
* @param caps the end cap decorations as per {@code BasicStroke} |
|
68 |
* @param join the segment join decorations as per {@code BasicStroke} |
|
69 |
* @param miterlimit the miter limit as per {@code BasicStroke} |
|
70 |
* @param dashes the dash length array as per {@code BasicStroke} |
|
71 |
* @param dashphase the initial dash phase as per {@code BasicStroke} |
|
72 |
* @return the widened path stored in a new {@code Shape} object |
|
73 |
* @since 1.7 |
|
74 |
*/ |
|
75 |
public Shape createStrokedShape(Shape src, |
|
76 |
float width, |
|
77 |
int caps, |
|
78 |
int join, |
|
79 |
float miterlimit, |
|
80 |
float dashes[], |
|
81 |
float dashphase) |
|
82 |
{ |
|
83 |
final Path2D p2d = new Path2D.Float(); |
|
84 |
||
85 |
strokeTo(src, |
|
86 |
null, |
|
87 |
width, |
|
88 |
caps, |
|
89 |
join, |
|
90 |
miterlimit, |
|
91 |
dashes, |
|
92 |
dashphase, |
|
93 |
new LineSink() { |
|
94 |
public void moveTo(int x0, int y0) { |
|
95 |
p2d.moveTo(S15_16ToFloat(x0), S15_16ToFloat(y0)); |
|
96 |
} |
|
97 |
public void lineJoin() {} |
|
98 |
public void lineTo(int x1, int y1) { |
|
99 |
p2d.lineTo(S15_16ToFloat(x1), S15_16ToFloat(y1)); |
|
100 |
} |
|
101 |
public void close() { |
|
102 |
p2d.closePath(); |
|
103 |
} |
|
104 |
public void end() {} |
|
105 |
}); |
|
106 |
||
107 |
return p2d; |
|
108 |
} |
|
109 |
||
110 |
/** |
|
111 |
* Sends the geometry for a widened path as specified by the parameters |
|
112 |
* to the specified consumer. |
|
113 |
* <p> |
|
114 |
* The specified {@code src} {@link Shape} is widened according |
|
115 |
* to the parameters specified by the {@link BasicStroke} object. |
|
116 |
* Adjustments are made to the path as appropriate for the |
|
117 |
* {@link VALUE_STROKE_NORMALIZE} hint if the {@code normalize} |
|
118 |
* boolean parameter is true. |
|
119 |
* Adjustments are made to the path as appropriate for the |
|
120 |
* {@link VALUE_ANTIALIAS_ON} hint if the {@code antialias} |
|
121 |
* boolean parameter is true. |
|
122 |
* <p> |
|
123 |
* The geometry of the widened path is forwarded to the indicated |
|
124 |
* {@link PathConsumer2D} object as it is calculated. |
|
125 |
* |
|
126 |
* @param src the source path to be widened |
|
127 |
* @param bs the {@code BasicSroke} object specifying the |
|
128 |
* decorations to be applied to the widened path |
|
129 |
* @param normalize indicates whether stroke normalization should |
|
130 |
* be applied |
|
131 |
* @param antialias indicates whether or not adjustments appropriate |
|
132 |
* to antialiased rendering should be applied |
|
133 |
* @param consumer the {@code PathConsumer2D} instance to forward |
|
134 |
* the widened geometry to |
|
135 |
* @since 1.7 |
|
136 |
*/ |
|
137 |
public void strokeTo(Shape src, |
|
138 |
AffineTransform at, |
|
139 |
BasicStroke bs, |
|
140 |
boolean thin, |
|
141 |
boolean normalize, |
|
142 |
boolean antialias, |
|
143 |
final PathConsumer2D consumer) |
|
144 |
{ |
|
145 |
strokeTo(src, at, bs, thin, normalize, antialias, |
|
146 |
new LineSink() { |
|
147 |
public void moveTo(int x0, int y0) { |
|
148 |
consumer.moveTo(S15_16ToFloat(x0), S15_16ToFloat(y0)); |
|
149 |
} |
|
150 |
public void lineJoin() {} |
|
151 |
public void lineTo(int x1, int y1) { |
|
152 |
consumer.lineTo(S15_16ToFloat(x1), S15_16ToFloat(y1)); |
|
153 |
} |
|
154 |
public void close() { |
|
155 |
consumer.closePath(); |
|
156 |
} |
|
157 |
public void end() { |
|
158 |
consumer.pathDone(); |
|
159 |
} |
|
160 |
}); |
|
161 |
} |
|
162 |
||
163 |
void strokeTo(Shape src, |
|
164 |
AffineTransform at, |
|
165 |
BasicStroke bs, |
|
166 |
boolean thin, |
|
167 |
boolean normalize, |
|
168 |
boolean antialias, |
|
169 |
LineSink lsink) |
|
170 |
{ |
|
171 |
float lw; |
|
172 |
if (thin) { |
|
173 |
if (antialias) { |
|
3927
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
174 |
lw = userSpaceLineWidth(at, 0.5f); |
2 | 175 |
} else { |
3927
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
176 |
lw = userSpaceLineWidth(at, 1.0f); |
2 | 177 |
} |
178 |
} else { |
|
179 |
lw = bs.getLineWidth(); |
|
180 |
} |
|
181 |
strokeTo(src, |
|
182 |
at, |
|
183 |
lw, |
|
184 |
bs.getEndCap(), |
|
185 |
bs.getLineJoin(), |
|
186 |
bs.getMiterLimit(), |
|
187 |
bs.getDashArray(), |
|
188 |
bs.getDashPhase(), |
|
189 |
lsink); |
|
190 |
} |
|
191 |
||
3927
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
192 |
private float userSpaceLineWidth(AffineTransform at, float lw) { |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
193 |
|
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
194 |
double widthScale; |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
195 |
|
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
196 |
if ((at.getType() & (AffineTransform.TYPE_GENERAL_TRANSFORM | |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
197 |
AffineTransform.TYPE_GENERAL_SCALE)) != 0) { |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
198 |
widthScale = Math.sqrt(at.getDeterminant()); |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
199 |
} else { |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
200 |
/* First calculate the "maximum scale" of this transform. */ |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
201 |
double A = at.getScaleX(); // m00 |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
202 |
double C = at.getShearX(); // m01 |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
203 |
double B = at.getShearY(); // m10 |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
204 |
double D = at.getScaleY(); // m11 |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
205 |
|
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
206 |
/* |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
207 |
* Given a 2 x 2 affine matrix [ A B ] such that |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
208 |
* [ C D ] |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
209 |
* v' = [x' y'] = [Ax + Cy, Bx + Dy], we want to |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
210 |
* find the maximum magnitude (norm) of the vector v' |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
211 |
* with the constraint (x^2 + y^2 = 1). |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
212 |
* The equation to maximize is |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
213 |
* |v'| = sqrt((Ax+Cy)^2+(Bx+Dy)^2) |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
214 |
* or |v'| = sqrt((AA+BB)x^2 + 2(AC+BD)xy + (CC+DD)y^2). |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
215 |
* Since sqrt is monotonic we can maximize |v'|^2 |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
216 |
* instead and plug in the substitution y = sqrt(1 - x^2). |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
217 |
* Trigonometric equalities can then be used to get |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
218 |
* rid of most of the sqrt terms. |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
219 |
*/ |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
220 |
|
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
221 |
double EA = A*A + B*B; // x^2 coefficient |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
222 |
double EB = 2*(A*C + B*D); // xy coefficient |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
223 |
double EC = C*C + D*D; // y^2 coefficient |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
224 |
|
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
225 |
/* |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
226 |
* There is a lot of calculus omitted here. |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
227 |
* |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
228 |
* Conceptually, in the interests of understanding the |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
229 |
* terms that the calculus produced we can consider |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
230 |
* that EA and EC end up providing the lengths along |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
231 |
* the major axes and the hypot term ends up being an |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
232 |
* adjustment for the additional length along the off-axis |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
233 |
* angle of rotated or sheared ellipses as well as an |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
234 |
* adjustment for the fact that the equation below |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
235 |
* averages the two major axis lengths. (Notice that |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
236 |
* the hypot term contains a part which resolves to the |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
237 |
* difference of these two axis lengths in the absence |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
238 |
* of rotation.) |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
239 |
* |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
240 |
* In the calculus, the ratio of the EB and (EA-EC) terms |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
241 |
* ends up being the tangent of 2*theta where theta is |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
242 |
* the angle that the long axis of the ellipse makes |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
243 |
* with the horizontal axis. Thus, this equation is |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
244 |
* calculating the length of the hypotenuse of a triangle |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
245 |
* along that axis. |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
246 |
*/ |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
247 |
|
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
248 |
double hypot = Math.sqrt(EB*EB + (EA-EC)*(EA-EC)); |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
249 |
/* sqrt omitted, compare to squared limits below. */ |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
250 |
double widthsquared = ((EA + EC + hypot)/2.0); |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
251 |
|
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
252 |
widthScale = Math.sqrt(widthsquared); |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
253 |
} |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
254 |
|
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
255 |
return (float) (lw / widthScale); |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
256 |
} |
d717df90e151
6829673: ThinLineTest: A line < 1 pixel disappears.
jgodinez
parents:
2391
diff
changeset
|
257 |
|
2 | 258 |
void strokeTo(Shape src, |
259 |
AffineTransform at, |
|
260 |
float width, |
|
261 |
int caps, |
|
262 |
int join, |
|
263 |
float miterlimit, |
|
264 |
float dashes[], |
|
265 |
float dashphase, |
|
266 |
LineSink lsink) |
|
267 |
{ |
|
268 |
Transform4 t4; |
|
269 |
||
270 |
if (at == null || at.isIdentity()) { |
|
271 |
t4 = IdentT4; |
|
272 |
} else { |
|
273 |
t4 = new Transform4(FloatToS15_16((float) at.getScaleX()), |
|
274 |
FloatToS15_16((float) at.getShearX()), |
|
275 |
FloatToS15_16((float) at.getShearY()), |
|
276 |
FloatToS15_16((float) at.getScaleY())); |
|
277 |
} |
|
278 |
||
279 |
lsink = new Stroker(lsink, |
|
280 |
FloatToS15_16(width), |
|
281 |
caps, |
|
282 |
join, |
|
283 |
FloatToS15_16(miterlimit), |
|
284 |
t4); |
|
285 |
if (dashes != null) { |
|
286 |
int fdashes[] = new int[dashes.length]; |
|
287 |
for (int i = 0; i < dashes.length; i++) { |
|
288 |
fdashes[i] = FloatToS15_16(dashes[i]); |
|
289 |
} |
|
290 |
lsink = new Dasher(lsink, |
|
291 |
fdashes, |
|
292 |
FloatToS15_16(dashphase), |
|
293 |
t4); |
|
294 |
} |
|
295 |
||
296 |
PathIterator pi = src.getPathIterator(at, defaultFlat); |
|
297 |
pathTo(pi, lsink); |
|
298 |
} |
|
299 |
||
300 |
void pathTo(PathIterator pi, LineSink lsink) { |
|
301 |
float coords[] = new float[2]; |
|
302 |
while (!pi.isDone()) { |
|
303 |
switch (pi.currentSegment(coords)) { |
|
304 |
case PathIterator.SEG_MOVETO: |
|
305 |
lsink.moveTo(FloatToS15_16(coords[0]), |
|
306 |
FloatToS15_16(coords[1])); |
|
307 |
break; |
|
308 |
case PathIterator.SEG_LINETO: |
|
309 |
lsink.lineJoin(); |
|
310 |
lsink.lineTo(FloatToS15_16(coords[0]), |
|
311 |
FloatToS15_16(coords[1])); |
|
312 |
break; |
|
313 |
case PathIterator.SEG_CLOSE: |
|
2391
3397fe90e591
6812600: The miter line join decoration isn't rendered properly
jgodinez
parents:
2
diff
changeset
|
314 |
lsink.lineJoin(); |
2 | 315 |
lsink.close(); |
316 |
break; |
|
317 |
default: |
|
318 |
throw new InternalError("unknown flattened segment type"); |
|
319 |
} |
|
320 |
pi.next(); |
|
321 |
} |
|
322 |
lsink.end(); |
|
323 |
} |
|
324 |
||
325 |
/** |
|
326 |
* Construct an antialiased tile generator for the given shape with |
|
327 |
* the given rendering attributes and store the bounds of the tile |
|
328 |
* iteration in the bbox parameter. |
|
329 |
* The {@code at} parameter specifies a transform that should affect |
|
330 |
* both the shape and the {@code BasicStroke} attributes. |
|
331 |
* The {@code clip} parameter specifies the current clip in effect |
|
332 |
* in device coordinates and can be used to prune the data for the |
|
333 |
* operation, but the renderer is not required to perform any |
|
334 |
* clipping. |
|
335 |
* If the {@code BasicStroke} parameter is null then the shape |
|
336 |
* should be filled as is, otherwise the attributes of the |
|
337 |
* {@code BasicStroke} should be used to specify a draw operation. |
|
338 |
* The {@code thin} parameter indicates whether or not the |
|
339 |
* transformed {@code BasicStroke} represents coordinates smaller |
|
340 |
* than the minimum resolution of the antialiasing rasterizer as |
|
341 |
* specified by the {@code getMinimumAAPenWidth()} method. |
|
342 |
* <p> |
|
343 |
* Upon returning, this method will fill the {@code bbox} parameter |
|
344 |
* with 4 values indicating the bounds of the iteration of the |
|
345 |
* tile generator. |
|
346 |
* The iteration order of the tiles will be as specified by the |
|
347 |
* pseudo-code: |
|
348 |
* <pre> |
|
349 |
* for (y = bbox[1]; y < bbox[3]; y += tileheight) { |
|
350 |
* for (x = bbox[0]; x < bbox[2]; x += tilewidth) { |
|
351 |
* } |
|
352 |
* } |
|
353 |
* </pre> |
|
354 |
* If there is no output to be rendered, this method may return |
|
355 |
* null. |
|
356 |
* |
|
357 |
* @param s the shape to be rendered (fill or draw) |
|
358 |
* @param at the transform to be applied to the shape and the |
|
359 |
* stroke attributes |
|
360 |
* @param clip the current clip in effect in device coordinates |
|
361 |
* @param bs if non-null, a {@code BasicStroke} whose attributes |
|
362 |
* should be applied to this operation |
|
363 |
* @param thin true if the transformed stroke attributes are smaller |
|
364 |
* than the minimum dropout pen width |
|
365 |
* @param normalize true if the {@code VALUE_STROKE_NORMALIZE} |
|
366 |
* {@code RenderingHint} is in effect |
|
367 |
* @param bbox returns the bounds of the iteration |
|
368 |
* @return the {@code AATileGenerator} instance to be consulted |
|
369 |
* for tile coverages, or null if there is no output to render |
|
370 |
* @since 1.7 |
|
371 |
*/ |
|
372 |
public AATileGenerator getAATileGenerator(Shape s, |
|
373 |
AffineTransform at, |
|
374 |
Region clip, |
|
375 |
BasicStroke bs, |
|
376 |
boolean thin, |
|
377 |
boolean normalize, |
|
378 |
int bbox[]) |
|
379 |
{ |
|
380 |
PiscesCache pc = PiscesCache.createInstance(); |
|
381 |
Renderer r = new Renderer(); |
|
382 |
r.setCache(pc); |
|
383 |
r.setAntialiasing(3, 3); |
|
384 |
r.beginRendering(clip.getLoX(), clip.getLoY(), |
|
385 |
clip.getWidth(), clip.getHeight()); |
|
386 |
if (bs == null) { |
|
387 |
PathIterator pi = s.getPathIterator(at, defaultFlat); |
|
388 |
r.setWindingRule(pi.getWindingRule()); |
|
389 |
pathTo(pi, r); |
|
390 |
} else { |
|
391 |
r.setWindingRule(PathIterator.WIND_NON_ZERO); |
|
392 |
strokeTo(s, at, bs, thin, normalize, true, r); |
|
393 |
} |
|
394 |
r.endRendering(); |
|
395 |
PiscesTileGenerator ptg = new PiscesTileGenerator(pc, r.MAX_AA_ALPHA); |
|
396 |
ptg.getBbox(bbox); |
|
397 |
return ptg; |
|
398 |
} |
|
399 |
||
400 |
/** |
|
401 |
* Returns the minimum pen width that the antialiasing rasterizer |
|
402 |
* can represent without dropouts occuring. |
|
403 |
* @since 1.7 |
|
404 |
*/ |
|
405 |
public float getMinimumAAPenSize() { |
|
406 |
return 0.5f; |
|
407 |
} |
|
408 |
||
409 |
static { |
|
410 |
if (PathIterator.WIND_NON_ZERO != Renderer.WIND_NON_ZERO || |
|
411 |
PathIterator.WIND_EVEN_ODD != Renderer.WIND_EVEN_ODD || |
|
412 |
BasicStroke.JOIN_MITER != Stroker.JOIN_MITER || |
|
413 |
BasicStroke.JOIN_ROUND != Stroker.JOIN_ROUND || |
|
414 |
BasicStroke.JOIN_BEVEL != Stroker.JOIN_BEVEL || |
|
415 |
BasicStroke.CAP_BUTT != Stroker.CAP_BUTT || |
|
416 |
BasicStroke.CAP_ROUND != Stroker.CAP_ROUND || |
|
417 |
BasicStroke.CAP_SQUARE != Stroker.CAP_SQUARE) |
|
418 |
{ |
|
419 |
throw new InternalError("mismatched renderer constants"); |
|
420 |
} |
|
421 |
} |
|
422 |
} |