20 * |
20 * |
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 * or visit www.oracle.com if you need additional information or have any |
22 * or visit www.oracle.com if you need additional information or have any |
23 * questions. |
23 * questions. |
24 */ |
24 */ |
25 |
|
26 package sun.java2d.pipe; |
25 package sun.java2d.pipe; |
27 |
26 |
28 import java.awt.BasicStroke; |
27 import java.awt.BasicStroke; |
29 import java.awt.Rectangle; |
28 import java.awt.Rectangle; |
30 import java.awt.Shape; |
29 import java.awt.Shape; |
31 import java.awt.geom.Rectangle2D; |
30 import java.awt.geom.Rectangle2D; |
32 import java.awt.geom.PathIterator; |
|
33 import sun.awt.SunHints; |
31 import sun.awt.SunHints; |
34 import sun.java2d.SunGraphics2D; |
32 import sun.java2d.SunGraphics2D; |
35 |
33 |
36 /** |
34 /** |
37 * This class is used to convert raw geometry into 8-bit alpha tiles |
35 * This class is used to convert raw geometry into 8-bit alpha tiles |
64 renderPath(sg, s, bs); |
71 renderPath(sg, s, bs); |
65 } |
72 } |
66 |
73 |
67 public void fill(SunGraphics2D sg, Shape s) { |
74 public void fill(SunGraphics2D sg, Shape s) { |
68 renderPath(sg, s, null); |
75 renderPath(sg, s, null); |
69 } |
|
70 |
|
71 private static Rectangle2D computeBBox(double ux1, double uy1, |
|
72 double ux2, double uy2) |
|
73 { |
|
74 if ((ux2 -= ux1) < 0) { |
|
75 ux1 += ux2; |
|
76 ux2 = -ux2; |
|
77 } |
|
78 if ((uy2 -= uy1) < 0) { |
|
79 uy1 += uy2; |
|
80 uy2 = -uy2; |
|
81 } |
|
82 return new Rectangle2D.Double(ux1, uy1, ux2, uy2); |
|
83 } |
76 } |
84 |
77 |
85 public void fillParallelogram(SunGraphics2D sg, |
78 public void fillParallelogram(SunGraphics2D sg, |
86 double ux1, double uy1, |
79 double ux1, double uy1, |
87 double ux2, double uy2, |
80 double ux2, double uy2, |
88 double x, double y, |
81 double x, double y, |
89 double dx1, double dy1, |
82 double dx1, double dy1, |
90 double dx2, double dy2) |
83 double dx2, double dy2) |
91 { |
84 { |
92 Region clip = sg.getCompClip(); |
85 Region clip = sg.getCompClip(); |
93 int abox[] = new int[4]; |
86 final TileState ts = tileStateThreadLocal.get(); |
|
87 final int[] abox = ts.abox; |
|
88 |
94 AATileGenerator aatg = |
89 AATileGenerator aatg = |
95 renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, 0, 0, |
90 renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, 0, 0, |
96 clip, abox); |
91 clip, abox); |
97 if (aatg == null) { |
92 if (aatg == null) { |
98 // Nothing to render |
93 // Nothing to render |
99 return; |
94 return; |
100 } |
95 } |
101 |
96 |
102 renderTiles(sg, computeBBox(ux1, uy1, ux2, uy2), aatg, abox); |
97 renderTiles(sg, ts.computeBBox(ux1, uy1, ux2, uy2), aatg, abox, ts); |
103 } |
98 } |
104 |
99 |
105 public void drawParallelogram(SunGraphics2D sg, |
100 public void drawParallelogram(SunGraphics2D sg, |
106 double ux1, double uy1, |
101 double ux1, double uy1, |
107 double ux2, double uy2, |
102 double ux2, double uy2, |
109 double dx1, double dy1, |
104 double dx1, double dy1, |
110 double dx2, double dy2, |
105 double dx2, double dy2, |
111 double lw1, double lw2) |
106 double lw1, double lw2) |
112 { |
107 { |
113 Region clip = sg.getCompClip(); |
108 Region clip = sg.getCompClip(); |
114 int abox[] = new int[4]; |
109 final TileState ts = tileStateThreadLocal.get(); |
|
110 final int[] abox = ts.abox; |
|
111 |
115 AATileGenerator aatg = |
112 AATileGenerator aatg = |
116 renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, lw1, lw2, |
113 renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, lw1, lw2, |
117 clip, abox); |
114 clip, abox); |
118 if (aatg == null) { |
115 if (aatg == null) { |
119 // Nothing to render |
116 // Nothing to render |
120 return; |
117 return; |
121 } |
118 } |
122 |
119 |
123 // Note that bbox is of the original shape, not the wide path. |
120 // Note that bbox is of the original shape, not the wide path. |
124 // This is appropriate for handing to Paint methods... |
121 // This is appropriate for handing to Paint methods... |
125 renderTiles(sg, computeBBox(ux1, uy1, ux2, uy2), aatg, abox); |
122 renderTiles(sg, ts.computeBBox(ux1, uy1, ux2, uy2), aatg, abox, ts); |
126 } |
|
127 |
|
128 private static byte[] theTile; |
|
129 |
|
130 private static synchronized byte[] getAlphaTile(int len) { |
|
131 byte[] t = theTile; |
|
132 if (t == null || t.length < len) { |
|
133 t = new byte[len]; |
|
134 } else { |
|
135 theTile = null; |
|
136 } |
|
137 return t; |
|
138 } |
|
139 |
|
140 private static synchronized void dropAlphaTile(byte[] t) { |
|
141 theTile = t; |
|
142 } |
123 } |
143 |
124 |
144 public void renderPath(SunGraphics2D sg, Shape s, BasicStroke bs) { |
125 public void renderPath(SunGraphics2D sg, Shape s, BasicStroke bs) { |
145 boolean adjust = (bs != null && |
126 boolean adjust = (bs != null && |
146 sg.strokeHint != SunHints.INTVAL_STROKE_PURE); |
127 sg.strokeHint != SunHints.INTVAL_STROKE_PURE); |
147 boolean thin = (sg.strokeState <= SunGraphics2D.STROKE_THINDASHED); |
128 boolean thin = (sg.strokeState <= SunGraphics2D.STROKE_THINDASHED); |
148 |
129 |
149 Region clip = sg.getCompClip(); |
130 Region clip = sg.getCompClip(); |
150 int abox[] = new int[4]; |
131 final TileState ts = tileStateThreadLocal.get(); |
|
132 final int[] abox = ts.abox; |
|
133 |
151 AATileGenerator aatg = |
134 AATileGenerator aatg = |
152 renderengine.getAATileGenerator(s, sg.transform, clip, |
135 renderengine.getAATileGenerator(s, sg.transform, clip, |
153 bs, thin, adjust, abox); |
136 bs, thin, adjust, abox); |
154 if (aatg == null) { |
137 if (aatg == null) { |
155 // Nothing to render |
138 // Nothing to render |
156 return; |
139 return; |
157 } |
140 } |
158 |
141 |
159 renderTiles(sg, s, aatg, abox); |
142 renderTiles(sg, s, aatg, abox, ts); |
160 } |
143 } |
161 |
144 |
162 public void renderTiles(SunGraphics2D sg, Shape s, |
145 public void renderTiles(SunGraphics2D sg, Shape s, |
163 AATileGenerator aatg, int abox[]) |
146 AATileGenerator aatg, int abox[], TileState ts) |
164 { |
147 { |
165 Object context = null; |
148 Object context = null; |
166 byte alpha[] = null; |
|
167 try { |
149 try { |
168 context = outpipe.startSequence(sg, s, |
150 context = outpipe.startSequence(sg, s, |
169 new Rectangle(abox[0], abox[1], |
151 ts.computeDevBox(abox), |
170 abox[2] - abox[0], |
|
171 abox[3] - abox[1]), |
|
172 abox); |
152 abox); |
173 |
153 |
174 int tw = aatg.getTileWidth(); |
154 final int tw = aatg.getTileWidth(); |
175 int th = aatg.getTileHeight(); |
155 final int th = aatg.getTileHeight(); |
176 alpha = getAlphaTile(tw * th); |
156 |
177 |
157 // get tile from thread local storage: |
|
158 final byte[] alpha = ts.getAlphaTile(tw * th); |
178 byte[] atile; |
159 byte[] atile; |
179 |
160 |
180 for (int y = abox[1]; y < abox[3]; y += th) { |
161 for (int y = abox[1]; y < abox[3]; y += th) { |
|
162 int h = Math.min(th, abox[3] - y); |
|
163 |
181 for (int x = abox[0]; x < abox[2]; x += tw) { |
164 for (int x = abox[0]; x < abox[2]; x += tw) { |
182 int w = Math.min(tw, abox[2] - x); |
165 int w = Math.min(tw, abox[2] - x); |
183 int h = Math.min(th, abox[3] - y); |
|
184 |
166 |
185 int a = aatg.getTypicalAlpha(); |
167 int a = aatg.getTypicalAlpha(); |
186 if (a == 0x00 || |
168 if (a == 0x00 || |
187 outpipe.needTile(context, x, y, w, h) == false) |
169 outpipe.needTile(context, x, y, w, h) == false) |
188 { |
170 { |
205 } finally { |
187 } finally { |
206 aatg.dispose(); |
188 aatg.dispose(); |
207 if (context != null) { |
189 if (context != null) { |
208 outpipe.endSequence(context); |
190 outpipe.endSequence(context); |
209 } |
191 } |
210 if (alpha != null) { |
192 } |
211 dropAlphaTile(alpha); |
193 } |
212 } |
194 |
213 } |
195 // Tile state used by AAShapePipe |
214 } |
196 static final class TileState { |
|
197 // cached tile (32 x 32 tile by default) |
|
198 private byte[] theTile = new byte[32 * 32]; |
|
199 // dirty aabox array |
|
200 final int[] abox = new int[4]; |
|
201 // dirty bbox rectangle |
|
202 private final Rectangle dev = new Rectangle(); |
|
203 // dirty bbox rectangle2D.Double |
|
204 private final Rectangle2D.Double bbox2D = new Rectangle2D.Double(); |
|
205 |
|
206 byte[] getAlphaTile(int len) { |
|
207 byte[] t = theTile; |
|
208 if (t.length < len) { |
|
209 // create a larger tile and may free current theTile (too small) |
|
210 theTile = t = new byte[len]; |
|
211 } |
|
212 return t; |
|
213 } |
|
214 |
|
215 Rectangle computeDevBox(final int[] abox) { |
|
216 final Rectangle box = this.dev; |
|
217 box.x = abox[0]; |
|
218 box.y = abox[1]; |
|
219 box.width = abox[2] - abox[0]; |
|
220 box.height = abox[3] - abox[1]; |
|
221 return box; |
|
222 } |
|
223 |
|
224 Rectangle2D computeBBox(double ux1, double uy1, |
|
225 double ux2, double uy2) |
|
226 { |
|
227 if ((ux2 -= ux1) < 0.0) { |
|
228 ux1 += ux2; |
|
229 ux2 = -ux2; |
|
230 } |
|
231 if ((uy2 -= uy1) < 0.0) { |
|
232 uy1 += uy2; |
|
233 uy2 = -uy2; |
|
234 } |
|
235 final Rectangle2D.Double box = this.bbox2D; |
|
236 box.x = ux1; |
|
237 box.y = uy1; |
|
238 box.width = ux2; |
|
239 box.height = uy2; |
|
240 return box; |
|
241 } |
|
242 } |
|
243 |
215 } |
244 } |