46 public static final long OFF_CURX_OR = 0; 47 public static final long OFF_ERROR = OFF_CURX_OR + SIZE_INT; 48 public static final long OFF_BUMP_X = OFF_ERROR + SIZE_INT; 49 public static final long OFF_BUMP_ERR = OFF_BUMP_X + SIZE_INT; 50 public static final long OFF_NEXT = OFF_BUMP_ERR + SIZE_INT; 51 public static final long OFF_YMAX = OFF_NEXT + SIZE_INT; 52 53 // size of one edge in bytes 54 public static final int SIZEOF_EDGE_BYTES = (int)(OFF_YMAX + SIZE_INT); 55 56 // curve break into lines 57 // cubic error in subpixels to decrement step 58 private static final double CUB_DEC_ERR_SUBPIX 59 = MarlinProperties.getCubicDecD2() * (1.0d / 8.0d); // 1 pixel 60 // cubic error in subpixels to increment step 61 private static final double CUB_INC_ERR_SUBPIX 62 = MarlinProperties.getCubicIncD1() * (1.0d / 8.0d); // 0.4 pixel 63 64 // TestNonAARasterization (JDK-8170879): cubics 65 // bad paths (59294/100000 == 59,29%, 94335 bad pixels (avg = 1,59), 3966 warnings (avg = 0,07) 66 67 // cubic bind length to decrement step 68 public static final double CUB_DEC_BND 69 = 8.0d * CUB_DEC_ERR_SUBPIX; 70 // cubic bind length to increment step 71 public static final double CUB_INC_BND 72 = 8.0d * CUB_INC_ERR_SUBPIX; 73 74 // cubic countlg 75 public static final int CUB_COUNT_LG = 2; 76 // cubic count = 2^countlg 77 private static final int CUB_COUNT = 1 << CUB_COUNT_LG; 78 // cubic count^2 = 4^countlg 79 private static final int CUB_COUNT_2 = 1 << (2 * CUB_COUNT_LG); 80 // cubic count^3 = 8^countlg 81 private static final int CUB_COUNT_3 = 1 << (3 * CUB_COUNT_LG); 82 // cubic dt = 1 / count 83 private static final double CUB_INV_COUNT = 1.0d / CUB_COUNT; 84 // cubic dt^2 = 1 / count^2 = 1 / 4^countlg 85 private static final double CUB_INV_COUNT_2 = 1.0d / CUB_COUNT_2; 86 // cubic dt^3 = 1 / count^3 = 1 / 8^countlg 87 private static final double CUB_INV_COUNT_3 = 1.0d / CUB_COUNT_3; 88 89 // quad break into lines 90 // quadratic error in subpixels 91 private static final double QUAD_DEC_ERR_SUBPIX 92 = MarlinProperties.getQuadDecD2() * (1.0d / 8.0d); // 0.5 pixel 93 94 // TestNonAARasterization (JDK-8170879): quads 95 // bad paths (62916/100000 == 62,92%, 103818 bad pixels (avg = 1,65), 6514 warnings (avg = 0,10) 96 97 // quadratic bind length to decrement step 98 public static final double QUAD_DEC_BND 99 = 8.0d * QUAD_DEC_ERR_SUBPIX; 100 101 ////////////////////////////////////////////////////////////////////////////// 102 // SCAN LINE 103 ////////////////////////////////////////////////////////////////////////////// 104 // crossings ie subpixel edge x coordinates 105 private int[] crossings; 106 // auxiliary storage for crossings (merge sort) 107 private int[] aux_crossings; 108 109 // indices into the segment pointer lists. They indicate the "active" 110 // sublist in the segment lists (the portion of the list that contains 111 // all the segments that cross the next scan line). 112 private int edgeCount; 113 private int[] edgePtrs; 114 // auxiliary storage for edge pointers (merge sort) 115 private int[] aux_edgePtrs; 158 final DCurve c, 159 final double x2, final double y2) 160 { 161 int count = 1; // dt = 1 / count 162 163 // maximum(ddX|Y) = norm(dbx, dby) * dt^2 (= 1) 164 double maxDD = Math.abs(c.dbx) + Math.abs(c.dby); 165 166 final double _DEC_BND = QUAD_DEC_BND; 167 168 while (maxDD >= _DEC_BND) { 169 // divide step by half: 170 maxDD /= 4.0d; // error divided by 2^2 = 4 171 172 count <<= 1; 173 if (DO_STATS) { 174 rdrCtx.stats.stat_rdr_quadBreak_dec.add(count); 175 } 176 } 177 178 int nL = 0; // line count 179 if (count > 1) { 180 final double icount = 1.0d / count; // dt 181 final double icount2 = icount * icount; // dt^2 182 183 final double ddx = c.dbx * icount2; 184 final double ddy = c.dby * icount2; 185 double dx = c.bx * icount2 + c.cx * icount; 186 double dy = c.by * icount2 + c.cy * icount; 187 188 double x1, y1; 189 190 while (--count > 0) { 191 x1 = x0 + dx; 192 dx += ddx; 193 y1 = y0 + dy; 194 dy += ddy; 195 196 addLine(x0, y0, x1, y1); 197 198 if (DO_STATS) { nL++; } 199 x0 = x1; 200 y0 = y1; 201 } 202 } 203 addLine(x0, y0, x2, y2); 204 205 if (DO_STATS) { 206 rdrCtx.stats.stat_rdr_quadBreak.add(nL + 1); 207 } 208 } 209 210 // x0, y0 and x3,y3 are the endpoints of the curve. We could compute these 211 // using c.xat(0),c.yat(0) and c.xat(1),c.yat(1), but this might introduce 212 // numerical errors, and our callers already have the exact values. 213 // Another alternative would be to pass all the control points, and call 214 // c.set here, but then too many numbers are passed around. 215 private void curveBreakIntoLinesAndAdd(double x0, double y0, 216 final DCurve c, 217 final double x3, final double y3) 218 { 219 int count = CUB_COUNT; 220 final double icount = CUB_INV_COUNT; // dt 221 final double icount2 = CUB_INV_COUNT_2; // dt^2 222 final double icount3 = CUB_INV_COUNT_3; // dt^3 223 224 // the dx and dy refer to forward differencing variables, not the last 225 // coefficients of the "points" polynomial 226 double dddx, dddy, ddx, ddy, dx, dy; 227 dddx = 2.0d * c.dax * icount3; 228 dddy = 2.0d * c.day * icount3; 229 ddx = dddx + c.dbx * icount2; 230 ddy = dddy + c.dby * icount2; 231 dx = c.ax * icount3 + c.bx * icount2 + c.cx * icount; 232 dy = c.ay * icount3 + c.by * icount2 + c.cy * icount; 233 234 // we use x0, y0 to walk the line 235 double x1 = x0, y1 = y0; 236 int nL = 0; // line count 237 238 final double _DEC_BND = CUB_DEC_BND; 239 final double _INC_BND = CUB_INC_BND; 240 241 while (count > 0) { 242 // divide step by half: 243 while (Math.abs(ddx) + Math.abs(ddy) >= _DEC_BND) { 244 dddx /= 8.0d; 245 dddy /= 8.0d; 246 ddx = ddx / 4.0d - dddx; 247 ddy = ddy / 4.0d - dddy; 248 dx = (dx - ddx) / 2.0d; 249 dy = (dy - ddy) / 2.0d; 250 251 count <<= 1; 252 if (DO_STATS) { 253 rdrCtx.stats.stat_rdr_curveBreak_dec.add(count); 254 } 255 } 256 257 // double step: 258 // can only do this on even "count" values, because we must divide count by 2 259 while (count % 2 == 0 260 && Math.abs(dx) + Math.abs(dy) <= _INC_BND) 261 { 262 dx = 2.0d * dx + ddx; 263 dy = 2.0d * dy + ddy; 264 ddx = 4.0d * (ddx + dddx); 265 ddy = 4.0d * (ddy + dddy); 266 dddx *= 8.0d; 267 dddy *= 8.0d; 268 269 count >>= 1; 270 if (DO_STATS) { 271 rdrCtx.stats.stat_rdr_curveBreak_inc.add(count); 272 } 273 } 274 if (--count > 0) { 275 x1 += dx; 276 dx += ddx; 277 ddx += dddx; 278 y1 += dy; 279 dy += ddy; 280 ddy += dddy; 281 } else { 282 x1 = x3; 283 y1 = y3; 284 } 285 286 addLine(x0, y0, x1, y1); 287 288 if (DO_STATS) { nL++; } 289 x0 = x1; 290 y0 = y1; 291 } 292 if (DO_STATS) { 293 rdrCtx.stats.stat_rdr_curveBreak.add(nL); 294 } 295 } 296 297 private void addLine(double x1, double y1, double x2, double y2) { 298 if (DO_MONITORS) { 299 rdrCtx.stats.mon_rdr_addLine.start(); 300 } 301 if (DO_STATS) { 302 rdrCtx.stats.stat_rdr_addLine.add(1); 303 } 304 int or = 1; // orientation of the line. 1 if y increases, 0 otherwise. 305 if (y2 < y1) { 306 or = 0; 307 double tmp = y2; 308 y2 = y1; 309 y1 = tmp; 310 tmp = x2; 311 x2 = x1; 312 x1 = tmp; 313 } 652 this.x0 = sx; 653 this.y0 = sy; 654 } 655 656 @Override 657 public void lineTo(final double pix_x1, final double pix_y1) { 658 final double x1 = tosubpixx(pix_x1); 659 final double y1 = tosubpixy(pix_y1); 660 addLine(x0, y0, x1, y1); 661 x0 = x1; 662 y0 = y1; 663 } 664 665 @Override 666 public void curveTo(final double pix_x1, final double pix_y1, 667 final double pix_x2, final double pix_y2, 668 final double pix_x3, final double pix_y3) 669 { 670 final double xe = tosubpixx(pix_x3); 671 final double ye = tosubpixy(pix_y3); 672 curve.set(x0, y0, tosubpixx(pix_x1), tosubpixy(pix_y1), 673 tosubpixx(pix_x2), tosubpixy(pix_y2), xe, ye); 674 curveBreakIntoLinesAndAdd(x0, y0, curve, xe, ye); 675 x0 = xe; 676 y0 = ye; 677 } 678 679 @Override 680 public void quadTo(final double pix_x1, final double pix_y1, 681 final double pix_x2, final double pix_y2) 682 { 683 final double xe = tosubpixx(pix_x2); 684 final double ye = tosubpixy(pix_y2); 685 curve.set(x0, y0, tosubpixx(pix_x1), tosubpixy(pix_y1), xe, ye); 686 quadBreakIntoLinesAndAdd(x0, y0, curve, xe, ye); 687 x0 = xe; 688 y0 = ye; 689 } 690 691 @Override 692 public void closePath() { 693 if (x0 != sx0 || y0 != sy0) { 694 addLine(x0, y0, sx0, sy0); 695 x0 = sx0; 696 y0 = sy0; 697 } 698 } 699 700 @Override 701 public void pathDone() { 702 closePath(); 703 704 // call endRendering() to determine the boundaries: 705 endRendering(); | 46 public static final long OFF_CURX_OR = 0; 47 public static final long OFF_ERROR = OFF_CURX_OR + SIZE_INT; 48 public static final long OFF_BUMP_X = OFF_ERROR + SIZE_INT; 49 public static final long OFF_BUMP_ERR = OFF_BUMP_X + SIZE_INT; 50 public static final long OFF_NEXT = OFF_BUMP_ERR + SIZE_INT; 51 public static final long OFF_YMAX = OFF_NEXT + SIZE_INT; 52 53 // size of one edge in bytes 54 public static final int SIZEOF_EDGE_BYTES = (int)(OFF_YMAX + SIZE_INT); 55 56 // curve break into lines 57 // cubic error in subpixels to decrement step 58 private static final double CUB_DEC_ERR_SUBPIX 59 = MarlinProperties.getCubicDecD2() * (1.0d / 8.0d); // 1 pixel 60 // cubic error in subpixels to increment step 61 private static final double CUB_INC_ERR_SUBPIX 62 = MarlinProperties.getCubicIncD1() * (1.0d / 8.0d); // 0.4 pixel 63 64 // TestNonAARasterization (JDK-8170879): cubics 65 // bad paths (59294/100000 == 59,29%, 94335 bad pixels (avg = 1,59), 3966 warnings (avg = 0,07) 66 // 2018 67 // 1.0 / 0.2: bad paths (67194/100000 == 67,19%, 117394 bad pixels (avg = 1,75 - max = 9), 4042 warnings (avg = 0,06) 68 69 // cubic bind length to decrement step 70 public static final double CUB_DEC_BND 71 = 8.0d * CUB_DEC_ERR_SUBPIX; 72 // cubic bind length to increment step 73 public static final double CUB_INC_BND 74 = 8.0d * CUB_INC_ERR_SUBPIX; 75 76 // cubic countlg 77 public static final int CUB_COUNT_LG = 2; 78 // cubic count = 2^countlg 79 private static final int CUB_COUNT = 1 << CUB_COUNT_LG; 80 // cubic count^2 = 4^countlg 81 private static final int CUB_COUNT_2 = 1 << (2 * CUB_COUNT_LG); 82 // cubic count^3 = 8^countlg 83 private static final int CUB_COUNT_3 = 1 << (3 * CUB_COUNT_LG); 84 // cubic dt = 1 / count 85 private static final double CUB_INV_COUNT = 1.0d / CUB_COUNT; 86 // cubic dt^2 = 1 / count^2 = 1 / 4^countlg 87 private static final double CUB_INV_COUNT_2 = 1.0d / CUB_COUNT_2; 88 // cubic dt^3 = 1 / count^3 = 1 / 8^countlg 89 private static final double CUB_INV_COUNT_3 = 1.0d / CUB_COUNT_3; 90 91 // quad break into lines 92 // quadratic error in subpixels 93 private static final double QUAD_DEC_ERR_SUBPIX 94 = MarlinProperties.getQuadDecD2() * (1.0d / 8.0d); // 0.5 pixel 95 96 // TestNonAARasterization (JDK-8170879): quads 97 // bad paths (62916/100000 == 62,92%, 103818 bad pixels (avg = 1,65), 6514 warnings (avg = 0,10) 98 // 2018 99 // 0.50px = bad paths (62915/100000 == 62,92%, 103810 bad pixels (avg = 1,65), 6512 warnings (avg = 0,10) 100 101 // quadratic bind length to decrement step 102 public static final double QUAD_DEC_BND 103 = 8.0d * QUAD_DEC_ERR_SUBPIX; 104 105 ////////////////////////////////////////////////////////////////////////////// 106 // SCAN LINE 107 ////////////////////////////////////////////////////////////////////////////// 108 // crossings ie subpixel edge x coordinates 109 private int[] crossings; 110 // auxiliary storage for crossings (merge sort) 111 private int[] aux_crossings; 112 113 // indices into the segment pointer lists. They indicate the "active" 114 // sublist in the segment lists (the portion of the list that contains 115 // all the segments that cross the next scan line). 116 private int edgeCount; 117 private int[] edgePtrs; 118 // auxiliary storage for edge pointers (merge sort) 119 private int[] aux_edgePtrs; 162 final DCurve c, 163 final double x2, final double y2) 164 { 165 int count = 1; // dt = 1 / count 166 167 // maximum(ddX|Y) = norm(dbx, dby) * dt^2 (= 1) 168 double maxDD = Math.abs(c.dbx) + Math.abs(c.dby); 169 170 final double _DEC_BND = QUAD_DEC_BND; 171 172 while (maxDD >= _DEC_BND) { 173 // divide step by half: 174 maxDD /= 4.0d; // error divided by 2^2 = 4 175 176 count <<= 1; 177 if (DO_STATS) { 178 rdrCtx.stats.stat_rdr_quadBreak_dec.add(count); 179 } 180 } 181 182 final int nL = count; // line count 183 184 if (count > 1) { 185 final double icount = 1.0d / count; // dt 186 final double icount2 = icount * icount; // dt^2 187 188 final double ddx = c.dbx * icount2; 189 final double ddy = c.dby * icount2; 190 double dx = c.bx * icount2 + c.cx * icount; 191 double dy = c.by * icount2 + c.cy * icount; 192 193 // we use x0, y0 to walk the line 194 for (double x1 = x0, y1 = y0; --count > 0; dx += ddx, dy += ddy) { 195 x1 += dx; 196 y1 += dy; 197 198 addLine(x0, y0, x1, y1); 199 x0 = x1; 200 y0 = y1; 201 } 202 } 203 addLine(x0, y0, x2, y2); 204 205 if (DO_STATS) { 206 rdrCtx.stats.stat_rdr_quadBreak.add(nL); 207 } 208 } 209 210 // x0, y0 and x3,y3 are the endpoints of the curve. We could compute these 211 // using c.xat(0),c.yat(0) and c.xat(1),c.yat(1), but this might introduce 212 // numerical errors, and our callers already have the exact values. 213 // Another alternative would be to pass all the control points, and call 214 // c.set here, but then too many numbers are passed around. 215 private void curveBreakIntoLinesAndAdd(double x0, double y0, 216 final DCurve c, 217 final double x3, final double y3) 218 { 219 int count = CUB_COUNT; 220 final double icount = CUB_INV_COUNT; // dt 221 final double icount2 = CUB_INV_COUNT_2; // dt^2 222 final double icount3 = CUB_INV_COUNT_3; // dt^3 223 224 // the dx and dy refer to forward differencing variables, not the last 225 // coefficients of the "points" polynomial 226 double dddx, dddy, ddx, ddy, dx, dy; 227 dddx = 2.0d * c.dax * icount3; 228 dddy = 2.0d * c.day * icount3; 229 ddx = dddx + c.dbx * icount2; 230 ddy = dddy + c.dby * icount2; 231 dx = c.ax * icount3 + c.bx * icount2 + c.cx * icount; 232 dy = c.ay * icount3 + c.by * icount2 + c.cy * icount; 233 234 int nL = 0; // line count 235 236 final double _DEC_BND = CUB_DEC_BND; 237 final double _INC_BND = CUB_INC_BND; 238 239 // we use x0, y0 to walk the line 240 for (double x1 = x0, y1 = y0; count > 0; ) { 241 // inc / dec => ratio ~ 5 to minimize upscale / downscale but minimize edges 242 243 // double step: 244 // can only do this on even "count" values, because we must divide count by 2 245 while ((count % 2 == 0) 246 && ((Math.abs(ddx) + Math.abs(ddy)) <= _INC_BND)) { 247 dx = 2.0d * dx + ddx; 248 dy = 2.0d * dy + ddy; 249 ddx = 4.0d * (ddx + dddx); 250 ddy = 4.0d * (ddy + dddy); 251 dddx *= 8.0d; 252 dddy *= 8.0d; 253 254 count >>= 1; 255 if (DO_STATS) { 256 rdrCtx.stats.stat_rdr_curveBreak_inc.add(count); 257 } 258 } 259 260 // divide step by half: 261 while ((Math.abs(ddx) + Math.abs(ddy)) >= _DEC_BND) { 262 dddx /= 8.0d; 263 dddy /= 8.0d; 264 ddx = ddx / 4.0d - dddx; 265 ddy = ddy / 4.0d - dddy; 266 dx = (dx - ddx) / 2.0d; 267 dy = (dy - ddy) / 2.0d; 268 269 count <<= 1; 270 if (DO_STATS) { 271 rdrCtx.stats.stat_rdr_curveBreak_dec.add(count); 272 } 273 } 274 if (--count == 0) { 275 break; 276 } 277 278 x1 += dx; 279 y1 += dy; 280 dx += ddx; 281 dy += ddy; 282 ddx += dddx; 283 ddy += dddy; 284 285 addLine(x0, y0, x1, y1); 286 x0 = x1; 287 y0 = y1; 288 } 289 addLine(x0, y0, x3, y3); 290 291 if (DO_STATS) { 292 rdrCtx.stats.stat_rdr_curveBreak.add(nL + 1); 293 } 294 } 295 296 private void addLine(double x1, double y1, double x2, double y2) { 297 if (DO_MONITORS) { 298 rdrCtx.stats.mon_rdr_addLine.start(); 299 } 300 if (DO_STATS) { 301 rdrCtx.stats.stat_rdr_addLine.add(1); 302 } 303 int or = 1; // orientation of the line. 1 if y increases, 0 otherwise. 304 if (y2 < y1) { 305 or = 0; 306 double tmp = y2; 307 y2 = y1; 308 y1 = tmp; 309 tmp = x2; 310 x2 = x1; 311 x1 = tmp; 312 } 651 this.x0 = sx; 652 this.y0 = sy; 653 } 654 655 @Override 656 public void lineTo(final double pix_x1, final double pix_y1) { 657 final double x1 = tosubpixx(pix_x1); 658 final double y1 = tosubpixy(pix_y1); 659 addLine(x0, y0, x1, y1); 660 x0 = x1; 661 y0 = y1; 662 } 663 664 @Override 665 public void curveTo(final double pix_x1, final double pix_y1, 666 final double pix_x2, final double pix_y2, 667 final double pix_x3, final double pix_y3) 668 { 669 final double xe = tosubpixx(pix_x3); 670 final double ye = tosubpixy(pix_y3); 671 curve.set(x0, y0, 672 tosubpixx(pix_x1), tosubpixy(pix_y1), 673 tosubpixx(pix_x2), tosubpixy(pix_y2), 674 xe, ye); 675 curveBreakIntoLinesAndAdd(x0, y0, curve, xe, ye); 676 x0 = xe; 677 y0 = ye; 678 } 679 680 @Override 681 public void quadTo(final double pix_x1, final double pix_y1, 682 final double pix_x2, final double pix_y2) 683 { 684 final double xe = tosubpixx(pix_x2); 685 final double ye = tosubpixy(pix_y2); 686 curve.set(x0, y0, 687 tosubpixx(pix_x1), tosubpixy(pix_y1), 688 xe, ye); 689 quadBreakIntoLinesAndAdd(x0, y0, curve, xe, ye); 690 x0 = xe; 691 y0 = ye; 692 } 693 694 @Override 695 public void closePath() { 696 if (x0 != sx0 || y0 != sy0) { 697 addLine(x0, y0, sx0, sy0); 698 x0 = sx0; 699 y0 = sy0; 700 } 701 } 702 703 @Override 704 public void pathDone() { 705 closePath(); 706 707 // call endRendering() to determine the boundaries: 708 endRendering(); |