Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/dc/DuctusRenderingEngine.java
38829 views
1
/*
2
* Copyright (c) 2007, 2013, 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
26
package sun.dc;
27
28
import java.awt.Shape;
29
import java.awt.BasicStroke;
30
import java.awt.geom.Path2D;
31
import java.awt.geom.PathIterator;
32
import java.awt.geom.AffineTransform;
33
34
import sun.awt.geom.PathConsumer2D;
35
import sun.java2d.pipe.Region;
36
import sun.java2d.pipe.AATileGenerator;
37
import sun.java2d.pipe.RenderingEngine;
38
39
import sun.dc.pr.Rasterizer;
40
import sun.dc.pr.PathStroker;
41
import sun.dc.pr.PathDasher;
42
import sun.dc.pr.PRException;
43
import sun.dc.path.PathConsumer;
44
import sun.dc.path.PathException;
45
import sun.dc.path.FastPathProducer;
46
47
public 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()+")", e);
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
* among 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
* among 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 among 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 among 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()+")", e);
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
}
837
838