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+
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()+")");
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+}