< prev index next >

src/java.desktop/share/classes/sun/java2d/marlin/Renderer.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


  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


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


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


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


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

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

 259 
 260         while (count > 0) {
 261             // divide step by half:
 262             while (Math.abs(ddx) + Math.abs(ddy) >= _DEC_BND) {
 263                 dddx /= 8.0f;
 264                 dddy /= 8.0f;
 265                 ddx = ddx / 4.0f - dddx;
 266                 ddy = ddy / 4.0f - dddy;
 267                 dx = (dx - ddx) / 2.0f;
 268                 dy = (dy - ddy) / 2.0f;
 269 
 270                 count <<= 1;
 271                 if (DO_STATS) {
 272                     rdrCtx.stats.stat_rdr_curveBreak_dec.add(count);
 273                 }
 274             }
 275 
 276             // double step:
 277             // can only do this on even "count" values, because we must divide count by 2
 278             while (count % 2 == 0
 279                    && Math.abs(dx) + Math.abs(dy) <= _INC_BND)
 280             {

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









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





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


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


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


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


 701         curveBreakIntoLinesAndAdd(x0, y0, curve, xe, ye);
 702         x0 = xe;
 703         y0 = ye;
 704     }
 705 
 706     @Override
 707     public void quadTo(final float pix_x1, final float pix_y1,
 708                        final float pix_x2, final float pix_y2)
 709     {
 710         final float xe = tosubpixx(pix_x2);
 711         final float ye = tosubpixy(pix_y2);
 712         curve.set(x0, y0, tosubpixx(pix_x1), tosubpixy(pix_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         if (x0 != sx0 || y0 != sy0) {
 721             addLine(x0, y0, sx0, sy0);
 722             x0 = sx0;
 723             y0 = sy0;
 724         }
 725     }
 726 
 727     @Override
 728     public void pathDone() {
 729         closePath();
 730     }
 731 
 732     @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


  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     // 2176 pixels (height) x 8 subpixels = 68K
  58     static final int INITIAL_BUCKET_ARRAY
  59         = INITIAL_PIXEL_HEIGHT * 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() * (SUBPIXEL_POSITIONS_X / 8.0f); // 1.0 / 8th pixel
  81     // cubic error in subpixels to increment step
  82     private static final float CUB_INC_ERR_SUBPIX
  83         = MarlinProperties.getCubicIncD1() * (SUBPIXEL_POSITIONS_X / 8.0f); // 0.4 / 8th pixel
  84     // scale factor for Y-axis contribution to quad / cubic errors:
  85     public static final float SCALE_DY = ((float) SUBPIXEL_POSITIONS_X) / SUBPIXEL_POSITIONS_Y;
  86 
  87     // TestNonAARasterization (JDK-8170879): cubics
  88     // bad paths (59294/100000 == 59,29%, 94335 bad pixels (avg = 1,59), 3966 warnings (avg = 0,07)
  89 // 2018
  90     // 1.0 / 0.2: bad paths (67194/100000 == 67,19%, 117394 bad pixels (avg = 1,75 - max =  9), 4042 warnings (avg = 0,06)
  91 
  92     // cubic bind length to decrement step
  93     public static final float CUB_DEC_BND
  94         = 8.0f * CUB_DEC_ERR_SUBPIX;
  95     // cubic bind length to increment step
  96     public static final float CUB_INC_BND
  97         = 8.0f * CUB_INC_ERR_SUBPIX;
  98 
  99     // cubic countlg
 100     public static final int CUB_COUNT_LG = 2;
 101     // cubic count = 2^countlg
 102     private static final int CUB_COUNT = 1 << CUB_COUNT_LG;
 103     // cubic count^2 = 4^countlg
 104     private static final int CUB_COUNT_2 = 1 << (2 * CUB_COUNT_LG);
 105     // cubic count^3 = 8^countlg
 106     private static final int CUB_COUNT_3 = 1 << (3 * CUB_COUNT_LG);
 107     // cubic dt = 1 / count
 108     private static final float CUB_INV_COUNT = 1.0f / CUB_COUNT;
 109     // cubic dt^2 = 1 / count^2 = 1 / 4^countlg
 110     private static final float CUB_INV_COUNT_2 = 1.0f / CUB_COUNT_2;
 111     // cubic dt^3 = 1 / count^3 = 1 / 8^countlg
 112     private static final float CUB_INV_COUNT_3 = 1.0f / CUB_COUNT_3;
 113 
 114     // quad break into lines
 115     // quadratic error in subpixels
 116     private static final float QUAD_DEC_ERR_SUBPIX
 117         = MarlinProperties.getQuadDecD2() * (SUBPIXEL_POSITIONS_X / 8.0f); // 0.5 / 8th pixel
 118 
 119     // TestNonAARasterization (JDK-8170879): quads
 120     // bad paths (62916/100000 == 62,92%, 103818 bad pixels (avg = 1,65), 6514 warnings (avg = 0,10)
 121 // 2018
 122     // 0.50px  = bad paths (62915/100000 == 62,92%, 103810 bad pixels (avg = 1,65), 6512 warnings (avg = 0,10)
 123 
 124     // quadratic bind length to decrement step
 125     public static final float QUAD_DEC_BND
 126         = 8.0f * QUAD_DEC_ERR_SUBPIX;
 127 
 128 //////////////////////////////////////////////////////////////////////////////
 129 //  SCAN LINE
 130 //////////////////////////////////////////////////////////////////////////////
 131     // crossings ie subpixel edge x coordinates
 132     private int[] crossings;
 133     // auxiliary storage for crossings (merge sort)
 134     private int[] aux_crossings;
 135 
 136     // indices into the segment pointer lists. They indicate the "active"
 137     // sublist in the segment lists (the portion of the list that contains
 138     // all the segments that cross the next scan line).
 139     private int edgeCount;
 140     private int[] edgePtrs;
 141     // auxiliary storage for edge pointers (merge sort)
 142     private int[] aux_edgePtrs;


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



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


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


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












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


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


 685         this.x0 = sx;
 686         this.y0 = sy;
 687     }
 688 
 689     @Override
 690     public void lineTo(final float pix_x1, final float pix_y1) {
 691         final float x1 = tosubpixx(pix_x1);
 692         final float y1 = tosubpixy(pix_y1);
 693         addLine(x0, y0, x1, y1);
 694         x0 = x1;
 695         y0 = y1;
 696     }
 697 
 698     @Override
 699     public void curveTo(final float pix_x1, final float pix_y1,
 700                         final float pix_x2, final float pix_y2,
 701                         final float pix_x3, final float pix_y3)
 702     {
 703         final float xe = tosubpixx(pix_x3);
 704         final float ye = tosubpixy(pix_y3);
 705         curve.set(x0, y0,
 706                 tosubpixx(pix_x1), tosubpixy(pix_y1),
 707                 tosubpixx(pix_x2), tosubpixy(pix_y2),
 708                 xe, ye);
 709         curveBreakIntoLinesAndAdd(x0, y0, curve, xe, ye);
 710         x0 = xe;
 711         y0 = ye;
 712     }
 713 
 714     @Override
 715     public void quadTo(final float pix_x1, final float pix_y1,
 716                        final float pix_x2, final float pix_y2)
 717     {
 718         final float xe = tosubpixx(pix_x2);
 719         final float ye = tosubpixy(pix_y2);
 720         curve.set(x0, y0,
 721                 tosubpixx(pix_x1), tosubpixy(pix_y1),
 722                 xe, ye);
 723         quadBreakIntoLinesAndAdd(x0, y0, curve, xe, ye);
 724         x0 = xe;
 725         y0 = ye;
 726     }
 727 
 728     @Override
 729     public void closePath() {
 730         if (x0 != sx0 || y0 != sy0) {
 731             addLine(x0, y0, sx0, sy0);
 732             x0 = sx0;
 733             y0 = sy0;
 734         }
 735     }
 736 
 737     @Override
 738     public void pathDone() {
 739         closePath();
 740     }
 741 
 742     @Override


< prev index next >