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.java2d.marlin;
27
28 import static java.lang.Math.PI;
29 import static java.lang.Math.cos;
30 import static java.lang.Math.sqrt;
31 import static java.lang.Math.cbrt;
32 import static java.lang.Math.acos;
33
34 final class DHelpers implements MarlinConst {
35
36 private DHelpers() {
37 throw new Error("This is a non instantiable class");
38 }
39
40 static boolean within(final double x, final double y, final double err) {
41 final double d = y - x;
42 return (d <= err && d >= -err);
43 }
44
45 static int quadraticRoots(final double a, final double b,
46 final double c, double[] zeroes, final int off)
47 {
48 int ret = off;
49 double t;
50 if (a != 0.0d) {
51 final double dis = b*b - 4*a*c;
52 if (dis > 0.0d) {
154
155 static double evalQuad(final double a, final double b,
156 final double c, final double t)
157 {
158 return t * (t * a + b) + c;
159 }
160
161 // returns the index 1 past the last valid element remaining after filtering
162 static int filterOutNotInAB(double[] nums, final int off, final int len,
163 final double a, final double b)
164 {
165 int ret = off;
166 for (int i = off, end = off + len; i < end; i++) {
167 if (nums[i] >= a && nums[i] < b) {
168 nums[ret++] = nums[i];
169 }
170 }
171 return ret;
172 }
173
174 static double polyLineLength(double[] poly, final int off, final int nCoords) {
175 assert nCoords % 2 == 0 && poly.length >= off + nCoords : "";
176 double acc = 0.0d;
177 for (int i = off + 2; i < off + nCoords; i += 2) {
178 acc += linelen(poly[i], poly[i+1], poly[i-2], poly[i-1]);
179 }
180 return acc;
181 }
182
183 static double linelen(double x1, double y1, double x2, double y2) {
184 final double dx = x2 - x1;
185 final double dy = y2 - y1;
186 return Math.sqrt(dx*dx + dy*dy);
187 }
188
189 static void subdivide(double[] src, int srcoff, double[] left, int leftoff,
190 double[] right, int rightoff, int type)
191 {
192 switch(type) {
193 case 6:
194 DHelpers.subdivideQuad(src, srcoff, left, leftoff, right, rightoff);
195 return;
196 case 8:
197 DHelpers.subdivideCubic(src, srcoff, left, leftoff, right, rightoff);
198 return;
199 default:
200 throw new InternalError("Unsupported curve type");
201 }
202 }
414 }
415 if (right != null) {
416 right[rightoff + 0] = ctrlx;
417 right[rightoff + 1] = ctrly;
418 right[rightoff + 2] = x2;
419 right[rightoff + 3] = y2;
420 }
421 }
422
423 static void subdivideAt(double t, double[] src, int srcoff,
424 double[] left, int leftoff,
425 double[] right, int rightoff, int size)
426 {
427 switch(size) {
428 case 8:
429 subdivideCubicAt(t, src, srcoff, left, leftoff, right, rightoff);
430 return;
431 case 6:
432 subdivideQuadAt(t, src, srcoff, left, leftoff, right, rightoff);
433 return;
434 }
435 }
436 }
|
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.java2d.marlin;
27
28 import static java.lang.Math.PI;
29 import static java.lang.Math.cos;
30 import static java.lang.Math.sqrt;
31 import static java.lang.Math.cbrt;
32 import static java.lang.Math.acos;
33 import java.util.Arrays;
34 import static sun.java2d.marlin.MarlinConst.INITIAL_EDGES_COUNT;
35 import sun.java2d.marlin.stats.Histogram;
36 import sun.java2d.marlin.stats.StatLong;
37
38 final class DHelpers implements MarlinConst {
39
40 private DHelpers() {
41 throw new Error("This is a non instantiable class");
42 }
43
44 static boolean within(final double x, final double y, final double err) {
45 final double d = y - x;
46 return (d <= err && d >= -err);
47 }
48
49 static int quadraticRoots(final double a, final double b,
50 final double c, double[] zeroes, final int off)
51 {
52 int ret = off;
53 double t;
54 if (a != 0.0d) {
55 final double dis = b*b - 4*a*c;
56 if (dis > 0.0d) {
158
159 static double evalQuad(final double a, final double b,
160 final double c, final double t)
161 {
162 return t * (t * a + b) + c;
163 }
164
165 // returns the index 1 past the last valid element remaining after filtering
166 static int filterOutNotInAB(double[] nums, final int off, final int len,
167 final double a, final double b)
168 {
169 int ret = off;
170 for (int i = off, end = off + len; i < end; i++) {
171 if (nums[i] >= a && nums[i] < b) {
172 nums[ret++] = nums[i];
173 }
174 }
175 return ret;
176 }
177
178 static double linelen(double x1, double y1, double x2, double y2) {
179 final double dx = x2 - x1;
180 final double dy = y2 - y1;
181 return Math.sqrt(dx*dx + dy*dy);
182 }
183
184 static void subdivide(double[] src, int srcoff, double[] left, int leftoff,
185 double[] right, int rightoff, int type)
186 {
187 switch(type) {
188 case 6:
189 DHelpers.subdivideQuad(src, srcoff, left, leftoff, right, rightoff);
190 return;
191 case 8:
192 DHelpers.subdivideCubic(src, srcoff, left, leftoff, right, rightoff);
193 return;
194 default:
195 throw new InternalError("Unsupported curve type");
196 }
197 }
409 }
410 if (right != null) {
411 right[rightoff + 0] = ctrlx;
412 right[rightoff + 1] = ctrly;
413 right[rightoff + 2] = x2;
414 right[rightoff + 3] = y2;
415 }
416 }
417
418 static void subdivideAt(double t, double[] src, int srcoff,
419 double[] left, int leftoff,
420 double[] right, int rightoff, int size)
421 {
422 switch(size) {
423 case 8:
424 subdivideCubicAt(t, src, srcoff, left, leftoff, right, rightoff);
425 return;
426 case 6:
427 subdivideQuadAt(t, src, srcoff, left, leftoff, right, rightoff);
428 return;
429 }
430 }
431
432 // From sun.java2d.loops.GeneralRenderer:
433
434 static final int OUTCODE_TOP = 1;
435 static final int OUTCODE_BOTTOM = 2;
436 static final int OUTCODE_LEFT = 4;
437 static final int OUTCODE_RIGHT = 8;
438
439 static int outcode(final double x, final double y,
440 final double[] clipRect)
441 {
442 int code;
443 if (y < clipRect[0]) {
444 code = OUTCODE_TOP;
445 } else if (y >= clipRect[1]) {
446 code = OUTCODE_BOTTOM;
447 } else {
448 code = 0;
449 }
450 if (x < clipRect[2]) {
451 code |= OUTCODE_LEFT;
452 } else if (x >= clipRect[3]) {
453 code |= OUTCODE_RIGHT;
454 }
455 return code;
456 }
457
458 // a stack of polynomial curves where each curve shares endpoints with
459 // adjacent ones.
460 static final class PolyStack {
461 private static final byte TYPE_LINETO = (byte) 0;
462 private static final byte TYPE_QUADTO = (byte) 1;
463 private static final byte TYPE_CUBICTO = (byte) 2;
464
465 // curves capacity = edges count (8192) = edges x 2 (coords)
466 private static final int INITIAL_CURVES_COUNT = INITIAL_EDGES_COUNT << 1;
467
468 // types capacity = edges count (4096)
469 private static final int INITIAL_TYPES_COUNT = INITIAL_EDGES_COUNT;
470
471 double[] curves;
472 int end;
473 byte[] curveTypes;
474 int numCurves;
475
476 // curves ref (dirty)
477 final DoubleArrayCache.Reference curves_ref;
478 // curveTypes ref (dirty)
479 final ByteArrayCache.Reference curveTypes_ref;
480
481 // used marks (stats only)
482 int curveTypesUseMark;
483 int curvesUseMark;
484
485 private final StatLong stat_polystack_types;
486 private final StatLong stat_polystack_curves;
487 private final Histogram hist_polystack_curves;
488 private final StatLong stat_array_polystack_curves;
489 private final StatLong stat_array_polystack_curveTypes;
490
491 PolyStack(final DRendererContext rdrCtx) {
492 this(rdrCtx, null, null, null, null, null);
493 }
494
495 PolyStack(final DRendererContext rdrCtx,
496 final StatLong stat_polystack_types,
497 final StatLong stat_polystack_curves,
498 final Histogram hist_polystack_curves,
499 final StatLong stat_array_polystack_curves,
500 final StatLong stat_array_polystack_curveTypes)
501 {
502 curves_ref = rdrCtx.newDirtyDoubleArrayRef(INITIAL_CURVES_COUNT); // 32K
503 curves = curves_ref.initial;
504
505 curveTypes_ref = rdrCtx.newDirtyByteArrayRef(INITIAL_TYPES_COUNT); // 4K
506 curveTypes = curveTypes_ref.initial;
507 numCurves = 0;
508 end = 0;
509
510 if (DO_STATS) {
511 curveTypesUseMark = 0;
512 curvesUseMark = 0;
513 }
514 this.stat_polystack_types = stat_polystack_types;
515 this.stat_polystack_curves = stat_polystack_curves;
516 this.hist_polystack_curves = hist_polystack_curves;
517 this.stat_array_polystack_curves = stat_array_polystack_curves;
518 this.stat_array_polystack_curveTypes = stat_array_polystack_curveTypes;
519 }
520
521 /**
522 * Disposes this PolyStack:
523 * clean up before reusing this instance
524 */
525 void dispose() {
526 end = 0;
527 numCurves = 0;
528
529 if (DO_STATS) {
530 stat_polystack_types.add(curveTypesUseMark);
531 stat_polystack_curves.add(curvesUseMark);
532 hist_polystack_curves.add(curvesUseMark);
533
534 // reset marks
535 curveTypesUseMark = 0;
536 curvesUseMark = 0;
537 }
538
539 // Return arrays:
540 // curves and curveTypes are kept dirty
541 curves = curves_ref.putArray(curves);
542 curveTypes = curveTypes_ref.putArray(curveTypes);
543 }
544
545 private void ensureSpace(final int n) {
546 // use substraction to avoid integer overflow:
547 if (curves.length - end < n) {
548 if (DO_STATS) {
549 stat_array_polystack_curves.add(end + n);
550 }
551 curves = curves_ref.widenArray(curves, end, end + n);
552 }
553 if (curveTypes.length <= numCurves) {
554 if (DO_STATS) {
555 stat_array_polystack_curveTypes.add(numCurves + 1);
556 }
557 curveTypes = curveTypes_ref.widenArray(curveTypes,
558 numCurves,
559 numCurves + 1);
560 }
561 }
562
563 void pushCubic(double x0, double y0,
564 double x1, double y1,
565 double x2, double y2)
566 {
567 ensureSpace(6);
568 curveTypes[numCurves++] = TYPE_CUBICTO;
569 // we reverse the coordinate order to make popping easier
570 final double[] _curves = curves;
571 int e = end;
572 _curves[e++] = x2; _curves[e++] = y2;
573 _curves[e++] = x1; _curves[e++] = y1;
574 _curves[e++] = x0; _curves[e++] = y0;
575 end = e;
576 }
577
578 void pushQuad(double x0, double y0,
579 double x1, double y1)
580 {
581 ensureSpace(4);
582 curveTypes[numCurves++] = TYPE_QUADTO;
583 final double[] _curves = curves;
584 int e = end;
585 _curves[e++] = x1; _curves[e++] = y1;
586 _curves[e++] = x0; _curves[e++] = y0;
587 end = e;
588 }
589
590 void pushLine(double x, double y) {
591 ensureSpace(2);
592 curveTypes[numCurves++] = TYPE_LINETO;
593 curves[end++] = x; curves[end++] = y;
594 }
595
596 void pullAll(final DPathConsumer2D io) {
597 final int nc = numCurves;
598 if (nc == 0) {
599 return;
600 }
601 if (DO_STATS) {
602 // update used marks:
603 if (numCurves > curveTypesUseMark) {
604 curveTypesUseMark = numCurves;
605 }
606 if (end > curvesUseMark) {
607 curvesUseMark = end;
608 }
609 }
610 final byte[] _curveTypes = curveTypes;
611 final double[] _curves = curves;
612 int e = 0;
613
614 for (int i = 0; i < nc; i++) {
615 switch(_curveTypes[i]) {
616 case TYPE_LINETO:
617 io.lineTo(_curves[e], _curves[e+1]);
618 e += 2;
619 continue;
620 case TYPE_QUADTO:
621 io.quadTo(_curves[e+0], _curves[e+1],
622 _curves[e+2], _curves[e+3]);
623 e += 4;
624 continue;
625 case TYPE_CUBICTO:
626 io.curveTo(_curves[e+0], _curves[e+1],
627 _curves[e+2], _curves[e+3],
628 _curves[e+4], _curves[e+5]);
629 e += 6;
630 continue;
631 default:
632 }
633 }
634 numCurves = 0;
635 end = 0;
636 }
637
638 void popAll(final DPathConsumer2D io) {
639 int nc = numCurves;
640 if (nc == 0) {
641 return;
642 }
643 if (DO_STATS) {
644 // update used marks:
645 if (numCurves > curveTypesUseMark) {
646 curveTypesUseMark = numCurves;
647 }
648 if (end > curvesUseMark) {
649 curvesUseMark = end;
650 }
651 }
652 final byte[] _curveTypes = curveTypes;
653 final double[] _curves = curves;
654 int e = end;
655
656 while (nc != 0) {
657 switch(_curveTypes[--nc]) {
658 case TYPE_LINETO:
659 e -= 2;
660 io.lineTo(_curves[e], _curves[e+1]);
661 continue;
662 case TYPE_QUADTO:
663 e -= 4;
664 io.quadTo(_curves[e+0], _curves[e+1],
665 _curves[e+2], _curves[e+3]);
666 continue;
667 case TYPE_CUBICTO:
668 e -= 6;
669 io.curveTo(_curves[e+0], _curves[e+1],
670 _curves[e+2], _curves[e+3],
671 _curves[e+4], _curves[e+5]);
672 continue;
673 default:
674 }
675 }
676 numCurves = 0;
677 end = 0;
678 }
679
680 @Override
681 public String toString() {
682 String ret = "";
683 int nc = numCurves;
684 int last = end;
685 int len;
686 while (nc != 0) {
687 switch(curveTypes[--nc]) {
688 case TYPE_LINETO:
689 len = 2;
690 ret += "line: ";
691 break;
692 case TYPE_QUADTO:
693 len = 4;
694 ret += "quad: ";
695 break;
696 case TYPE_CUBICTO:
697 len = 6;
698 ret += "cubic: ";
699 break;
700 default:
701 len = 0;
702 }
703 last -= len;
704 ret += Arrays.toString(Arrays.copyOfRange(curves, last, last+len))
705 + "\n";
706 }
707 return ret;
708 }
709 }
710 }
|