History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/dc/DuctusRenderingEngine.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/dc/DuctusRenderingEngine.java+836−0
@@ -0,0 +1,836 @@
1/*
2 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.dc;
27
28import java.awt.Shape;
29import java.awt.BasicStroke;
30import java.awt.geom.Path2D;
31import java.awt.geom.PathIterator;
32import java.awt.geom.AffineTransform;
33
34import sun.awt.geom.PathConsumer2D;
35import sun.java2d.pipe.Region;
36import sun.java2d.pipe.AATileGenerator;
37import sun.java2d.pipe.RenderingEngine;
38
39import sun.dc.pr.Rasterizer;
40import sun.dc.pr.PathStroker;
41import sun.dc.pr.PathDasher;
42import sun.dc.pr.PRException;
43import sun.dc.path.PathConsumer;
44import sun.dc.path.PathException;
45import sun.dc.path.FastPathProducer;
46
47public class DuctusRenderingEngine extends RenderingEngine {
48 static final float PenUnits = 0.01f;
49 static final int MinPenUnits = 100;
50 static final int MinPenUnitsAA = 20;
51 static final float MinPenSizeAA = PenUnits * MinPenUnitsAA;
52
53 static final float UPPER_BND = Float.MAX_VALUE / 2.0f;
54 static final float LOWER_BND = -UPPER_BND;
55
56 private static final int RasterizerCaps[] = {
57 Rasterizer.BUTT, Rasterizer.ROUND, Rasterizer.SQUARE
58 };
59
60 private static final int RasterizerCorners[] = {
61 Rasterizer.MITER, Rasterizer.ROUND, Rasterizer.BEVEL
62 };
63
64 static float[] getTransformMatrix(AffineTransform transform) {
65 float matrix[] = new float[4];
66 double dmatrix[] = new double[6];
67 transform.getMatrix(dmatrix);
68 for (int i = 0; i < 4; i++) {
69 matrix[i] = (float) dmatrix[i];
70 }
71 return matrix;
72 }
73
74 /**
75 * {@inheritDoc}
76 */
77 @Override
78 public Shape createStrokedShape(Shape src,
79 float width,
80 int caps,
81 int join,
82 float miterlimit,
83 float dashes[],
84 float dashphase)
85 {
86 FillAdapter filler = new FillAdapter();
87 PathStroker stroker = new PathStroker(filler);
88 PathDasher dasher = null;
89
90 try {
91 PathConsumer consumer;
92
93 stroker.setPenDiameter(width);
94 stroker.setPenT4(null);
95 stroker.setCaps(RasterizerCaps[caps]);
96 stroker.setCorners(RasterizerCorners[join], miterlimit);
97 if (dashes != null) {
98 dasher = new PathDasher(stroker);
99 dasher.setDash(dashes, dashphase);
100 dasher.setDashT4(null);
101 consumer = dasher;
102 } else {
103 consumer = stroker;
104 }
105
106 feedConsumer(consumer, src.getPathIterator(null));
107 } finally {
108 stroker.dispose();
109 if (dasher != null) {
110 dasher.dispose();
111 }
112 }
113
114 return filler.getShape();
115 }
116
117 /**
118 * {@inheritDoc}
119 */
120 @Override
121 public void strokeTo(Shape src,
122 AffineTransform transform,
123 BasicStroke bs,
124 boolean thin,
125 boolean normalize,
126 boolean antialias,
127 PathConsumer2D sr)
128 {
129 PathStroker stroker = new PathStroker(sr);
130 PathConsumer consumer = stroker;
131
132 float matrix[] = null;
133 if (!thin) {
134 stroker.setPenDiameter(bs.getLineWidth());
135 if (transform != null) {
136 matrix = getTransformMatrix(transform);
137 }
138 stroker.setPenT4(matrix);
139 stroker.setPenFitting(PenUnits, MinPenUnits);
140 }
141 stroker.setCaps(RasterizerCaps[bs.getEndCap()]);
142 stroker.setCorners(RasterizerCorners[bs.getLineJoin()],
143 bs.getMiterLimit());
144 float[] dashes = bs.getDashArray();
145 if (dashes != null) {
146 PathDasher dasher = new PathDasher(stroker);
147 dasher.setDash(dashes, bs.getDashPhase());
148 if (transform != null && matrix == null) {
149 matrix = getTransformMatrix(transform);
150 }
151 dasher.setDashT4(matrix);
152 consumer = dasher;
153 }
154
155 try {
156 PathIterator pi = src.getPathIterator(transform);
157
158 feedConsumer(pi, consumer, normalize, 0.25f);
159 } catch (PathException e) {
160 throw new InternalError("Unable to Stroke shape ("+
161 e.getMessage()+")");
162 } finally {
163 while (consumer != null && consumer != sr) {
164 PathConsumer next = consumer.getConsumer();
165 consumer.dispose();
166 consumer = next;
167 }
168 }
169 }
170
171 /*
172 * Feed a path from a PathIterator to a Ductus PathConsumer.
173 */
174 public static void feedConsumer(PathIterator pi, PathConsumer consumer,
175 boolean normalize, float norm)
176 throws PathException
177 {
178 consumer.beginPath();
179 boolean pathClosed = false;
180 boolean skip = false;
181 boolean subpathStarted = false;
182 float mx = 0.0f;
183 float my = 0.0f;
184 float point[] = new float[6];
185 float rnd = (0.5f - norm);
186 float ax = 0.0f;
187 float ay = 0.0f;
188
189 while (!pi.isDone()) {
190 int type = pi.currentSegment(point);
191 if (pathClosed == true) {
192 pathClosed = false;
193 if (type != PathIterator.SEG_MOVETO) {
194 // Force current point back to last moveto point
195 consumer.beginSubpath(mx, my);
196 subpathStarted = true;
197 }
198 }
199 if (normalize) {
200 int index;
201 switch (type) {
202 case PathIterator.SEG_CUBICTO:
203 index = 4;
204 break;
205 case PathIterator.SEG_QUADTO:
206 index = 2;
207 break;
208 case PathIterator.SEG_MOVETO:
209 case PathIterator.SEG_LINETO:
210 index = 0;
211 break;
212 case PathIterator.SEG_CLOSE:
213 default:
214 index = -1;
215 break;
216 }
217 if (index >= 0) {
218 float ox = point[index];
219 float oy = point[index+1];
220 float newax = (float) Math.floor(ox + rnd) + norm;
221 float neway = (float) Math.floor(oy + rnd) + norm;
222 point[index] = newax;
223 point[index+1] = neway;
224 newax -= ox;
225 neway -= oy;
226 switch (type) {
227 case PathIterator.SEG_CUBICTO:
228 point[0] += ax;
229 point[1] += ay;
230 point[2] += newax;
231 point[3] += neway;
232 break;
233 case PathIterator.SEG_QUADTO:
234 point[0] += (newax + ax) / 2;
235 point[1] += (neway + ay) / 2;
236 break;
237 case PathIterator.SEG_MOVETO:
238 case PathIterator.SEG_LINETO:
239 case PathIterator.SEG_CLOSE:
240 break;
241 }
242 ax = newax;
243 ay = neway;
244 }
245 }
246 switch (type) {
247 case PathIterator.SEG_MOVETO:
248
249 /* Checking SEG_MOVETO coordinates if they are out of the
250 * [LOWER_BND, UPPER_BND] range. This check also handles NaN
251 * and Infinity values. Skipping next path segment in case of
252 * invalid data.
253 */
254 if (point[0] < UPPER_BND && point[0] > LOWER_BND &&
255 point[1] < UPPER_BND && point[1] > LOWER_BND)
256 {
257 mx = point[0];
258 my = point[1];
259 consumer.beginSubpath(mx, my);
260 subpathStarted = true;
261 skip = false;
262 } else {
263 skip = true;
264 }
265 break;
266 case PathIterator.SEG_LINETO:
267 /* Checking SEG_LINETO coordinates if they are out of the
268 * [LOWER_BND, UPPER_BND] range. This check also handles NaN
269 * and Infinity values. Ignoring current path segment in case
270 * of invalid data. If segment is skipped its endpoint
271 * (if valid) is used to begin new subpath.
272 */
273 if (point[0] < UPPER_BND && point[0] > LOWER_BND &&
274 point[1] < UPPER_BND && point[1] > LOWER_BND)
275 {
276 if (skip) {
277 consumer.beginSubpath(point[0], point[1]);
278 subpathStarted = true;
279 skip = false;
280 } else {
281 consumer.appendLine(point[0], point[1]);
282 }
283 }
284 break;
285 case PathIterator.SEG_QUADTO:
286 // Quadratic curves take two points
287
288 /* Checking SEG_QUADTO coordinates if they are out of the
289 * [LOWER_BND, UPPER_BND] range. This check also handles NaN
290 * and Infinity values. Ignoring current path segment in case
291 * of invalid endpoints's data. Equivalent to the SEG_LINETO
292 * if endpoint coordinates are valid but there are invalid data
293 * amoung other coordinates
294 */
295 if (point[2] < UPPER_BND && point[2] > LOWER_BND &&
296 point[3] < UPPER_BND && point[3] > LOWER_BND)
297 {
298 if (skip) {
299 consumer.beginSubpath(point[2], point[3]);
300 subpathStarted = true;
301 skip = false;
302 } else {
303 if (point[0] < UPPER_BND && point[0] > LOWER_BND &&
304 point[1] < UPPER_BND && point[1] > LOWER_BND)
305 {
306 consumer.appendQuadratic(point[0], point[1],
307 point[2], point[3]);
308 } else {
309 consumer.appendLine(point[2], point[3]);
310 }
311 }
312 }
313 break;
314 case PathIterator.SEG_CUBICTO:
315 // Cubic curves take three points
316
317 /* Checking SEG_CUBICTO coordinates if they are out of the
318 * [LOWER_BND, UPPER_BND] range. This check also handles NaN
319 * and Infinity values. Ignoring current path segment in case
320 * of invalid endpoints's data. Equivalent to the SEG_LINETO
321 * if endpoint coordinates are valid but there are invalid data
322 * amoung other coordinates
323 */
324 if (point[4] < UPPER_BND && point[4] > LOWER_BND &&
325 point[5] < UPPER_BND && point[5] > LOWER_BND)
326 {
327 if (skip) {
328 consumer.beginSubpath(point[4], point[5]);
329 subpathStarted = true;
330 skip = false;
331 } else {
332 if (point[0] < UPPER_BND && point[0] > LOWER_BND &&
333 point[1] < UPPER_BND && point[1] > LOWER_BND &&
334 point[2] < UPPER_BND && point[2] > LOWER_BND &&
335 point[3] < UPPER_BND && point[3] > LOWER_BND)
336 {
337 consumer.appendCubic(point[0], point[1],
338 point[2], point[3],
339 point[4], point[5]);
340 } else {
341 consumer.appendLine(point[4], point[5]);
342 }
343 }
344 }
345 break;
346 case PathIterator.SEG_CLOSE:
347 if (subpathStarted) {
348 consumer.closedSubpath();
349 subpathStarted = false;
350 pathClosed = true;
351 }
352 break;
353 }
354 pi.next();
355 }
356
357 consumer.endPath();
358 }
359
360 private static Rasterizer theRasterizer;
361
362 public synchronized static Rasterizer getRasterizer() {
363 Rasterizer r = theRasterizer;
364 if (r == null) {
365 r = new Rasterizer();
366 } else {
367 theRasterizer = null;
368 }
369 return r;
370 }
371
372 public synchronized static void dropRasterizer(Rasterizer r) {
373 r.reset();
374 theRasterizer = r;
375 }
376
377 /**
378 * {@inheritDoc}
379 */
380 @Override
381 public float getMinimumAAPenSize() {
382 return MinPenSizeAA;
383 }
384
385 /**
386 * {@inheritDoc}
387 */
388 @Override
389 public AATileGenerator getAATileGenerator(Shape s,
390 AffineTransform at,
391 Region clip,
392 BasicStroke bs,
393 boolean thin,
394 boolean normalize,
395 int bbox[])
396 {
397 Rasterizer r = getRasterizer();
398 PathIterator pi = s.getPathIterator(at);
399
400 if (bs != null) {
401 float matrix[] = null;
402 r.setUsage(Rasterizer.STROKE);
403 if (thin) {
404 r.setPenDiameter(MinPenSizeAA);
405 } else {
406 r.setPenDiameter(bs.getLineWidth());
407 if (at != null) {
408 matrix = getTransformMatrix(at);
409 r.setPenT4(matrix);
410 }
411 r.setPenFitting(PenUnits, MinPenUnitsAA);
412 }
413 r.setCaps(RasterizerCaps[bs.getEndCap()]);
414 r.setCorners(RasterizerCorners[bs.getLineJoin()],
415 bs.getMiterLimit());
416 float[] dashes = bs.getDashArray();
417 if (dashes != null) {
418 r.setDash(dashes, bs.getDashPhase());
419 if (at != null && matrix == null) {
420 matrix = getTransformMatrix(at);
421 }
422 r.setDashT4(matrix);
423 }
424 } else {
425 r.setUsage(pi.getWindingRule() == PathIterator.WIND_EVEN_ODD
426 ? Rasterizer.EOFILL
427 : Rasterizer.NZFILL);
428 }
429
430 r.beginPath();
431 {
432 boolean pathClosed = false;
433 boolean skip = false;
434 boolean subpathStarted = false;
435 float mx = 0.0f;
436 float my = 0.0f;
437 float point[] = new float[6];
438 float ax = 0.0f;
439 float ay = 0.0f;
440
441 while (!pi.isDone()) {
442 int type = pi.currentSegment(point);
443 if (pathClosed == true) {
444 pathClosed = false;
445 if (type != PathIterator.SEG_MOVETO) {
446 // Force current point back to last moveto point
447 r.beginSubpath(mx, my);
448 subpathStarted = true;
449 }
450 }
451 if (normalize) {
452 int index;
453 switch (type) {
454 case PathIterator.SEG_CUBICTO:
455 index = 4;
456 break;
457 case PathIterator.SEG_QUADTO:
458 index = 2;
459 break;
460 case PathIterator.SEG_MOVETO:
461 case PathIterator.SEG_LINETO:
462 index = 0;
463 break;
464 case PathIterator.SEG_CLOSE:
465 default:
466 index = -1;
467 break;
468 }
469 if (index >= 0) {
470 float ox = point[index];
471 float oy = point[index+1];
472 float newax = (float) Math.floor(ox) + 0.5f;
473 float neway = (float) Math.floor(oy) + 0.5f;
474 point[index] = newax;
475 point[index+1] = neway;
476 newax -= ox;
477 neway -= oy;
478 switch (type) {
479 case PathIterator.SEG_CUBICTO:
480 point[0] += ax;
481 point[1] += ay;
482 point[2] += newax;
483 point[3] += neway;
484 break;
485 case PathIterator.SEG_QUADTO:
486 point[0] += (newax + ax) / 2;
487 point[1] += (neway + ay) / 2;
488 break;
489 case PathIterator.SEG_MOVETO:
490 case PathIterator.SEG_LINETO:
491 case PathIterator.SEG_CLOSE:
492 break;
493 }
494 ax = newax;
495 ay = neway;
496 }
497 }
498 switch (type) {
499 case PathIterator.SEG_MOVETO:
500
501 /* Checking SEG_MOVETO coordinates if they are out of the
502 * [LOWER_BND, UPPER_BND] range. This check also handles NaN
503 * and Infinity values. Skipping next path segment in case
504 * of invalid data.
505 */
506
507 if (point[0] < UPPER_BND && point[0] > LOWER_BND &&
508 point[1] < UPPER_BND && point[1] > LOWER_BND)
509 {
510 mx = point[0];
511 my = point[1];
512 r.beginSubpath(mx, my);
513 subpathStarted = true;
514 skip = false;
515 } else {
516 skip = true;
517 }
518 break;
519
520 case PathIterator.SEG_LINETO:
521 /* Checking SEG_LINETO coordinates if they are out of the
522 * [LOWER_BND, UPPER_BND] range. This check also handles
523 * NaN and Infinity values. Ignoring current path segment
524 * in case of invalid data. If segment is skipped its
525 * endpoint (if valid) is used to begin new subpath.
526 */
527 if (point[0] < UPPER_BND && point[0] > LOWER_BND &&
528 point[1] < UPPER_BND && point[1] > LOWER_BND)
529 {
530 if (skip) {
531 r.beginSubpath(point[0], point[1]);
532 subpathStarted = true;
533 skip = false;
534 } else {
535 r.appendLine(point[0], point[1]);
536 }
537 }
538 break;
539
540 case PathIterator.SEG_QUADTO:
541 // Quadratic curves take two points
542
543 /* Checking SEG_QUADTO coordinates if they are out of the
544 * [LOWER_BND, UPPER_BND] range. This check also handles
545 * NaN and Infinity values. Ignoring current path segment
546 * in case of invalid endpoints's data. Equivalent to the
547 * SEG_LINETO if endpoint coordinates are valid but there
548 * are invalid data amoung other coordinates
549 */
550 if (point[2] < UPPER_BND && point[2] > LOWER_BND &&
551 point[3] < UPPER_BND && point[3] > LOWER_BND)
552 {
553 if (skip) {
554 r.beginSubpath(point[2], point[3]);
555 subpathStarted = true;
556 skip = false;
557 } else {
558 if (point[0] < UPPER_BND && point[0] > LOWER_BND &&
559 point[1] < UPPER_BND && point[1] > LOWER_BND)
560 {
561 r.appendQuadratic(point[0], point[1],
562 point[2], point[3]);
563 } else {
564 r.appendLine(point[2], point[3]);
565 }
566 }
567 }
568 break;
569 case PathIterator.SEG_CUBICTO:
570 // Cubic curves take three points
571
572 /* Checking SEG_CUBICTO coordinates if they are out of the
573 * [LOWER_BND, UPPER_BND] range. This check also handles
574 * NaN and Infinity values. Ignoring current path segment
575 * in case of invalid endpoints's data. Equivalent to the
576 * SEG_LINETO if endpoint coordinates are valid but there
577 * are invalid data amoung other coordinates
578 */
579
580 if (point[4] < UPPER_BND && point[4] > LOWER_BND &&
581 point[5] < UPPER_BND && point[5] > LOWER_BND)
582 {
583 if (skip) {
584 r.beginSubpath(point[4], point[5]);
585 subpathStarted = true;
586 skip = false;
587 } else {
588 if (point[0] < UPPER_BND && point[0] > LOWER_BND &&
589 point[1] < UPPER_BND && point[1] > LOWER_BND &&
590 point[2] < UPPER_BND && point[2] > LOWER_BND &&
591 point[3] < UPPER_BND && point[3] > LOWER_BND)
592 {
593 r.appendCubic(point[0], point[1],
594 point[2], point[3],
595 point[4], point[5]);
596 } else {
597 r.appendLine(point[4], point[5]);
598 }
599 }
600 }
601 break;
602 case PathIterator.SEG_CLOSE:
603 if (subpathStarted) {
604 r.closedSubpath();
605 subpathStarted = false;
606 pathClosed = true;
607 }
608 break;
609 }
610 pi.next();
611 }
612 }
613
614 try {
615 r.endPath();
616 r.getAlphaBox(bbox);
617 clip.clipBoxToBounds(bbox);
618 if (bbox[0] >= bbox[2] || bbox[1] >= bbox[3]) {
619 dropRasterizer(r);
620 return null;
621 }
622 r.setOutputArea(bbox[0], bbox[1],
623 bbox[2] - bbox[0],
624 bbox[3] - bbox[1]);
625 } catch (PRException e) {
626 /*
627 * This exeption is thrown from the native part of the Ductus
628 * (only in case of a debug build) to indicate that some
629 * segments of the path have very large coordinates.
630 * See 4485298 for more info.
631 */
632 System.err.println("DuctusRenderingEngine.getAATileGenerator: "+e);
633 }
634
635 return r;
636 }
637
638 /**
639 * {@inheritDoc}
640 */
641 @Override
642 public AATileGenerator getAATileGenerator(double x, double y,
643 double dx1, double dy1,
644 double dx2, double dy2,
645 double lw1, double lw2,
646 Region clip,
647 int bbox[])
648 {
649 // REMIND: Deal with large coordinates!
650 double ldx1, ldy1, ldx2, ldy2;
651 boolean innerpgram = (lw1 > 0 && lw2 > 0);
652
653 if (innerpgram) {
654 ldx1 = dx1 * lw1;
655 ldy1 = dy1 * lw1;
656 ldx2 = dx2 * lw2;
657 ldy2 = dy2 * lw2;
658 x -= (ldx1 + ldx2) / 2.0;
659 y -= (ldy1 + ldy2) / 2.0;
660 dx1 += ldx1;
661 dy1 += ldy1;
662 dx2 += ldx2;
663 dy2 += ldy2;
664 if (lw1 > 1 && lw2 > 1) {
665 // Inner parallelogram was entirely consumed by stroke...
666 innerpgram = false;
667 }
668 } else {
669 ldx1 = ldy1 = ldx2 = ldy2 = 0;
670 }
671
672 Rasterizer r = getRasterizer();
673
674 r.setUsage(Rasterizer.EOFILL);
675
676 r.beginPath();
677 r.beginSubpath((float) x, (float) y);
678 r.appendLine((float) (x+dx1), (float) (y+dy1));
679 r.appendLine((float) (x+dx1+dx2), (float) (y+dy1+dy2));
680 r.appendLine((float) (x+dx2), (float) (y+dy2));
681 r.closedSubpath();
682 if (innerpgram) {
683 x += ldx1 + ldx2;
684 y += ldy1 + ldy2;
685 dx1 -= 2.0 * ldx1;
686 dy1 -= 2.0 * ldy1;
687 dx2 -= 2.0 * ldx2;
688 dy2 -= 2.0 * ldy2;
689 r.beginSubpath((float) x, (float) y);
690 r.appendLine((float) (x+dx1), (float) (y+dy1));
691 r.appendLine((float) (x+dx1+dx2), (float) (y+dy1+dy2));
692 r.appendLine((float) (x+dx2), (float) (y+dy2));
693 r.closedSubpath();
694 }
695
696 try {
697 r.endPath();
698 r.getAlphaBox(bbox);
699 clip.clipBoxToBounds(bbox);
700 if (bbox[0] >= bbox[2] || bbox[1] >= bbox[3]) {
701 dropRasterizer(r);
702 return null;
703 }
704 r.setOutputArea(bbox[0], bbox[1],
705 bbox[2] - bbox[0],
706 bbox[3] - bbox[1]);
707 } catch (PRException e) {
708 /*
709 * This exeption is thrown from the native part of the Ductus
710 * (only in case of a debug build) to indicate that some
711 * segments of the path have very large coordinates.
712 * See 4485298 for more info.
713 */
714 System.err.println("DuctusRenderingEngine.getAATileGenerator: "+e);
715 }
716
717 return r;
718 }
719
720 private void feedConsumer(PathConsumer consumer, PathIterator pi) {
721 try {
722 consumer.beginPath();
723 boolean pathClosed = false;
724 float mx = 0.0f;
725 float my = 0.0f;
726 float point[] = new float[6];
727
728 while (!pi.isDone()) {
729 int type = pi.currentSegment(point);
730 if (pathClosed == true) {
731 pathClosed = false;
732 if (type != PathIterator.SEG_MOVETO) {
733 // Force current point back to last moveto point
734 consumer.beginSubpath(mx, my);
735 }
736 }
737 switch (type) {
738 case PathIterator.SEG_MOVETO:
739 mx = point[0];
740 my = point[1];
741 consumer.beginSubpath(point[0], point[1]);
742 break;
743 case PathIterator.SEG_LINETO:
744 consumer.appendLine(point[0], point[1]);
745 break;
746 case PathIterator.SEG_QUADTO:
747 consumer.appendQuadratic(point[0], point[1],
748 point[2], point[3]);
749 break;
750 case PathIterator.SEG_CUBICTO:
751 consumer.appendCubic(point[0], point[1],
752 point[2], point[3],
753 point[4], point[5]);
754 break;
755 case PathIterator.SEG_CLOSE:
756 consumer.closedSubpath();
757 pathClosed = true;
758 break;
759 }
760 pi.next();
761 }
762
763 consumer.endPath();
764 } catch (PathException e) {
765 throw new InternalError("Unable to Stroke shape ("+
766 e.getMessage()+")");
767 }
768 }
769
770 private class FillAdapter implements PathConsumer {
771 boolean closed;
772 Path2D.Float path;
773
774 public FillAdapter() {
775 // Ductus only supplies float coordinates so
776 // Path2D.Double is not necessary here.
777 path = new Path2D.Float(Path2D.WIND_NON_ZERO);
778 }
779
780 public Shape getShape() {
781 return path;
782 }
783
784 public void dispose() {
785 }
786
787 public PathConsumer getConsumer() {
788 return null;
789 }
790
791 public void beginPath() {}
792
793 public void beginSubpath(float x0, float y0) {
794 if (closed) {
795 path.closePath();
796 closed = false;
797 }
798 path.moveTo(x0, y0);
799 }
800
801 public void appendLine(float x1, float y1) {
802 path.lineTo(x1, y1);
803 }
804
805 public void appendQuadratic(float xm, float ym, float x1, float y1) {
806 path.quadTo(xm, ym, x1, y1);
807 }
808
809 public void appendCubic(float xm, float ym,
810 float xn, float yn,
811 float x1, float y1) {
812 path.curveTo(xm, ym, xn, yn, x1, y1);
813 }
814
815 public void closedSubpath() {
816 closed = true;
817 }
818
819 public void endPath() {
820 if (closed) {
821 path.closePath();
822 closed = false;
823 }
824 }
825
826 public void useProxy(FastPathProducer proxy)
827 throws PathException
828 {
829 proxy.sendTo(this);
830 }
831
832 public long getCPathConsumer() {
833 return 0;
834 }
835 }
836}