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