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; 70 public static final long OFF_BUMP_ERR = OFF_BUMP_X + SIZE_INT; 71 public static final long OFF_NEXT = OFF_BUMP_ERR + SIZE_INT; 72 public static final long OFF_YMAX = OFF_NEXT + SIZE_INT; 73 74 // size of one edge in bytes 75 public static final int SIZEOF_EDGE_BYTES = (int)(OFF_YMAX + SIZE_INT); 76 77 // curve break into lines 78 // cubic error in subpixels to decrement step 79 private static final float CUB_DEC_ERR_SUBPIX 80 = MarlinProperties.getCubicDecD2() * (NORM_SUBPIXELS / 8.0f); // 1 pixel 81 // cubic error in subpixels to increment step 82 private static final float CUB_INC_ERR_SUBPIX 83 = MarlinProperties.getCubicIncD1() * (NORM_SUBPIXELS / 8.0f); // 0.4 pixel 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.5f / SUBPIXEL_SCALE_X; 51 static final float RDR_OFFSET_Y = 0.5f / 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 // 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; 70 public static final long OFF_BUMP_ERR = OFF_BUMP_X + SIZE_INT; 71 public static final long OFF_NEXT = OFF_BUMP_ERR + SIZE_INT; 72 public static final long OFF_YMAX = OFF_NEXT + SIZE_INT; 73 74 // size of one edge in bytes 75 public static final int SIZEOF_EDGE_BYTES = (int)(OFF_YMAX + SIZE_INT); 76 77 // curve break into lines 78 // cubic error in subpixels to decrement step 79 private static final float CUB_DEC_ERR_SUBPIX 80 = MarlinProperties.getCubicDecD2() * (NORM_SUBPIXELS / 8.0f); // 1 pixel 81 // cubic error in subpixels to increment step 82 private static final float CUB_INC_ERR_SUBPIX 83 = MarlinProperties.getCubicIncD1() * (NORM_SUBPIXELS / 8.0f); // 0.4 pixel 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(final float pix_x0, final 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(final float pix_x1, final 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(final float pix_x1, final float pix_y1, 696 final float pix_x2, final float pix_y2, 697 final float pix_x3, final float pix_y3) 698 { 699 final float xe = tosubpixx(pix_x3); 700 final float ye = tosubpixy(pix_y3); 701 curve.set(x0, y0, tosubpixx(pix_x1), tosubpixy(pix_y1), 702 tosubpixx(pix_x2), tosubpixy(pix_y2), xe, ye); 703 curveBreakIntoLinesAndAdd(x0, y0, curve, xe, ye); 704 x0 = xe; 705 y0 = ye; 706 } 707 708 @Override 709 public void quadTo(final float pix_x1, final float pix_y1, 710 final float pix_x2, final float pix_y2) 711 { 712 final float xe = tosubpixx(pix_x2); 713 final float ye = tosubpixy(pix_y2); 714 curve.set(x0, y0, tosubpixx(pix_x1), tosubpixy(pix_y1), xe, ye); 715 quadBreakIntoLinesAndAdd(x0, y0, curve, xe, ye); 716 x0 = xe; 717 y0 = ye; 718 } 719 720 @Override 721 public void closePath() { 722 if (x0 != sx0 || y0 != sy0) { 723 addLine(x0, y0, sx0, sy0); 724 x0 = sx0; 725 y0 = sy0; 726 } 727 } 728 729 @Override 730 public void pathDone() { 731 closePath(); 732 } 733 734 @Override 735 public long getNativeConsumer() { 736 throw new InternalError("Renderer does not use a native consumer."); 737 } 738 739 private void _endRendering(final int ymin, final int ymax) { 740 if (DISABLE_RENDER) { 741 return; 742 } 743 744 // Get X bounds as true pixel boundaries to compute correct pixel coverage: 745 final int bboxx0 = bbox_spminX; 746 final int bboxx1 = bbox_spmaxX; |