30 import jdk.internal.misc.Unsafe; 31 32 final class Renderer implements PathConsumer2D, MarlinRenderer { 33 34 static final boolean DISABLE_RENDER = false; 35 36 static final boolean ENABLE_BLOCK_FLAGS = MarlinProperties.isUseTileFlags(); 37 static final boolean ENABLE_BLOCK_FLAGS_HEURISTICS = MarlinProperties.isUseTileFlagsWithHeuristics(); 38 39 private static final int ALL_BUT_LSB = 0xFFFFFFFE; 40 private static final int ERR_STEP_MAX = 0x7FFFFFFF; // = 2^31 - 1 41 42 private static final double POWER_2_TO_32 = 0x1.0p32d; 43 44 // use float to make tosubpix methods faster (no int to float conversion) 45 static final float SUBPIXEL_SCALE_X = (float) SUBPIXEL_POSITIONS_X; 46 static final float SUBPIXEL_SCALE_Y = (float) SUBPIXEL_POSITIONS_Y; 47 static final int SUBPIXEL_MASK_X = SUBPIXEL_POSITIONS_X - 1; 48 static final int SUBPIXEL_MASK_Y = SUBPIXEL_POSITIONS_Y - 1; 49 50 // number of subpixels corresponding to a tile line 51 private static final int SUBPIXEL_TILE 52 = TILE_H << SUBPIXEL_LG_POSITIONS_Y; 53 54 // 2048 (pixelSize) pixels (height) x 8 subpixels = 64K 55 static final int INITIAL_BUCKET_ARRAY 56 = INITIAL_PIXEL_DIM * SUBPIXEL_POSITIONS_Y; 57 58 // crossing capacity = edges count / 4 ~ 1024 59 static final int INITIAL_CROSSING_COUNT = INITIAL_EDGES_COUNT >> 2; 60 61 public static final int WIND_EVEN_ODD = 0; 62 public static final int WIND_NON_ZERO = 1; 63 64 // common to all types of input path segments. 65 // OFFSET as bytes 66 // only integer values: 67 public static final long OFF_CURX_OR = 0; 68 public static final long OFF_ERROR = OFF_CURX_OR + SIZE_INT; 69 public static final long OFF_BUMP_X = OFF_ERROR + SIZE_INT; 655 // Force zero-fill dirty arrays: 656 edges.fill(BYTE_0); 657 } 658 if (DO_MONITORS) { 659 rdrCtx.stats.mon_rdr_endRendering.stop(); 660 } 661 // recycle the RendererContext instance 662 MarlinRenderingEngine.returnRendererContext(rdrCtx); 663 } 664 665 private static float tosubpixx(final float pix_x) { 666 return SUBPIXEL_SCALE_X * pix_x; 667 } 668 669 private static float tosubpixy(final float pix_y) { 670 // shift y by -0.5 for fast ceil(y - 0.5): 671 return SUBPIXEL_SCALE_Y * pix_y - 0.5f; 672 } 673 674 @Override 675 public void moveTo(float pix_x0, float pix_y0) { 676 closePath(); 677 final float sx = tosubpixx(pix_x0); 678 final float sy = tosubpixy(pix_y0); 679 this.sx0 = sx; 680 this.sy0 = sy; 681 this.x0 = sx; 682 this.y0 = sy; 683 } 684 685 @Override 686 public void lineTo(float pix_x1, float pix_y1) { 687 final float x1 = tosubpixx(pix_x1); 688 final float y1 = tosubpixy(pix_y1); 689 addLine(x0, y0, x1, y1); 690 x0 = x1; 691 y0 = y1; 692 } 693 694 @Override 695 public void curveTo(float x1, float y1, 696 float x2, float y2, 697 float x3, float y3) 698 { 699 final float xe = tosubpixx(x3); 700 final float ye = tosubpixy(y3); 701 curve.set(x0, y0, tosubpixx(x1), tosubpixy(y1), 702 tosubpixx(x2), tosubpixy(y2), xe, ye); 703 curveBreakIntoLinesAndAdd(x0, y0, curve, xe, ye); 704 x0 = xe; 705 y0 = ye; 706 } 707 708 @Override 709 public void quadTo(float x1, float y1, float x2, float y2) { 710 final float xe = tosubpixx(x2); 711 final float ye = tosubpixy(y2); 712 curve.set(x0, y0, tosubpixx(x1), tosubpixy(y1), xe, ye); 713 quadBreakIntoLinesAndAdd(x0, y0, curve, xe, ye); 714 x0 = xe; 715 y0 = ye; 716 } 717 718 @Override 719 public void closePath() { 720 addLine(x0, y0, sx0, sy0); 721 x0 = sx0; 722 y0 = sy0; 723 } 724 725 @Override 726 public void pathDone() { 727 closePath(); 728 } 729 730 @Override 731 public long getNativeConsumer() { 732 throw new InternalError("Renderer does not use a native consumer."); 733 } 734 735 private void _endRendering(final int ymin, final int ymax) { 736 if (DISABLE_RENDER) { 737 return; 738 } 739 740 // Get X bounds as true pixel boundaries to compute correct pixel coverage: 741 final int bboxx0 = bbox_spminX; 742 final int bboxx1 = bbox_spmaxX; | 30 import jdk.internal.misc.Unsafe; 31 32 final class Renderer implements PathConsumer2D, MarlinRenderer { 33 34 static final boolean DISABLE_RENDER = false; 35 36 static final boolean ENABLE_BLOCK_FLAGS = MarlinProperties.isUseTileFlags(); 37 static final boolean ENABLE_BLOCK_FLAGS_HEURISTICS = MarlinProperties.isUseTileFlagsWithHeuristics(); 38 39 private static final int ALL_BUT_LSB = 0xFFFFFFFE; 40 private static final int ERR_STEP_MAX = 0x7FFFFFFF; // = 2^31 - 1 41 42 private static final double POWER_2_TO_32 = 0x1.0p32d; 43 44 // use float to make tosubpix methods faster (no int to float conversion) 45 static final float SUBPIXEL_SCALE_X = (float) SUBPIXEL_POSITIONS_X; 46 static final float SUBPIXEL_SCALE_Y = (float) SUBPIXEL_POSITIONS_Y; 47 static final int SUBPIXEL_MASK_X = SUBPIXEL_POSITIONS_X - 1; 48 static final int SUBPIXEL_MASK_Y = SUBPIXEL_POSITIONS_Y - 1; 49 50 static final float RDR_OFFSET_X = 0.501f / SUBPIXEL_SCALE_X; 51 static final float RDR_OFFSET_Y = 0.501f / SUBPIXEL_SCALE_Y; 52 53 // number of subpixels corresponding to a tile line 54 private static final int SUBPIXEL_TILE 55 = TILE_H << SUBPIXEL_LG_POSITIONS_Y; 56 57 // 2048 (pixelSize) pixels (height) x 8 subpixels = 64K 58 static final int INITIAL_BUCKET_ARRAY 59 = INITIAL_PIXEL_DIM * SUBPIXEL_POSITIONS_Y; 60 61 // crossing capacity = edges count / 4 ~ 1024 62 static final int INITIAL_CROSSING_COUNT = INITIAL_EDGES_COUNT >> 2; 63 64 public static final int WIND_EVEN_ODD = 0; 65 public static final int WIND_NON_ZERO = 1; 66 67 // common to all types of input path segments. 68 // OFFSET as bytes 69 // only integer values: 70 public static final long OFF_CURX_OR = 0; 71 public static final long OFF_ERROR = OFF_CURX_OR + SIZE_INT; 72 public static final long OFF_BUMP_X = OFF_ERROR + SIZE_INT; 658 // Force zero-fill dirty arrays: 659 edges.fill(BYTE_0); 660 } 661 if (DO_MONITORS) { 662 rdrCtx.stats.mon_rdr_endRendering.stop(); 663 } 664 // recycle the RendererContext instance 665 MarlinRenderingEngine.returnRendererContext(rdrCtx); 666 } 667 668 private static float tosubpixx(final float pix_x) { 669 return SUBPIXEL_SCALE_X * pix_x; 670 } 671 672 private static float tosubpixy(final float pix_y) { 673 // shift y by -0.5 for fast ceil(y - 0.5): 674 return SUBPIXEL_SCALE_Y * pix_y - 0.5f; 675 } 676 677 @Override 678 public void moveTo(final float pix_x0, final float pix_y0) { 679 closePath(); 680 final float sx = tosubpixx(pix_x0); 681 final float sy = tosubpixy(pix_y0); 682 this.sx0 = sx; 683 this.sy0 = sy; 684 this.x0 = sx; 685 this.y0 = sy; 686 } 687 688 @Override 689 public void lineTo(final float pix_x1, final float pix_y1) { 690 final float x1 = tosubpixx(pix_x1); 691 final float y1 = tosubpixy(pix_y1); 692 addLine(x0, y0, x1, y1); 693 x0 = x1; 694 y0 = y1; 695 } 696 697 @Override 698 public void curveTo(final float pix_x1, final float pix_y1, 699 final float pix_x2, final float pix_y2, 700 final float pix_x3, final float pix_y3) 701 { 702 final float xe = tosubpixx(pix_x3); 703 final float ye = tosubpixy(pix_y3); 704 curve.set(x0, y0, tosubpixx(pix_x1), tosubpixy(pix_y1), 705 tosubpixx(pix_x2), tosubpixy(pix_y2), xe, ye); 706 curveBreakIntoLinesAndAdd(x0, y0, curve, xe, ye); 707 x0 = xe; 708 y0 = ye; 709 } 710 711 @Override 712 public void quadTo(final float pix_x1, final float pix_y1, 713 final float pix_x2, final float pix_y2) 714 { 715 final float xe = tosubpixx(pix_x2); 716 final float ye = tosubpixy(pix_y2); 717 curve.set(x0, y0, tosubpixx(pix_x1), tosubpixy(pix_y1), xe, ye); 718 quadBreakIntoLinesAndAdd(x0, y0, curve, xe, ye); 719 x0 = xe; 720 y0 = ye; 721 } 722 723 @Override 724 public void closePath() { 725 if (x0 != sx0 || y0 != sy0) { 726 addLine(x0, y0, sx0, sy0); 727 x0 = sx0; 728 y0 = sy0; 729 } 730 } 731 732 @Override 733 public void pathDone() { 734 closePath(); 735 } 736 737 @Override 738 public long getNativeConsumer() { 739 throw new InternalError("Renderer does not use a native consumer."); 740 } 741 742 private void _endRendering(final int ymin, final int ymax) { 743 if (DISABLE_RENDER) { 744 return; 745 } 746 747 // Get X bounds as true pixel boundaries to compute correct pixel coverage: 748 final int bboxx0 = bbox_spminX; 749 final int bboxx1 = bbox_spmaxX; |