< prev index next >

src/java.desktop/share/classes/sun/java2d/marlin/DRenderer.java

Print this page


   1 /*
   2  * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  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


  36     static final boolean ENABLE_BLOCK_FLAGS_HEURISTICS = MarlinProperties.isUseTileFlagsWithHeuristics();
  37 
  38     private static final int ALL_BUT_LSB = 0xFFFFFFFE;
  39     private static final int ERR_STEP_MAX = 0x7FFFFFFF; // = 2^31 - 1
  40 
  41     private static final double POWER_2_TO_32 = 0x1.0p32d;
  42 
  43     // use double to make tosubpix methods faster (no int to double conversion)
  44     static final double SUBPIXEL_SCALE_X = SUBPIXEL_POSITIONS_X;
  45     static final double SUBPIXEL_SCALE_Y = SUBPIXEL_POSITIONS_Y;
  46     static final int SUBPIXEL_MASK_X = SUBPIXEL_POSITIONS_X - 1;
  47     static final int SUBPIXEL_MASK_Y = SUBPIXEL_POSITIONS_Y - 1;
  48 
  49     static final double RDR_OFFSET_X = 0.5d / SUBPIXEL_SCALE_X;
  50     static final double RDR_OFFSET_Y = 0.5d / SUBPIXEL_SCALE_Y;
  51 
  52     // number of subpixels corresponding to a tile line
  53     private static final int SUBPIXEL_TILE
  54         = TILE_H << SUBPIXEL_LG_POSITIONS_Y;
  55 
  56     // 2048 (pixelSize) pixels (height) x 8 subpixels = 64K
  57     static final int INITIAL_BUCKET_ARRAY
  58         = INITIAL_PIXEL_DIM * SUBPIXEL_POSITIONS_Y;
  59 
  60     // crossing capacity = edges count / 4 ~ 1024
  61     static final int INITIAL_CROSSING_COUNT = INITIAL_EDGES_COUNT >> 2;
  62 
  63     // common to all types of input path segments.
  64     // OFFSET as bytes
  65     // only integer values:
  66     public static final long OFF_CURX_OR  = 0;
  67     public static final long OFF_ERROR    = OFF_CURX_OR  + SIZE_INT;
  68     public static final long OFF_BUMP_X   = OFF_ERROR    + SIZE_INT;
  69     public static final long OFF_BUMP_ERR = OFF_BUMP_X   + SIZE_INT;
  70     public static final long OFF_NEXT     = OFF_BUMP_ERR + SIZE_INT;
  71     public static final long OFF_YMAX     = OFF_NEXT     + SIZE_INT;
  72 
  73     // size of one edge in bytes
  74     public static final int SIZEOF_EDGE_BYTES = (int)(OFF_YMAX + SIZE_INT);
  75 
  76     // curve break into lines
  77     // cubic error in subpixels to decrement step
  78     private static final double CUB_DEC_ERR_SUBPIX
  79         = MarlinProperties.getCubicDecD2() * (NORM_SUBPIXELS / 8.0d); // 1 pixel
  80     // cubic error in subpixels to increment step
  81     private static final double CUB_INC_ERR_SUBPIX
  82         = MarlinProperties.getCubicIncD1() * (NORM_SUBPIXELS / 8.0d); // 0.4 pixel


  83 
  84     // TestNonAARasterization (JDK-8170879): cubics
  85     // bad paths (59294/100000 == 59,29%, 94335 bad pixels (avg = 1,59), 3966 warnings (avg = 0,07)


  86 
  87     // cubic bind length to decrement step
  88     public static final double CUB_DEC_BND
  89         = 8.0d * CUB_DEC_ERR_SUBPIX;
  90     // cubic bind length to increment step
  91     public static final double CUB_INC_BND
  92         = 8.0d * CUB_INC_ERR_SUBPIX;
  93 
  94     // cubic countlg
  95     public static final int CUB_COUNT_LG = 2;
  96     // cubic count = 2^countlg
  97     private static final int CUB_COUNT = 1 << CUB_COUNT_LG;
  98     // cubic count^2 = 4^countlg
  99     private static final int CUB_COUNT_2 = 1 << (2 * CUB_COUNT_LG);
 100     // cubic count^3 = 8^countlg
 101     private static final int CUB_COUNT_3 = 1 << (3 * CUB_COUNT_LG);
 102     // cubic dt = 1 / count
 103     private static final double CUB_INV_COUNT = 1.0d / CUB_COUNT;
 104     // cubic dt^2 = 1 / count^2 = 1 / 4^countlg
 105     private static final double CUB_INV_COUNT_2 = 1.0d / CUB_COUNT_2;
 106     // cubic dt^3 = 1 / count^3 = 1 / 8^countlg
 107     private static final double CUB_INV_COUNT_3 = 1.0d / CUB_COUNT_3;
 108 
 109     // quad break into lines
 110     // quadratic error in subpixels
 111     private static final double QUAD_DEC_ERR_SUBPIX
 112         = MarlinProperties.getQuadDecD2() * (NORM_SUBPIXELS / 8.0d); // 0.5 pixel
 113 
 114     // TestNonAARasterization (JDK-8170879): quads
 115     // bad paths (62916/100000 == 62,92%, 103818 bad pixels (avg = 1,65), 6514 warnings (avg = 0,10)


 116 
 117     // quadratic bind length to decrement step
 118     public static final double QUAD_DEC_BND
 119         = 8.0d * QUAD_DEC_ERR_SUBPIX;
 120 
 121 //////////////////////////////////////////////////////////////////////////////
 122 //  SCAN LINE
 123 //////////////////////////////////////////////////////////////////////////////
 124     // crossings ie subpixel edge x coordinates
 125     private int[] crossings;
 126     // auxiliary storage for crossings (merge sort)
 127     private int[] aux_crossings;
 128 
 129     // indices into the segment pointer lists. They indicate the "active"
 130     // sublist in the segment lists (the portion of the list that contains
 131     // all the segments that cross the next scan line).
 132     private int edgeCount;
 133     private int[] edgePtrs;
 134     // auxiliary storage for edge pointers (merge sort)
 135     private int[] aux_edgePtrs;


 162     private int[] edgeBucketCounts; // 2*newedges + (1 if pruning needed)
 163     // used range for edgeBuckets / edgeBucketCounts
 164     private int buckets_minY;
 165     private int buckets_maxY;
 166 
 167     // edgeBuckets ref (clean)
 168     private final IntArrayCache.Reference edgeBuckets_ref;
 169     // edgeBucketCounts ref (clean)
 170     private final IntArrayCache.Reference edgeBucketCounts_ref;
 171 
 172     // Flattens using adaptive forward differencing. This only carries out
 173     // one iteration of the AFD loop. All it does is update AFD variables (i.e.
 174     // X0, Y0, D*[X|Y], COUNT; not variables used for computing scanline crossings).
 175     private void quadBreakIntoLinesAndAdd(double x0, double y0,
 176                                           final DCurve c,
 177                                           final double x2, final double y2)
 178     {
 179         int count = 1; // dt = 1 / count
 180 
 181         // maximum(ddX|Y) = norm(dbx, dby) * dt^2 (= 1)
 182         double maxDD = Math.abs(c.dbx) + Math.abs(c.dby);
 183 
 184         final double _DEC_BND = QUAD_DEC_BND;
 185 
 186         while (maxDD >= _DEC_BND) {
 187             // divide step by half:
 188             maxDD /= 4.0d; // error divided by 2^2 = 4
 189 
 190             count <<= 1;
 191             if (DO_STATS) {
 192                 rdrCtx.stats.stat_rdr_quadBreak_dec.add(count);
 193             }
 194         }
 195 
 196         int nL = 0; // line count

 197         if (count > 1) {
 198             final double icount = 1.0d / count; // dt
 199             final double icount2 = icount * icount; // dt^2
 200 
 201             final double ddx = c.dbx * icount2;
 202             final double ddy = c.dby * icount2;
 203             double dx = c.bx * icount2 + c.cx * icount;
 204             double dy = c.by * icount2 + c.cy * icount;
 205 
 206             double x1, y1;
 207 
 208             while (--count > 0) {
 209                 x1 = x0 + dx;
 210                 dx += ddx;
 211                 y1 = y0 + dy;
 212                 dy += ddy;
 213 
 214                 addLine(x0, y0, x1, y1);
 215 
 216                 if (DO_STATS) { nL++; }
 217                 x0 = x1;
 218                 y0 = y1;
 219             }
 220         }
 221         addLine(x0, y0, x2, y2);
 222 
 223         if (DO_STATS) {
 224             rdrCtx.stats.stat_rdr_quadBreak.add(nL + 1);
 225         }
 226     }
 227 
 228     // x0, y0 and x3,y3 are the endpoints of the curve. We could compute these
 229     // using c.xat(0),c.yat(0) and c.xat(1),c.yat(1), but this might introduce
 230     // numerical errors, and our callers already have the exact values.
 231     // Another alternative would be to pass all the control points, and call
 232     // c.set here, but then too many numbers are passed around.
 233     private void curveBreakIntoLinesAndAdd(double x0, double y0,
 234                                            final DCurve c,
 235                                            final double x3, final double y3)
 236     {
 237         int count           = CUB_COUNT;
 238         final double icount  = CUB_INV_COUNT;   // dt
 239         final double icount2 = CUB_INV_COUNT_2; // dt^2
 240         final double icount3 = CUB_INV_COUNT_3; // dt^3
 241 
 242         // the dx and dy refer to forward differencing variables, not the last
 243         // coefficients of the "points" polynomial
 244         double dddx, dddy, ddx, ddy, dx, dy;
 245         dddx = 2.0d * c.dax * icount3;
 246         dddy = 2.0d * c.day * icount3;
 247         ddx = dddx + c.dbx * icount2;
 248         ddy = dddy + c.dby * icount2;
 249         dx = c.ax * icount3 + c.bx * icount2 + c.cx * icount;
 250         dy = c.ay * icount3 + c.by * icount2 + c.cy * icount;
 251 
 252         // we use x0, y0 to walk the line
 253         double x1 = x0, y1 = y0;
 254         int nL = 0; // line count
 255 
 256         final double _DEC_BND = CUB_DEC_BND;
 257         final double _INC_BND = CUB_INC_BND;

 258 
 259         while (count > 0) {
 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 
 275             // double step:
 276             // can only do this on even "count" values, because we must divide count by 2
 277             while (count % 2 == 0
 278                    && Math.abs(dx) + Math.abs(dy) <= _INC_BND)
 279             {

 280                 dx = 2.0d * dx + ddx;
 281                 dy = 2.0d * dy + ddy;
 282                 ddx = 4.0d * (ddx + dddx);
 283                 ddy = 4.0d * (ddy + dddy);
 284                 dddx *= 8.0d;
 285                 dddy *= 8.0d;
 286 
 287                 count >>= 1;
 288                 if (DO_STATS) {
 289                     rdrCtx.stats.stat_rdr_curveBreak_inc.add(count);
 290                 }
 291             }
 292             if (--count > 0) {
 293                 x1 += dx;
 294                 dx += ddx;
 295                 ddx += dddx;
 296                 y1 += dy;
 297                 dy += ddy;
 298                 ddy += dddy;
 299             } else {
 300                 x1 = x3;
 301                 y1 = y3;









 302             }
 303 
 304             addLine(x0, y0, x1, y1);





 305 
 306             if (DO_STATS) { nL++; }
 307             x0 = x1;
 308             y0 = y1;
 309         }


 310         if (DO_STATS) {
 311             rdrCtx.stats.stat_rdr_curveBreak.add(nL);
 312         }
 313     }
 314 
 315     private void addLine(double x1, double y1, double x2, double y2) {
 316         if (DO_MONITORS) {
 317             rdrCtx.stats.mon_rdr_addLine.start();
 318         }
 319         if (DO_STATS) {
 320             rdrCtx.stats.stat_rdr_addLine.add(1);
 321         }
 322         int or = 1; // orientation of the line. 1 if y increases, 0 otherwise.
 323         if (y2 < y1) {
 324             or = 0;
 325             double tmp = y2;
 326             y2 = y1;
 327             y1 = tmp;
 328             tmp = x2;
 329             x2 = x1;
 330             x1 = tmp;
 331         }


 516 
 517     /* block flags (0|1) */
 518     private int[] blkFlags;
 519 
 520     // blkFlags ref (clean)
 521     private final IntArrayCache.Reference blkFlags_ref;
 522 
 523     DRenderer(final DRendererContext rdrCtx) {
 524         this.rdrCtx = rdrCtx;
 525         this.curve = rdrCtx.curve;
 526         this.cache = rdrCtx.cache;
 527 
 528         this.edges = rdrCtx.newOffHeapArray(INITIAL_EDGES_CAPACITY); // 96K
 529 
 530         edgeBuckets_ref      = rdrCtx.newCleanIntArrayRef(INITIAL_BUCKET_ARRAY); // 64K
 531         edgeBucketCounts_ref = rdrCtx.newCleanIntArrayRef(INITIAL_BUCKET_ARRAY); // 64K
 532 
 533         edgeBuckets      = edgeBuckets_ref.initial;
 534         edgeBucketCounts = edgeBucketCounts_ref.initial;
 535 
 536         // 2048 (pixelsize) pixel large
 537         alphaLine_ref = rdrCtx.newCleanIntArrayRef(INITIAL_AA_ARRAY); // 8K
 538         alphaLine     = alphaLine_ref.initial;
 539 
 540         crossings_ref     = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
 541         aux_crossings_ref = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
 542         edgePtrs_ref      = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
 543         aux_edgePtrs_ref  = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
 544 
 545         crossings     = crossings_ref.initial;
 546         aux_crossings = aux_crossings_ref.initial;
 547         edgePtrs      = edgePtrs_ref.initial;
 548         aux_edgePtrs  = aux_edgePtrs_ref.initial;
 549 
 550         blkFlags_ref = rdrCtx.newCleanIntArrayRef(INITIAL_ARRAY); // 1K = 1 tile line
 551         blkFlags     = blkFlags_ref.initial;
 552     }
 553 
 554     DRenderer init(final int pix_boundsX, final int pix_boundsY,
 555                   final int pix_boundsWidth, final int pix_boundsHeight,
 556                   final int windingRule)
 557     {


 675         this.x0 = sx;
 676         this.y0 = sy;
 677     }
 678 
 679     @Override
 680     public void lineTo(final double pix_x1, final double pix_y1) {
 681         final double x1 = tosubpixx(pix_x1);
 682         final double y1 = tosubpixy(pix_y1);
 683         addLine(x0, y0, x1, y1);
 684         x0 = x1;
 685         y0 = y1;
 686     }
 687 
 688     @Override
 689     public void curveTo(final double pix_x1, final double pix_y1,
 690                         final double pix_x2, final double pix_y2,
 691                         final double pix_x3, final double pix_y3)
 692     {
 693         final double xe = tosubpixx(pix_x3);
 694         final double ye = tosubpixy(pix_y3);
 695         curve.set(x0, y0, tosubpixx(pix_x1), tosubpixy(pix_y1),
 696                   tosubpixx(pix_x2), tosubpixy(pix_y2), xe, ye);


 697         curveBreakIntoLinesAndAdd(x0, y0, curve, xe, ye);
 698         x0 = xe;
 699         y0 = ye;
 700     }
 701 
 702     @Override
 703     public void quadTo(final double pix_x1, final double pix_y1,
 704                        final double pix_x2, final double pix_y2)
 705     {
 706         final double xe = tosubpixx(pix_x2);
 707         final double ye = tosubpixy(pix_y2);
 708         curve.set(x0, y0, tosubpixx(pix_x1), tosubpixy(pix_y1), xe, ye);


 709         quadBreakIntoLinesAndAdd(x0, y0, curve, xe, ye);
 710         x0 = xe;
 711         y0 = ye;
 712     }
 713 
 714     @Override
 715     public void closePath() {
 716         if (x0 != sx0 || y0 != sy0) {
 717             addLine(x0, y0, sx0, sy0);
 718             x0 = sx0;
 719             y0 = sy0;
 720         }
 721     }
 722 
 723     @Override
 724     public void pathDone() {
 725         closePath();
 726     }
 727 
 728     @Override


   1 /*
   2  * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  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


  36     static final boolean ENABLE_BLOCK_FLAGS_HEURISTICS = MarlinProperties.isUseTileFlagsWithHeuristics();
  37 
  38     private static final int ALL_BUT_LSB = 0xFFFFFFFE;
  39     private static final int ERR_STEP_MAX = 0x7FFFFFFF; // = 2^31 - 1
  40 
  41     private static final double POWER_2_TO_32 = 0x1.0p32d;
  42 
  43     // use double to make tosubpix methods faster (no int to double conversion)
  44     static final double SUBPIXEL_SCALE_X = SUBPIXEL_POSITIONS_X;
  45     static final double SUBPIXEL_SCALE_Y = SUBPIXEL_POSITIONS_Y;
  46     static final int SUBPIXEL_MASK_X = SUBPIXEL_POSITIONS_X - 1;
  47     static final int SUBPIXEL_MASK_Y = SUBPIXEL_POSITIONS_Y - 1;
  48 
  49     static final double RDR_OFFSET_X = 0.5d / SUBPIXEL_SCALE_X;
  50     static final double RDR_OFFSET_Y = 0.5d / SUBPIXEL_SCALE_Y;
  51 
  52     // number of subpixels corresponding to a tile line
  53     private static final int SUBPIXEL_TILE
  54         = TILE_H << SUBPIXEL_LG_POSITIONS_Y;
  55 
  56     // 2176 pixels (height) x 8 subpixels = 68K
  57     static final int INITIAL_BUCKET_ARRAY
  58         = INITIAL_PIXEL_HEIGHT * SUBPIXEL_POSITIONS_Y;
  59 
  60     // crossing capacity = edges count / 4 ~ 1024
  61     static final int INITIAL_CROSSING_COUNT = INITIAL_EDGES_COUNT >> 2;
  62 
  63     // common to all types of input path segments.
  64     // OFFSET as bytes
  65     // only integer values:
  66     public static final long OFF_CURX_OR  = 0;
  67     public static final long OFF_ERROR    = OFF_CURX_OR  + SIZE_INT;
  68     public static final long OFF_BUMP_X   = OFF_ERROR    + SIZE_INT;
  69     public static final long OFF_BUMP_ERR = OFF_BUMP_X   + SIZE_INT;
  70     public static final long OFF_NEXT     = OFF_BUMP_ERR + SIZE_INT;
  71     public static final long OFF_YMAX     = OFF_NEXT     + SIZE_INT;
  72 
  73     // size of one edge in bytes
  74     public static final int SIZEOF_EDGE_BYTES = (int)(OFF_YMAX + SIZE_INT);
  75 
  76     // curve break into lines
  77     // cubic error in subpixels to decrement step
  78     private static final double CUB_DEC_ERR_SUBPIX
  79         = MarlinProperties.getCubicDecD2() * (SUBPIXEL_POSITIONS_X / 8.0d); // 1.0 / 8th pixel
  80     // cubic error in subpixels to increment step
  81     private static final double CUB_INC_ERR_SUBPIX
  82         = MarlinProperties.getCubicIncD1() * (SUBPIXEL_POSITIONS_X / 8.0d); // 0.4 / 8th pixel
  83     // scale factor for Y-axis contribution to quad / cubic errors:
  84     public static final double SCALE_DY = ((double) SUBPIXEL_POSITIONS_X) / SUBPIXEL_POSITIONS_Y;
  85 
  86     // TestNonAARasterization (JDK-8170879): cubics
  87     // bad paths (59294/100000 == 59,29%, 94335 bad pixels (avg = 1,59), 3966 warnings (avg = 0,07)
  88 // 2018
  89     // 1.0 / 0.2: bad paths (67194/100000 == 67,19%, 117394 bad pixels (avg = 1,75 - max =  9), 4042 warnings (avg = 0,06)
  90 
  91     // cubic bind length to decrement step
  92     public static final double CUB_DEC_BND
  93         = 8.0d * CUB_DEC_ERR_SUBPIX;
  94     // cubic bind length to increment step
  95     public static final double CUB_INC_BND
  96         = 8.0d * CUB_INC_ERR_SUBPIX;
  97 
  98     // cubic countlg
  99     public static final int CUB_COUNT_LG = 2;
 100     // cubic count = 2^countlg
 101     private static final int CUB_COUNT = 1 << CUB_COUNT_LG;
 102     // cubic count^2 = 4^countlg
 103     private static final int CUB_COUNT_2 = 1 << (2 * CUB_COUNT_LG);
 104     // cubic count^3 = 8^countlg
 105     private static final int CUB_COUNT_3 = 1 << (3 * CUB_COUNT_LG);
 106     // cubic dt = 1 / count
 107     private static final double CUB_INV_COUNT = 1.0d / CUB_COUNT;
 108     // cubic dt^2 = 1 / count^2 = 1 / 4^countlg
 109     private static final double CUB_INV_COUNT_2 = 1.0d / CUB_COUNT_2;
 110     // cubic dt^3 = 1 / count^3 = 1 / 8^countlg
 111     private static final double CUB_INV_COUNT_3 = 1.0d / CUB_COUNT_3;
 112 
 113     // quad break into lines
 114     // quadratic error in subpixels
 115     private static final double QUAD_DEC_ERR_SUBPIX
 116         = MarlinProperties.getQuadDecD2() * (SUBPIXEL_POSITIONS_X / 8.0d); // 0.5 / 8th pixel
 117 
 118     // TestNonAARasterization (JDK-8170879): quads
 119     // bad paths (62916/100000 == 62,92%, 103818 bad pixels (avg = 1,65), 6514 warnings (avg = 0,10)
 120 // 2018
 121     // 0.50px  = bad paths (62915/100000 == 62,92%, 103810 bad pixels (avg = 1,65), 6512 warnings (avg = 0,10)
 122 
 123     // quadratic bind length to decrement step
 124     public static final double QUAD_DEC_BND
 125         = 8.0d * QUAD_DEC_ERR_SUBPIX;
 126 
 127 //////////////////////////////////////////////////////////////////////////////
 128 //  SCAN LINE
 129 //////////////////////////////////////////////////////////////////////////////
 130     // crossings ie subpixel edge x coordinates
 131     private int[] crossings;
 132     // auxiliary storage for crossings (merge sort)
 133     private int[] aux_crossings;
 134 
 135     // indices into the segment pointer lists. They indicate the "active"
 136     // sublist in the segment lists (the portion of the list that contains
 137     // all the segments that cross the next scan line).
 138     private int edgeCount;
 139     private int[] edgePtrs;
 140     // auxiliary storage for edge pointers (merge sort)
 141     private int[] aux_edgePtrs;


 168     private int[] edgeBucketCounts; // 2*newedges + (1 if pruning needed)
 169     // used range for edgeBuckets / edgeBucketCounts
 170     private int buckets_minY;
 171     private int buckets_maxY;
 172 
 173     // edgeBuckets ref (clean)
 174     private final IntArrayCache.Reference edgeBuckets_ref;
 175     // edgeBucketCounts ref (clean)
 176     private final IntArrayCache.Reference edgeBucketCounts_ref;
 177 
 178     // Flattens using adaptive forward differencing. This only carries out
 179     // one iteration of the AFD loop. All it does is update AFD variables (i.e.
 180     // X0, Y0, D*[X|Y], COUNT; not variables used for computing scanline crossings).
 181     private void quadBreakIntoLinesAndAdd(double x0, double y0,
 182                                           final DCurve c,
 183                                           final double x2, final double y2)
 184     {
 185         int count = 1; // dt = 1 / count
 186 
 187         // maximum(ddX|Y) = norm(dbx, dby) * dt^2 (= 1)
 188         double maxDD = Math.abs(c.dbx) + Math.abs(c.dby) * SCALE_DY;
 189 
 190         final double _DEC_BND = QUAD_DEC_BND;
 191 
 192         while (maxDD >= _DEC_BND) {
 193             // divide step by half:
 194             maxDD /= 4.0d; // error divided by 2^2 = 4
 195 
 196             count <<= 1;
 197             if (DO_STATS) {
 198                 rdrCtx.stats.stat_rdr_quadBreak_dec.add(count);
 199             }
 200         }
 201 
 202         final int nL = count; // line count
 203 
 204         if (count > 1) {
 205             final double icount = 1.0d / count; // dt
 206             final double icount2 = icount * icount; // dt^2
 207 
 208             final double ddx = c.dbx * icount2;
 209             final double ddy = c.dby * icount2;
 210             double dx = c.bx * icount2 + c.cx * icount;
 211             double dy = c.by * icount2 + c.cy * icount;
 212 
 213             // we use x0, y0 to walk the line
 214             for (double x1 = x0, y1 = y0; --count > 0; dx += ddx, dy += ddy) {
 215                 x1 += dx;
 216                 y1 += dy;



 217 
 218                 addLine(x0, y0, x1, y1);


 219                 x0 = x1;
 220                 y0 = y1;
 221             }
 222         }
 223         addLine(x0, y0, x2, y2);
 224 
 225         if (DO_STATS) {
 226             rdrCtx.stats.stat_rdr_quadBreak.add(nL);
 227         }
 228     }
 229 
 230     // x0, y0 and x3,y3 are the endpoints of the curve. We could compute these
 231     // using c.xat(0),c.yat(0) and c.xat(1),c.yat(1), but this might introduce
 232     // numerical errors, and our callers already have the exact values.
 233     // Another alternative would be to pass all the control points, and call
 234     // c.set here, but then too many numbers are passed around.
 235     private void curveBreakIntoLinesAndAdd(double x0, double y0,
 236                                            final DCurve c,
 237                                            final double x3, final double y3)
 238     {
 239         int count            = CUB_COUNT;
 240         final double icount  = CUB_INV_COUNT;   // dt
 241         final double icount2 = CUB_INV_COUNT_2; // dt^2
 242         final double icount3 = CUB_INV_COUNT_3; // dt^3
 243 
 244         // the dx and dy refer to forward differencing variables, not the last
 245         // coefficients of the "points" polynomial
 246         double dddx, dddy, ddx, ddy, dx, dy;
 247         dddx = 2.0d * c.dax * icount3;
 248         dddy = 2.0d * c.day * icount3;
 249         ddx = dddx + c.dbx * icount2;
 250         ddy = dddy + c.dby * icount2;
 251         dx = c.ax * icount3 + c.bx * icount2 + c.cx * icount;
 252         dy = c.ay * icount3 + c.by * icount2 + c.cy * icount;
 253 


 254         int nL = 0; // line count
 255 
 256         final double _DEC_BND = CUB_DEC_BND;
 257         final double _INC_BND = CUB_INC_BND;
 258         final double _SCALE_DY = SCALE_DY;
 259 
 260         // we use x0, y0 to walk the line
 261         for (double x1 = x0, y1 = y0; count > 0; ) {
 262             // inc / dec => ratio ~ 5 to minimize upscale / downscale but minimize edges












 263 
 264             // double step:
 265             // can only do this on even "count" values, because we must divide count by 2
 266             while ((count % 2 == 0)
 267                     && ((Math.abs(ddx) + Math.abs(ddy) * _SCALE_DY) <= _INC_BND
 268 //                     && (Math.abs(ddx + dddx) + Math.abs(ddy + dddy) * _SCALE_DY) <= _INC_BND
 269                   )) {
 270                 dx = 2.0d * dx + ddx;
 271                 dy = 2.0d * dy + ddy;
 272                 ddx = 4.0d * (ddx + dddx);
 273                 ddy = 4.0d * (ddy + dddy);
 274                 dddx *= 8.0d;
 275                 dddy *= 8.0d;
 276 
 277                 count >>= 1;
 278                 if (DO_STATS) {
 279                     rdrCtx.stats.stat_rdr_curveBreak_inc.add(count);
 280                 }
 281             }
 282 
 283             // divide step by half:
 284             while ((Math.abs(ddx) + Math.abs(ddy) * _SCALE_DY) >= _DEC_BND
 285 //                || (Math.abs(ddx + dddx) + Math.abs(ddy + dddy) * _SCALE_DY) >= _DEC_BND
 286                   ) {
 287                 dddx /= 8.0d;
 288                 dddy /= 8.0d;
 289                 ddx = ddx / 4.0d - dddx;
 290                 ddy = ddy / 4.0d - dddy;
 291                 dx = (dx - ddx) / 2.0d;
 292                 dy = (dy - ddy) / 2.0d;
 293 
 294                 count <<= 1;
 295                 if (DO_STATS) {
 296                     rdrCtx.stats.stat_rdr_curveBreak_dec.add(count);
 297                 }
 298             }
 299             if (--count == 0) {
 300                 break;
 301             }
 302 
 303             x1 += dx;
 304             y1 += dy;
 305             dx += ddx;
 306             dy += ddy;
 307             ddx += dddx;
 308             ddy += dddy;
 309 
 310             addLine(x0, y0, x1, y1);
 311             x0 = x1;
 312             y0 = y1;
 313         }
 314         addLine(x0, y0, x3, y3);
 315 
 316         if (DO_STATS) {
 317             rdrCtx.stats.stat_rdr_curveBreak.add(nL + 1);
 318         }
 319     }
 320 
 321     private void addLine(double x1, double y1, double x2, double y2) {
 322         if (DO_MONITORS) {
 323             rdrCtx.stats.mon_rdr_addLine.start();
 324         }
 325         if (DO_STATS) {
 326             rdrCtx.stats.stat_rdr_addLine.add(1);
 327         }
 328         int or = 1; // orientation of the line. 1 if y increases, 0 otherwise.
 329         if (y2 < y1) {
 330             or = 0;
 331             double tmp = y2;
 332             y2 = y1;
 333             y1 = tmp;
 334             tmp = x2;
 335             x2 = x1;
 336             x1 = tmp;
 337         }


 522 
 523     /* block flags (0|1) */
 524     private int[] blkFlags;
 525 
 526     // blkFlags ref (clean)
 527     private final IntArrayCache.Reference blkFlags_ref;
 528 
 529     DRenderer(final DRendererContext rdrCtx) {
 530         this.rdrCtx = rdrCtx;
 531         this.curve = rdrCtx.curve;
 532         this.cache = rdrCtx.cache;
 533 
 534         this.edges = rdrCtx.newOffHeapArray(INITIAL_EDGES_CAPACITY); // 96K
 535 
 536         edgeBuckets_ref      = rdrCtx.newCleanIntArrayRef(INITIAL_BUCKET_ARRAY); // 64K
 537         edgeBucketCounts_ref = rdrCtx.newCleanIntArrayRef(INITIAL_BUCKET_ARRAY); // 64K
 538 
 539         edgeBuckets      = edgeBuckets_ref.initial;
 540         edgeBucketCounts = edgeBucketCounts_ref.initial;
 541 
 542         // 4096 pixels large
 543         alphaLine_ref = rdrCtx.newCleanIntArrayRef(INITIAL_AA_ARRAY); // 16K
 544         alphaLine     = alphaLine_ref.initial;
 545 
 546         crossings_ref     = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
 547         aux_crossings_ref = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
 548         edgePtrs_ref      = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
 549         aux_edgePtrs_ref  = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K
 550 
 551         crossings     = crossings_ref.initial;
 552         aux_crossings = aux_crossings_ref.initial;
 553         edgePtrs      = edgePtrs_ref.initial;
 554         aux_edgePtrs  = aux_edgePtrs_ref.initial;
 555 
 556         blkFlags_ref = rdrCtx.newCleanIntArrayRef(INITIAL_ARRAY); // 1K = 1 tile line
 557         blkFlags     = blkFlags_ref.initial;
 558     }
 559 
 560     DRenderer init(final int pix_boundsX, final int pix_boundsY,
 561                   final int pix_boundsWidth, final int pix_boundsHeight,
 562                   final int windingRule)
 563     {


 681         this.x0 = sx;
 682         this.y0 = sy;
 683     }
 684 
 685     @Override
 686     public void lineTo(final double pix_x1, final double pix_y1) {
 687         final double x1 = tosubpixx(pix_x1);
 688         final double 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 double pix_x1, final double pix_y1,
 696                         final double pix_x2, final double pix_y2,
 697                         final double pix_x3, final double pix_y3)
 698     {
 699         final double xe = tosubpixx(pix_x3);
 700         final double ye = tosubpixy(pix_y3);
 701         curve.set(x0, y0,
 702                 tosubpixx(pix_x1), tosubpixy(pix_y1),
 703                 tosubpixx(pix_x2), tosubpixy(pix_y2),
 704                 xe, ye);
 705         curveBreakIntoLinesAndAdd(x0, y0, curve, xe, ye);
 706         x0 = xe;
 707         y0 = ye;
 708     }
 709 
 710     @Override
 711     public void quadTo(final double pix_x1, final double pix_y1,
 712                        final double pix_x2, final double pix_y2)
 713     {
 714         final double xe = tosubpixx(pix_x2);
 715         final double ye = tosubpixy(pix_y2);
 716         curve.set(x0, y0,
 717                 tosubpixx(pix_x1), tosubpixy(pix_y1),
 718                 xe, ye);
 719         quadBreakIntoLinesAndAdd(x0, y0, curve, xe, ye);
 720         x0 = xe;
 721         y0 = ye;
 722     }
 723 
 724     @Override
 725     public void closePath() {
 726         if (x0 != sx0 || y0 != sy0) {
 727             addLine(x0, y0, sx0, sy0);
 728             x0 = sx0;
 729             y0 = sy0;
 730         }
 731     }
 732 
 733     @Override
 734     public void pathDone() {
 735         closePath();
 736     }
 737 
 738     @Override


< prev index next >