100 // Since we actually need P/3 and Q/2 for all of the |
111 // Since we actually need P/3 and Q/2 for all of the |
101 // calculations that follow, we will calculate |
112 // calculations that follow, we will calculate |
102 // p = P/3 |
113 // p = P/3 |
103 // q = Q/2 |
114 // q = Q/2 |
104 // instead and use those values for simplicity of the code. |
115 // instead and use those values for simplicity of the code. |
105 double sq_A = a * a; |
116 final double sub = (1.0d / 3.0d) * a; |
106 double p = (1.0d/3.0d) * ((-1.0d/3.0d) * sq_A + b); |
117 final double sq_A = a * a; |
107 double q = (1.0d/2.0d) * ((2.0d/27.0d) * a * sq_A - (1.0d/3.0d) * a * b + c); |
118 final double p = (1.0d / 3.0d) * ((-1.0d / 3.0d) * sq_A + b); |
|
119 final double q = (1.0d / 2.0d) * ((2.0d / 27.0d) * a * sq_A - sub * b + c); |
108 |
120 |
109 // use Cardano's formula |
121 // use Cardano's formula |
110 |
122 |
111 double cb_p = p * p * p; |
123 final double cb_p = p * p * p; |
112 double D = q * q + cb_p; |
124 final double D = q * q + cb_p; |
113 |
125 |
114 int num; |
126 int num; |
115 if (D < 0.0d) { |
127 if (D < 0.0d) { |
116 // see: http://en.wikipedia.org/wiki/Cubic_function#Trigonometric_.28and_hyperbolic.29_method |
128 // see: http://en.wikipedia.org/wiki/Cubic_function#Trigonometric_.28and_hyperbolic.29_method |
117 final double phi = (1.0d/3.0d) * Math.acos(-q / Math.sqrt(-cb_p)); |
129 final double phi = (1.0d / 3.0d) * Math.acos(-q / Math.sqrt(-cb_p)); |
118 final double t = 2.0d * Math.sqrt(-p); |
130 final double t = 2.0d * Math.sqrt(-p); |
119 |
131 |
120 pts[ off+0 ] = ( t * Math.cos(phi)); |
132 pts[off ] = ( t * Math.cos(phi) - sub); |
121 pts[ off+1 ] = (-t * Math.cos(phi + (PI / 3.0d))); |
133 pts[off + 1] = (-t * Math.cos(phi + (Math.PI / 3.0d)) - sub); |
122 pts[ off+2 ] = (-t * Math.cos(phi - (PI / 3.0d))); |
134 pts[off + 2] = (-t * Math.cos(phi - (Math.PI / 3.0d)) - sub); |
123 num = 3; |
135 num = 3; |
124 } else { |
136 } else { |
125 final double sqrt_D = Math.sqrt(D); |
137 final double sqrt_D = Math.sqrt(D); |
126 final double u = Math.cbrt(sqrt_D - q); |
138 final double u = Math.cbrt(sqrt_D - q); |
127 final double v = - Math.cbrt(sqrt_D + q); |
139 final double v = - Math.cbrt(sqrt_D + q); |
128 |
140 |
129 pts[ off ] = (u + v); |
141 pts[off ] = (u + v - sub); |
130 num = 1; |
142 num = 1; |
131 |
143 |
132 if (within(D, 0.0d, 1e-8d)) { |
144 if (within(D, 0.0d, 1e-8d)) { |
133 pts[off+1] = -(pts[off] / 2.0d); |
145 pts[off + 1] = ((-1.0d / 2.0d) * (u + v) - sub); |
134 num = 2; |
146 num = 2; |
135 } |
147 } |
136 } |
148 } |
137 |
149 |
138 final double sub = (1.0d/3.0d) * a; |
|
139 |
|
140 for (int i = 0; i < num; ++i) { |
|
141 pts[ off+i ] -= sub; |
|
142 } |
|
143 |
|
144 return filterOutNotInAB(pts, off, num, A, B) - off; |
150 return filterOutNotInAB(pts, off, num, A, B) - off; |
145 } |
151 } |
146 |
152 |
147 static double evalCubic(final double a, final double b, |
|
148 final double c, final double d, |
|
149 final double t) |
|
150 { |
|
151 return t * (t * (t * a + b) + c) + d; |
|
152 } |
|
153 |
|
154 static double evalQuad(final double a, final double b, |
|
155 final double c, final double t) |
|
156 { |
|
157 return t * (t * a + b) + c; |
|
158 } |
|
159 |
|
160 // returns the index 1 past the last valid element remaining after filtering |
153 // returns the index 1 past the last valid element remaining after filtering |
161 static int filterOutNotInAB(double[] nums, final int off, final int len, |
154 static int filterOutNotInAB(final double[] nums, final int off, final int len, |
162 final double a, final double b) |
155 final double a, final double b) |
163 { |
156 { |
164 int ret = off; |
157 int ret = off; |
165 for (int i = off, end = off + len; i < end; i++) { |
158 for (int i = off, end = off + len; i < end; i++) { |
166 if (nums[i] >= a && nums[i] < b) { |
159 if (nums[i] >= a && nums[i] < b) { |
168 } |
161 } |
169 } |
162 } |
170 return ret; |
163 return ret; |
171 } |
164 } |
172 |
165 |
173 static double linelen(double x1, double y1, double x2, double y2) { |
166 static double fastLineLen(final double x0, final double y0, |
174 final double dx = x2 - x1; |
167 final double x1, final double y1) |
175 final double dy = y2 - y1; |
168 { |
176 return Math.sqrt(dx*dx + dy*dy); |
169 final double dx = x1 - x0; |
177 } |
170 final double dy = y1 - y0; |
178 |
171 |
179 static void subdivide(double[] src, int srcoff, double[] left, int leftoff, |
172 // use manhattan norm: |
180 double[] right, int rightoff, int type) |
173 return Math.abs(dx) + Math.abs(dy); |
|
174 } |
|
175 |
|
176 static double linelen(final double x0, final double y0, |
|
177 final double x1, final double y1) |
|
178 { |
|
179 final double dx = x1 - x0; |
|
180 final double dy = y1 - y0; |
|
181 return Math.sqrt(dx * dx + dy * dy); |
|
182 } |
|
183 |
|
184 static double fastQuadLen(final double x0, final double y0, |
|
185 final double x1, final double y1, |
|
186 final double x2, final double y2) |
|
187 { |
|
188 final double dx1 = x1 - x0; |
|
189 final double dx2 = x2 - x1; |
|
190 final double dy1 = y1 - y0; |
|
191 final double dy2 = y2 - y1; |
|
192 |
|
193 // use manhattan norm: |
|
194 return Math.abs(dx1) + Math.abs(dx2) |
|
195 + Math.abs(dy1) + Math.abs(dy2); |
|
196 } |
|
197 |
|
198 static double quadlen(final double x0, final double y0, |
|
199 final double x1, final double y1, |
|
200 final double x2, final double y2) |
|
201 { |
|
202 return (linelen(x0, y0, x1, y1) |
|
203 + linelen(x1, y1, x2, y2) |
|
204 + linelen(x0, y0, x2, y2)) / 2.0d; |
|
205 } |
|
206 |
|
207 static double fastCurvelen(final double x0, final double y0, |
|
208 final double x1, final double y1, |
|
209 final double x2, final double y2, |
|
210 final double x3, final double y3) |
|
211 { |
|
212 final double dx1 = x1 - x0; |
|
213 final double dx2 = x2 - x1; |
|
214 final double dx3 = x3 - x2; |
|
215 final double dy1 = y1 - y0; |
|
216 final double dy2 = y2 - y1; |
|
217 final double dy3 = y3 - y2; |
|
218 |
|
219 // use manhattan norm: |
|
220 return Math.abs(dx1) + Math.abs(dx2) + Math.abs(dx3) |
|
221 + Math.abs(dy1) + Math.abs(dy2) + Math.abs(dy3); |
|
222 } |
|
223 |
|
224 static double curvelen(final double x0, final double y0, |
|
225 final double x1, final double y1, |
|
226 final double x2, final double y2, |
|
227 final double x3, final double y3) |
|
228 { |
|
229 return (linelen(x0, y0, x1, y1) |
|
230 + linelen(x1, y1, x2, y2) |
|
231 + linelen(x2, y2, x3, y3) |
|
232 + linelen(x0, y0, x3, y3)) / 2.0d; |
|
233 } |
|
234 |
|
235 // finds values of t where the curve in pts should be subdivided in order |
|
236 // to get good offset curves a distance of w away from the middle curve. |
|
237 // Stores the points in ts, and returns how many of them there were. |
|
238 static int findSubdivPoints(final DCurve c, final double[] pts, |
|
239 final double[] ts, final int type, |
|
240 final double w2) |
|
241 { |
|
242 final double x12 = pts[2] - pts[0]; |
|
243 final double y12 = pts[3] - pts[1]; |
|
244 // if the curve is already parallel to either axis we gain nothing |
|
245 // from rotating it. |
|
246 if ((y12 != 0.0d && x12 != 0.0d)) { |
|
247 // we rotate it so that the first vector in the control polygon is |
|
248 // parallel to the x-axis. This will ensure that rotated quarter |
|
249 // circles won't be subdivided. |
|
250 final double hypot = Math.sqrt(x12 * x12 + y12 * y12); |
|
251 final double cos = x12 / hypot; |
|
252 final double sin = y12 / hypot; |
|
253 final double x1 = cos * pts[0] + sin * pts[1]; |
|
254 final double y1 = cos * pts[1] - sin * pts[0]; |
|
255 final double x2 = cos * pts[2] + sin * pts[3]; |
|
256 final double y2 = cos * pts[3] - sin * pts[2]; |
|
257 final double x3 = cos * pts[4] + sin * pts[5]; |
|
258 final double y3 = cos * pts[5] - sin * pts[4]; |
|
259 |
|
260 switch(type) { |
|
261 case 8: |
|
262 final double x4 = cos * pts[6] + sin * pts[7]; |
|
263 final double y4 = cos * pts[7] - sin * pts[6]; |
|
264 c.set(x1, y1, x2, y2, x3, y3, x4, y4); |
|
265 break; |
|
266 case 6: |
|
267 c.set(x1, y1, x2, y2, x3, y3); |
|
268 break; |
|
269 default: |
|
270 } |
|
271 } else { |
|
272 c.set(pts, type); |
|
273 } |
|
274 |
|
275 int ret = 0; |
|
276 // we subdivide at values of t such that the remaining rotated |
|
277 // curves are monotonic in x and y. |
|
278 ret += c.dxRoots(ts, ret); |
|
279 ret += c.dyRoots(ts, ret); |
|
280 |
|
281 // subdivide at inflection points. |
|
282 if (type == 8) { |
|
283 // quadratic curves can't have inflection points |
|
284 ret += c.infPoints(ts, ret); |
|
285 } |
|
286 |
|
287 // now we must subdivide at points where one of the offset curves will have |
|
288 // a cusp. This happens at ts where the radius of curvature is equal to w. |
|
289 ret += c.rootsOfROCMinusW(ts, ret, w2, 0.0001d); |
|
290 |
|
291 ret = filterOutNotInAB(ts, 0, ret, 0.0001d, 0.9999d); |
|
292 isort(ts, ret); |
|
293 return ret; |
|
294 } |
|
295 |
|
296 // finds values of t where the curve in pts should be subdivided in order |
|
297 // to get intersections with the given clip rectangle. |
|
298 // Stores the points in ts, and returns how many of them there were. |
|
299 static int findClipPoints(final DCurve curve, final double[] pts, |
|
300 final double[] ts, final int type, |
|
301 final int outCodeOR, |
|
302 final double[] clipRect) |
|
303 { |
|
304 curve.set(pts, type); |
|
305 |
|
306 // clip rectangle (ymin, ymax, xmin, xmax) |
|
307 int ret = 0; |
|
308 |
|
309 if ((outCodeOR & OUTCODE_LEFT) != 0) { |
|
310 ret += curve.xPoints(ts, ret, clipRect[2]); |
|
311 } |
|
312 if ((outCodeOR & OUTCODE_RIGHT) != 0) { |
|
313 ret += curve.xPoints(ts, ret, clipRect[3]); |
|
314 } |
|
315 if ((outCodeOR & OUTCODE_TOP) != 0) { |
|
316 ret += curve.yPoints(ts, ret, clipRect[0]); |
|
317 } |
|
318 if ((outCodeOR & OUTCODE_BOTTOM) != 0) { |
|
319 ret += curve.yPoints(ts, ret, clipRect[1]); |
|
320 } |
|
321 isort(ts, ret); |
|
322 return ret; |
|
323 } |
|
324 |
|
325 static void subdivide(final double[] src, |
|
326 final double[] left, final double[] right, |
|
327 final int type) |
181 { |
328 { |
182 switch(type) { |
329 switch(type) { |
|
330 case 8: |
|
331 subdivideCubic(src, left, right); |
|
332 return; |
183 case 6: |
333 case 6: |
184 DHelpers.subdivideQuad(src, srcoff, left, leftoff, right, rightoff); |
334 subdivideQuad(src, left, right); |
185 return; |
|
186 case 8: |
|
187 DHelpers.subdivideCubic(src, srcoff, left, leftoff, right, rightoff); |
|
188 return; |
335 return; |
189 default: |
336 default: |
190 throw new InternalError("Unsupported curve type"); |
337 throw new InternalError("Unsupported curve type"); |
191 } |
338 } |
192 } |
339 } |
193 |
340 |
194 static void isort(double[] a, int off, int len) { |
341 static void isort(final double[] a, final int len) { |
195 for (int i = off + 1, end = off + len; i < end; i++) { |
342 for (int i = 1, j; i < len; i++) { |
196 double ai = a[i]; |
343 final double ai = a[i]; |
197 int j = i - 1; |
344 j = i - 1; |
198 for (; j >= off && a[j] > ai; j--) { |
345 for (; j >= 0 && a[j] > ai; j--) { |
199 a[j+1] = a[j]; |
346 a[j + 1] = a[j]; |
200 } |
347 } |
201 a[j+1] = ai; |
348 a[j + 1] = ai; |
202 } |
349 } |
203 } |
350 } |
204 |
351 |
205 // Most of these are copied from classes in java.awt.geom because we need |
352 // Most of these are copied from classes in java.awt.geom because we need |
206 // both single and double precision variants of these functions, and Line2D, |
353 // both single and double precision variants of these functions, and Line2D, |
219 * it is possible to pass the same array for <code>left</code> |
366 * it is possible to pass the same array for <code>left</code> |
220 * and <code>right</code> and to use offsets, such as <code>rightoff</code> |
367 * and <code>right</code> and to use offsets, such as <code>rightoff</code> |
221 * equals (<code>leftoff</code> + 6), in order |
368 * equals (<code>leftoff</code> + 6), in order |
222 * to avoid allocating extra storage for this common point. |
369 * to avoid allocating extra storage for this common point. |
223 * @param src the array holding the coordinates for the source curve |
370 * @param src the array holding the coordinates for the source curve |
224 * @param srcoff the offset into the array of the beginning of the |
|
225 * the 6 source coordinates |
|
226 * @param left the array for storing the coordinates for the first |
371 * @param left the array for storing the coordinates for the first |
227 * half of the subdivided curve |
372 * half of the subdivided curve |
228 * @param leftoff the offset into the array of the beginning of the |
|
229 * the 6 left coordinates |
|
230 * @param right the array for storing the coordinates for the second |
373 * @param right the array for storing the coordinates for the second |
231 * half of the subdivided curve |
374 * half of the subdivided curve |
232 * @param rightoff the offset into the array of the beginning of the |
|
233 * the 6 right coordinates |
|
234 * @since 1.7 |
375 * @since 1.7 |
235 */ |
376 */ |
236 static void subdivideCubic(double[] src, int srcoff, |
377 static void subdivideCubic(final double[] src, |
237 double[] left, int leftoff, |
378 final double[] left, |
238 double[] right, int rightoff) |
379 final double[] right) |
239 { |
380 { |
240 double x1 = src[srcoff + 0]; |
381 double x1 = src[0]; |
241 double y1 = src[srcoff + 1]; |
382 double y1 = src[1]; |
242 double ctrlx1 = src[srcoff + 2]; |
383 double cx1 = src[2]; |
243 double ctrly1 = src[srcoff + 3]; |
384 double cy1 = src[3]; |
244 double ctrlx2 = src[srcoff + 4]; |
385 double cx2 = src[4]; |
245 double ctrly2 = src[srcoff + 5]; |
386 double cy2 = src[5]; |
246 double x2 = src[srcoff + 6]; |
387 double x2 = src[6]; |
247 double y2 = src[srcoff + 7]; |
388 double y2 = src[7]; |
248 if (left != null) { |
389 |
249 left[leftoff + 0] = x1; |
390 left[0] = x1; |
250 left[leftoff + 1] = y1; |
391 left[1] = y1; |
251 } |
392 |
252 if (right != null) { |
393 right[6] = x2; |
253 right[rightoff + 6] = x2; |
394 right[7] = y2; |
254 right[rightoff + 7] = y2; |
395 |
255 } |
396 x1 = (x1 + cx1) / 2.0d; |
256 x1 = (x1 + ctrlx1) / 2.0d; |
397 y1 = (y1 + cy1) / 2.0d; |
257 y1 = (y1 + ctrly1) / 2.0d; |
398 x2 = (x2 + cx2) / 2.0d; |
258 x2 = (x2 + ctrlx2) / 2.0d; |
399 y2 = (y2 + cy2) / 2.0d; |
259 y2 = (y2 + ctrly2) / 2.0d; |
400 |
260 double centerx = (ctrlx1 + ctrlx2) / 2.0d; |
401 double cx = (cx1 + cx2) / 2.0d; |
261 double centery = (ctrly1 + ctrly2) / 2.0d; |
402 double cy = (cy1 + cy2) / 2.0d; |
262 ctrlx1 = (x1 + centerx) / 2.0d; |
403 |
263 ctrly1 = (y1 + centery) / 2.0d; |
404 cx1 = (x1 + cx) / 2.0d; |
264 ctrlx2 = (x2 + centerx) / 2.0d; |
405 cy1 = (y1 + cy) / 2.0d; |
265 ctrly2 = (y2 + centery) / 2.0d; |
406 cx2 = (x2 + cx) / 2.0d; |
266 centerx = (ctrlx1 + ctrlx2) / 2.0d; |
407 cy2 = (y2 + cy) / 2.0d; |
267 centery = (ctrly1 + ctrly2) / 2.0d; |
408 cx = (cx1 + cx2) / 2.0d; |
268 if (left != null) { |
409 cy = (cy1 + cy2) / 2.0d; |
269 left[leftoff + 2] = x1; |
410 |
270 left[leftoff + 3] = y1; |
411 left[2] = x1; |
271 left[leftoff + 4] = ctrlx1; |
412 left[3] = y1; |
272 left[leftoff + 5] = ctrly1; |
413 left[4] = cx1; |
273 left[leftoff + 6] = centerx; |
414 left[5] = cy1; |
274 left[leftoff + 7] = centery; |
415 left[6] = cx; |
275 } |
416 left[7] = cy; |
276 if (right != null) { |
417 |
277 right[rightoff + 0] = centerx; |
418 right[0] = cx; |
278 right[rightoff + 1] = centery; |
419 right[1] = cy; |
279 right[rightoff + 2] = ctrlx2; |
420 right[2] = cx2; |
280 right[rightoff + 3] = ctrly2; |
421 right[3] = cy2; |
281 right[rightoff + 4] = x2; |
422 right[4] = x2; |
282 right[rightoff + 5] = y2; |
423 right[5] = y2; |
283 } |
424 } |
284 } |
425 |
285 |
426 static void subdivideCubicAt(final double t, |
286 |
427 final double[] src, final int offS, |
287 static void subdivideCubicAt(double t, double[] src, int srcoff, |
428 final double[] pts, final int offL, final int offR) |
288 double[] left, int leftoff, |
429 { |
289 double[] right, int rightoff) |
430 double x1 = src[offS ]; |
290 { |
431 double y1 = src[offS + 1]; |
291 double x1 = src[srcoff + 0]; |
432 double cx1 = src[offS + 2]; |
292 double y1 = src[srcoff + 1]; |
433 double cy1 = src[offS + 3]; |
293 double ctrlx1 = src[srcoff + 2]; |
434 double cx2 = src[offS + 4]; |
294 double ctrly1 = src[srcoff + 3]; |
435 double cy2 = src[offS + 5]; |
295 double ctrlx2 = src[srcoff + 4]; |
436 double x2 = src[offS + 6]; |
296 double ctrly2 = src[srcoff + 5]; |
437 double y2 = src[offS + 7]; |
297 double x2 = src[srcoff + 6]; |
438 |
298 double y2 = src[srcoff + 7]; |
439 pts[offL ] = x1; |
299 if (left != null) { |
440 pts[offL + 1] = y1; |
300 left[leftoff + 0] = x1; |
441 |
301 left[leftoff + 1] = y1; |
442 pts[offR + 6] = x2; |
302 } |
443 pts[offR + 7] = y2; |
303 if (right != null) { |
444 |
304 right[rightoff + 6] = x2; |
445 x1 = x1 + t * (cx1 - x1); |
305 right[rightoff + 7] = y2; |
446 y1 = y1 + t * (cy1 - y1); |
306 } |
447 x2 = cx2 + t * (x2 - cx2); |
307 x1 = x1 + t * (ctrlx1 - x1); |
448 y2 = cy2 + t * (y2 - cy2); |
308 y1 = y1 + t * (ctrly1 - y1); |
449 |
309 x2 = ctrlx2 + t * (x2 - ctrlx2); |
450 double cx = cx1 + t * (cx2 - cx1); |
310 y2 = ctrly2 + t * (y2 - ctrly2); |
451 double cy = cy1 + t * (cy2 - cy1); |
311 double centerx = ctrlx1 + t * (ctrlx2 - ctrlx1); |
452 |
312 double centery = ctrly1 + t * (ctrly2 - ctrly1); |
453 cx1 = x1 + t * (cx - x1); |
313 ctrlx1 = x1 + t * (centerx - x1); |
454 cy1 = y1 + t * (cy - y1); |
314 ctrly1 = y1 + t * (centery - y1); |
455 cx2 = cx + t * (x2 - cx); |
315 ctrlx2 = centerx + t * (x2 - centerx); |
456 cy2 = cy + t * (y2 - cy); |
316 ctrly2 = centery + t * (y2 - centery); |
457 cx = cx1 + t * (cx2 - cx1); |
317 centerx = ctrlx1 + t * (ctrlx2 - ctrlx1); |
458 cy = cy1 + t * (cy2 - cy1); |
318 centery = ctrly1 + t * (ctrly2 - ctrly1); |
459 |
319 if (left != null) { |
460 pts[offL + 2] = x1; |
320 left[leftoff + 2] = x1; |
461 pts[offL + 3] = y1; |
321 left[leftoff + 3] = y1; |
462 pts[offL + 4] = cx1; |
322 left[leftoff + 4] = ctrlx1; |
463 pts[offL + 5] = cy1; |
323 left[leftoff + 5] = ctrly1; |
464 pts[offL + 6] = cx; |
324 left[leftoff + 6] = centerx; |
465 pts[offL + 7] = cy; |
325 left[leftoff + 7] = centery; |
466 |
326 } |
467 pts[offR ] = cx; |
327 if (right != null) { |
468 pts[offR + 1] = cy; |
328 right[rightoff + 0] = centerx; |
469 pts[offR + 2] = cx2; |
329 right[rightoff + 1] = centery; |
470 pts[offR + 3] = cy2; |
330 right[rightoff + 2] = ctrlx2; |
471 pts[offR + 4] = x2; |
331 right[rightoff + 3] = ctrly2; |
472 pts[offR + 5] = y2; |
332 right[rightoff + 4] = x2; |
473 } |
333 right[rightoff + 5] = y2; |
474 |
334 } |
475 static void subdivideQuad(final double[] src, |
335 } |
476 final double[] left, |
336 |
477 final double[] right) |
337 static void subdivideQuad(double[] src, int srcoff, |
478 { |
338 double[] left, int leftoff, |
479 double x1 = src[0]; |
339 double[] right, int rightoff) |
480 double y1 = src[1]; |
340 { |
481 double cx = src[2]; |
341 double x1 = src[srcoff + 0]; |
482 double cy = src[3]; |
342 double y1 = src[srcoff + 1]; |
483 double x2 = src[4]; |
343 double ctrlx = src[srcoff + 2]; |
484 double y2 = src[5]; |
344 double ctrly = src[srcoff + 3]; |
485 |
345 double x2 = src[srcoff + 4]; |
486 left[0] = x1; |
346 double y2 = src[srcoff + 5]; |
487 left[1] = y1; |
347 if (left != null) { |
488 |
348 left[leftoff + 0] = x1; |
489 right[4] = x2; |
349 left[leftoff + 1] = y1; |
490 right[5] = y2; |
350 } |
491 |
351 if (right != null) { |
492 x1 = (x1 + cx) / 2.0d; |
352 right[rightoff + 4] = x2; |
493 y1 = (y1 + cy) / 2.0d; |
353 right[rightoff + 5] = y2; |
494 x2 = (x2 + cx) / 2.0d; |
354 } |
495 y2 = (y2 + cy) / 2.0d; |
355 x1 = (x1 + ctrlx) / 2.0d; |
496 cx = (x1 + x2) / 2.0d; |
356 y1 = (y1 + ctrly) / 2.0d; |
497 cy = (y1 + y2) / 2.0d; |
357 x2 = (x2 + ctrlx) / 2.0d; |
498 |
358 y2 = (y2 + ctrly) / 2.0d; |
499 left[2] = x1; |
359 ctrlx = (x1 + x2) / 2.0d; |
500 left[3] = y1; |
360 ctrly = (y1 + y2) / 2.0d; |
501 left[4] = cx; |
361 if (left != null) { |
502 left[5] = cy; |
362 left[leftoff + 2] = x1; |
503 |
363 left[leftoff + 3] = y1; |
504 right[0] = cx; |
364 left[leftoff + 4] = ctrlx; |
505 right[1] = cy; |
365 left[leftoff + 5] = ctrly; |
506 right[2] = x2; |
366 } |
507 right[3] = y2; |
367 if (right != null) { |
508 } |
368 right[rightoff + 0] = ctrlx; |
509 |
369 right[rightoff + 1] = ctrly; |
510 static void subdivideQuadAt(final double t, |
370 right[rightoff + 2] = x2; |
511 final double[] src, final int offS, |
371 right[rightoff + 3] = y2; |
512 final double[] pts, final int offL, final int offR) |
372 } |
513 { |
373 } |
514 double x1 = src[offS ]; |
374 |
515 double y1 = src[offS + 1]; |
375 static void subdivideQuadAt(double t, double[] src, int srcoff, |
516 double cx = src[offS + 2]; |
376 double[] left, int leftoff, |
517 double cy = src[offS + 3]; |
377 double[] right, int rightoff) |
518 double x2 = src[offS + 4]; |
378 { |
519 double y2 = src[offS + 5]; |
379 double x1 = src[srcoff + 0]; |
520 |
380 double y1 = src[srcoff + 1]; |
521 pts[offL ] = x1; |
381 double ctrlx = src[srcoff + 2]; |
522 pts[offL + 1] = y1; |
382 double ctrly = src[srcoff + 3]; |
523 |
383 double x2 = src[srcoff + 4]; |
524 pts[offR + 4] = x2; |
384 double y2 = src[srcoff + 5]; |
525 pts[offR + 5] = y2; |
385 if (left != null) { |
526 |
386 left[leftoff + 0] = x1; |
527 x1 = x1 + t * (cx - x1); |
387 left[leftoff + 1] = y1; |
528 y1 = y1 + t * (cy - y1); |
388 } |
529 x2 = cx + t * (x2 - cx); |
389 if (right != null) { |
530 y2 = cy + t * (y2 - cy); |
390 right[rightoff + 4] = x2; |
531 cx = x1 + t * (x2 - x1); |
391 right[rightoff + 5] = y2; |
532 cy = y1 + t * (y2 - y1); |
392 } |
533 |
393 x1 = x1 + t * (ctrlx - x1); |
534 pts[offL + 2] = x1; |
394 y1 = y1 + t * (ctrly - y1); |
535 pts[offL + 3] = y1; |
395 x2 = ctrlx + t * (x2 - ctrlx); |
536 pts[offL + 4] = cx; |
396 y2 = ctrly + t * (y2 - ctrly); |
537 pts[offL + 5] = cy; |
397 ctrlx = x1 + t * (x2 - x1); |
538 |
398 ctrly = y1 + t * (y2 - y1); |
539 pts[offR ] = cx; |
399 if (left != null) { |
540 pts[offR + 1] = cy; |
400 left[leftoff + 2] = x1; |
541 pts[offR + 2] = x2; |
401 left[leftoff + 3] = y1; |
542 pts[offR + 3] = y2; |
402 left[leftoff + 4] = ctrlx; |
543 } |
403 left[leftoff + 5] = ctrly; |
544 |
404 } |
545 static void subdivideLineAt(final double t, |
405 if (right != null) { |
546 final double[] src, final int offS, |
406 right[rightoff + 0] = ctrlx; |
547 final double[] pts, final int offL, final int offR) |
407 right[rightoff + 1] = ctrly; |
548 { |
408 right[rightoff + 2] = x2; |
549 double x1 = src[offS ]; |
409 right[rightoff + 3] = y2; |
550 double y1 = src[offS + 1]; |
410 } |
551 double x2 = src[offS + 2]; |
411 } |
552 double y2 = src[offS + 3]; |
412 |
553 |
413 static void subdivideAt(double t, double[] src, int srcoff, |
554 pts[offL ] = x1; |
414 double[] left, int leftoff, |
555 pts[offL + 1] = y1; |
415 double[] right, int rightoff, int size) |
556 |
416 { |
557 pts[offR + 2] = x2; |
417 switch(size) { |
558 pts[offR + 3] = y2; |
418 case 8: |
559 |
419 subdivideCubicAt(t, src, srcoff, left, leftoff, right, rightoff); |
560 x1 = x1 + t * (x2 - x1); |
420 return; |
561 y1 = y1 + t * (y2 - y1); |
421 case 6: |
562 |
422 subdivideQuadAt(t, src, srcoff, left, leftoff, right, rightoff); |
563 pts[offL + 2] = x1; |
423 return; |
564 pts[offL + 3] = y1; |
|
565 |
|
566 pts[offR ] = x1; |
|
567 pts[offR + 1] = y1; |
|
568 } |
|
569 |
|
570 static void subdivideAt(final double t, |
|
571 final double[] src, final int offS, |
|
572 final double[] pts, final int offL, final int type) |
|
573 { |
|
574 // if instead of switch (perf + most probable cases first) |
|
575 if (type == 8) { |
|
576 subdivideCubicAt(t, src, offS, pts, offL, offL + type); |
|
577 } else if (type == 4) { |
|
578 subdivideLineAt(t, src, offS, pts, offL, offL + type); |
|
579 } else { |
|
580 subdivideQuadAt(t, src, offS, pts, offL, offL + type); |
424 } |
581 } |
425 } |
582 } |
426 |
583 |
427 // From sun.java2d.loops.GeneralRenderer: |
584 // From sun.java2d.loops.GeneralRenderer: |
428 |
585 |