< prev index next >

openjfx9/modules/javafx.graphics/src/main/java/com/sun/marlin/Renderer.java

Print this page

        

*** 21,70 **** * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ ! package sun.java2d.marlin; ! import java.util.Arrays; ! import sun.awt.geom.PathConsumer2D; ! import static sun.java2d.marlin.OffHeapArray.SIZE_INT; import jdk.internal.misc.Unsafe; ! final class Renderer implements PathConsumer2D, MarlinConst { static final boolean DISABLE_RENDER = false; - static final boolean ENABLE_BLOCK_FLAGS = MarlinProperties.isUseTileFlags(); - static final boolean ENABLE_BLOCK_FLAGS_HEURISTICS = MarlinProperties.isUseTileFlagsWithHeuristics(); - private static final int ALL_BUT_LSB = 0xfffffffe; private static final int ERR_STEP_MAX = 0x7fffffff; // = 2^31 - 1 private static final double POWER_2_TO_32 = 0x1.0p32; // use float to make tosubpix methods faster (no int to float conversion) ! public static final float F_SUBPIXEL_POSITIONS_X = (float) SUBPIXEL_POSITIONS_X; ! public static final float F_SUBPIXEL_POSITIONS_Y = (float) SUBPIXEL_POSITIONS_Y; ! public static final int SUBPIXEL_MASK_X = SUBPIXEL_POSITIONS_X - 1; ! public static final int SUBPIXEL_MASK_Y = SUBPIXEL_POSITIONS_Y - 1; ! ! // number of subpixels corresponding to a tile line ! private static final int SUBPIXEL_TILE ! = TILE_SIZE << SUBPIXEL_LG_POSITIONS_Y; // 2048 (pixelSize) pixels (height) x 8 subpixels = 64K static final int INITIAL_BUCKET_ARRAY = INITIAL_PIXEL_DIM * SUBPIXEL_POSITIONS_Y; ! // crossing capacity = edges count / 8 ~ 512 ! static final int INITIAL_CROSSING_COUNT = INITIAL_EDGES_COUNT >> 3; ! ! public static final int WIND_EVEN_ODD = 0; ! public static final int WIND_NON_ZERO = 1; // common to all types of input path segments. // OFFSET as bytes // only integer values: public static final long OFF_CURX_OR = 0; --- 21,58 ---- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ ! package com.sun.marlin; ! import static com.sun.marlin.OffHeapArray.SIZE_INT; import jdk.internal.misc.Unsafe; ! public final class Renderer implements MarlinRenderer, MarlinConst { static final boolean DISABLE_RENDER = false; private static final int ALL_BUT_LSB = 0xfffffffe; private static final int ERR_STEP_MAX = 0x7fffffff; // = 2^31 - 1 private static final double POWER_2_TO_32 = 0x1.0p32; // use float to make tosubpix methods faster (no int to float conversion) ! static final float F_SUBPIXEL_POSITIONS_X = (float) SUBPIXEL_POSITIONS_X; ! static final float F_SUBPIXEL_POSITIONS_Y = (float) SUBPIXEL_POSITIONS_Y; ! static final int SUBPIXEL_MASK_X = SUBPIXEL_POSITIONS_X - 1; ! static final int SUBPIXEL_MASK_Y = SUBPIXEL_POSITIONS_Y - 1; // 2048 (pixelSize) pixels (height) x 8 subpixels = 64K static final int INITIAL_BUCKET_ARRAY = INITIAL_PIXEL_DIM * SUBPIXEL_POSITIONS_Y; ! // crossing capacity = edges count / 4 ~ 1024 ! static final int INITIAL_CROSSING_COUNT = INITIAL_EDGES_COUNT >> 2; // common to all types of input path segments. // OFFSET as bytes // only integer values: public static final long OFF_CURX_OR = 0;
*** 78,101 **** public static final int SIZEOF_EDGE_BYTES = (int)(OFF_YMAX + SIZE_INT); // curve break into lines // cubic error in subpixels to decrement step private static final float CUB_DEC_ERR_SUBPIX ! = 2.5f * (NORM_SUBPIXELS / 8f); // 2.5 subpixel for typical 8x8 subpixels // cubic error in subpixels to increment step private static final float CUB_INC_ERR_SUBPIX ! = 1f * (NORM_SUBPIXELS / 8f); // 1 subpixel for typical 8x8 subpixels // cubic bind length to decrement step = 8 * error in subpixels - // pisces: 20 / 8 - // openjfx pisces: 8 / 3.2 // multiply by 8 = error scale factor: public static final float CUB_DEC_BND ! = 8f * CUB_DEC_ERR_SUBPIX; // 20f means 2.5 subpixel error // cubic bind length to increment step = 8 * error in subpixels public static final float CUB_INC_BND ! = 8f * CUB_INC_ERR_SUBPIX; // 8f means 1 subpixel error // cubic countlg public static final int CUB_COUNT_LG = 2; // cubic count = 2^countlg private static final int CUB_COUNT = 1 << CUB_COUNT_LG; --- 66,87 ---- public static final int SIZEOF_EDGE_BYTES = (int)(OFF_YMAX + SIZE_INT); // curve break into lines // cubic error in subpixels to decrement step private static final float CUB_DEC_ERR_SUBPIX ! = 1f * (NORM_SUBPIXELS / 8f); // 1 subpixel for typical 8x8 subpixels // cubic error in subpixels to increment step private static final float CUB_INC_ERR_SUBPIX ! = 0.4f * (NORM_SUBPIXELS / 8f); // 0.4 subpixel for typical 8x8 subpixels // cubic bind length to decrement step = 8 * error in subpixels // multiply by 8 = error scale factor: public static final float CUB_DEC_BND ! = 8f * CUB_DEC_ERR_SUBPIX; // cubic bind length to increment step = 8 * error in subpixels public static final float CUB_INC_BND ! = 8f * CUB_INC_ERR_SUBPIX; // cubic countlg public static final int CUB_COUNT_LG = 2; // cubic count = 2^countlg private static final int CUB_COUNT = 1 << CUB_COUNT_LG;
*** 114,126 **** // quadratic error in subpixels private static final float QUAD_DEC_ERR_SUBPIX = 1f * (NORM_SUBPIXELS / 8f); // 1 subpixel for typical 8x8 subpixels // quadratic bind length to decrement step = 8 * error in subpixels - // pisces and openjfx pisces: 32 public static final float QUAD_DEC_BND ! = 8f * QUAD_DEC_ERR_SUBPIX; // 8f means 1 subpixel error ////////////////////////////////////////////////////////////////////////////// // SCAN LINE ////////////////////////////////////////////////////////////////////////////// // crossings ie subpixel edge x coordinates --- 100,111 ---- // quadratic error in subpixels private static final float QUAD_DEC_ERR_SUBPIX = 1f * (NORM_SUBPIXELS / 8f); // 1 subpixel for typical 8x8 subpixels // quadratic bind length to decrement step = 8 * error in subpixels public static final float QUAD_DEC_BND ! = 8f * QUAD_DEC_ERR_SUBPIX; ////////////////////////////////////////////////////////////////////////////// // SCAN LINE ////////////////////////////////////////////////////////////////////////////// // crossings ie subpixel edge x coordinates
*** 163,180 **** private int[] edgeBuckets; private int[] edgeBucketCounts; // 2*newedges + (1 if pruning needed) // used range for edgeBuckets / edgeBucketCounts private int buckets_minY; private int buckets_maxY; - // sum of each edge delta Y (subpixels) - private int edgeSumDeltaY; // edgeBuckets ref (clean) private final IntArrayCache.Reference edgeBuckets_ref; // edgeBucketCounts ref (clean) private final IntArrayCache.Reference edgeBucketCounts_ref; // Flattens using adaptive forward differencing. This only carries out // one iteration of the AFD loop. All it does is update AFD variables (i.e. // X0, Y0, D*[X|Y], COUNT; not variables used for computing scanline crossings). private void quadBreakIntoLinesAndAdd(float x0, float y0, final Curve c, --- 148,165 ---- private int[] edgeBuckets; private int[] edgeBucketCounts; // 2*newedges + (1 if pruning needed) // used range for edgeBuckets / edgeBucketCounts private int buckets_minY; private int buckets_maxY; // edgeBuckets ref (clean) private final IntArrayCache.Reference edgeBuckets_ref; // edgeBucketCounts ref (clean) private final IntArrayCache.Reference edgeBucketCounts_ref; + boolean useRLE = false; + // Flattens using adaptive forward differencing. This only carries out // one iteration of the AFD loop. All it does is update AFD variables (i.e. // X0, Y0, D*[X|Y], COUNT; not variables used for computing scanline crossings). private void quadBreakIntoLinesAndAdd(float x0, float y0, final Curve c,
*** 482,494 **** _edgeBuckets[bucketIdx] = edgePtr; _edgeBucketCounts[bucketIdx] += 2; // 1 << 1 // last bit means edge end _edgeBucketCounts[lastCrossing - _boundsMinY] |= 0x1; - // update sum of delta Y (subpixels): - edgeSumDeltaY += (lastCrossing - firstCrossing); - // update free pointer (ie length in bytes) _edges.used += _SIZEOF_EDGE_BYTES; if (DO_MONITORS) { rdrCtx.stats.mon_rdr_addLine.stop(); --- 467,476 ----
*** 496,508 **** } // END EDGE LIST ////////////////////////////////////////////////////////////////////////////// - // Cache to store RLE-encoded coverage mask of the current primitive - final MarlinCache cache; - // Bounds of the drawing region, at subpixel precision. private int boundsMinX, boundsMinY, boundsMaxX, boundsMaxY; // Current winding rule private int windingRule; --- 478,487 ----
*** 548,559 **** // 2048 (pixelsize) pixel large alphaLine_ref = rdrCtx.newCleanIntArrayRef(INITIAL_AA_ARRAY); // 8K alphaLine = alphaLine_ref.initial; - this.cache = rdrCtx.cache; - crossings_ref = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K aux_crossings_ref = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K edgePtrs_ref = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K aux_edgePtrs_ref = rdrCtx.newDirtyIntArrayRef(INITIAL_CROSSING_COUNT); // 2K --- 527,536 ----
*** 564,577 **** blkFlags_ref = rdrCtx.newCleanIntArrayRef(INITIAL_ARRAY); // 1K = 1 tile line blkFlags = blkFlags_ref.initial; } ! Renderer init(final int pix_boundsX, final int pix_boundsY, final int pix_boundsWidth, final int pix_boundsHeight, ! final int windingRule) { ! this.windingRule = windingRule; // bounds as half-open intervals: minX <= x < maxX and minY <= y < maxY this.boundsMinX = pix_boundsX << SUBPIXEL_LG_POSITIONS_X; this.boundsMaxX = --- 541,554 ---- blkFlags_ref = rdrCtx.newCleanIntArrayRef(INITIAL_ARRAY); // 1K = 1 tile line blkFlags = blkFlags_ref.initial; } ! public Renderer init(final int pix_boundsX, final int pix_boundsY, final int pix_boundsWidth, final int pix_boundsHeight, ! final int windingRule) ! { this.windingRule = windingRule; // bounds as half-open intervals: minX <= x < maxX and minY <= y < maxY this.boundsMinX = pix_boundsX << SUBPIXEL_LG_POSITIONS_X; this.boundsMaxX =
*** 609,627 **** // reset used mark: edgeCount = 0; activeEdgeMaxUsed = 0; edges.used = 0; ! edgeSumDeltaY = 0; return this; // fluent API } /** * Disposes this renderer and recycle it clean up before reusing this instance */ ! void dispose() { if (DO_STATS) { rdrCtx.stats.stat_rdr_activeEdges.add(activeEdgeMaxUsed); rdrCtx.stats.stat_rdr_edges.add(edges.used); rdrCtx.stats.stat_rdr_edges_count.add(edges.used / SIZEOF_EDGE_BYTES); rdrCtx.stats.hist_rdr_edges_count.add(edges.used / SIZEOF_EDGE_BYTES); --- 586,606 ---- // reset used mark: edgeCount = 0; activeEdgeMaxUsed = 0; edges.used = 0; ! // reset bbox: ! bboxX0 = 0; ! bboxX1 = 0; return this; // fluent API } /** * Disposes this renderer and recycle it clean up before reusing this instance */ ! public void dispose() { if (DO_STATS) { rdrCtx.stats.stat_rdr_activeEdges.add(activeEdgeMaxUsed); rdrCtx.stats.stat_rdr_edges.add(edges.used); rdrCtx.stats.stat_rdr_edges_count.add(edges.used / SIZEOF_EDGE_BYTES); rdrCtx.stats.hist_rdr_edges_count.add(edges.used / SIZEOF_EDGE_BYTES);
*** 732,749 **** } @Override public void pathDone() { closePath(); - } ! @Override ! public long getNativeConsumer() { ! throw new InternalError("Renderer does not use a native consumer."); } ! private void _endRendering(final int ymin, final int ymax) { if (DISABLE_RENDER) { return; } // Get X bounds as true pixel boundaries to compute correct pixel coverage: --- 711,728 ---- } @Override public void pathDone() { closePath(); ! // call endRendering() to determine the boundaries: ! endRendering(); } ! private void _endRendering(final int ymin, final int ymax, ! final MarlinAlphaConsumer ac) ! { if (DISABLE_RENDER) { return; } // Get X bounds as true pixel boundaries to compute correct pixel coverage:
*** 754,764 **** // Useful when processing tile line by tile line final int[] _alpha = alphaLine; // local vars (performance): - final MarlinCache _cache = cache; final OffHeapArray _edges = edges; final int[] _edgeBuckets = edgeBuckets; final int[] _edgeBucketCounts = edgeBucketCounts; int[] _crossings = this.crossings; --- 733,742 ----
*** 1174,1184 **** if ((sum & 0x1) != 0) { // TODO: perform line clipping on left-right sides // to avoid such bound checks: x0 = (prev > bboxx0) ? prev : bboxx0; ! x1 = (curx < bboxx1) ? curx : bboxx1; if (x0 < x1) { x0 -= bboxx0; // turn x0, x1 from coords to indices x1 -= bboxx0; // in the alpha array. --- 1152,1169 ---- if ((sum & 0x1) != 0) { // TODO: perform line clipping on left-right sides // to avoid such bound checks: x0 = (prev > bboxx0) ? prev : bboxx0; ! ! if (curx < bboxx1) { ! x1 = curx; ! } else { ! x1 = bboxx1; ! // skip right side (fast exit loop): ! i = numCrossings; ! } if (x0 < x1) { x0 -= bboxx0; // turn x0, x1 from coords to indices x1 -= bboxx0; // in the alpha array.
*** 1191,1201 **** _alpha[pix_x ] += tmp; _alpha[pix_x + 1] -= tmp; if (useBlkFlags) { // flag used blocks: ! _blkFlags[pix_x >> _BLK_SIZE_LG] = 1; } } else { tmp = (x0 & _SUBPIXEL_MASK_X); _alpha[pix_x ] += (_SUBPIXEL_POSITIONS_X - tmp); --- 1176,1187 ---- _alpha[pix_x ] += tmp; _alpha[pix_x + 1] -= tmp; if (useBlkFlags) { // flag used blocks: ! _blkFlags[pix_x >> _BLK_SIZE_LG] = 1; ! _blkFlags[(pix_x + 1) >> _BLK_SIZE_LG] = 1; } } else { tmp = (x0 & _SUBPIXEL_MASK_X); _alpha[pix_x ] += (_SUBPIXEL_POSITIONS_X - tmp);
*** 1210,1221 **** _alpha[pix_xmax + 1] -= tmp; if (useBlkFlags) { // flag used blocks: ! _blkFlags[pix_x >> _BLK_SIZE_LG] = 1; ! _blkFlags[pix_xmax >> _BLK_SIZE_LG] = 1; } } } } --- 1196,1209 ---- _alpha[pix_xmax + 1] -= tmp; if (useBlkFlags) { // flag used blocks: ! _blkFlags[ pix_x >> _BLK_SIZE_LG] = 1; ! _blkFlags[(pix_x + 1) >> _BLK_SIZE_LG] = 1; ! _blkFlags[pix_xmax >> _BLK_SIZE_LG] = 1; ! _blkFlags[(pix_xmax + 1) >> _BLK_SIZE_LG] = 1; } } } }
*** 1235,1245 **** } } else { // TODO: perform line clipping on left-right sides // to avoid such bound checks: x0 = (prev > bboxx0) ? prev : bboxx0; ! x1 = (curx < bboxx1) ? curx : bboxx1; if (x0 < x1) { x0 -= bboxx0; // turn x0, x1 from coords to indices x1 -= bboxx0; // in the alpha array. --- 1223,1240 ---- } } else { // TODO: perform line clipping on left-right sides // to avoid such bound checks: x0 = (prev > bboxx0) ? prev : bboxx0; ! ! if (curx < bboxx1) { ! x1 = curx; ! } else { ! x1 = bboxx1; ! // skip right side (fast exit loop): ! i = numCrossings; ! } if (x0 < x1) { x0 -= bboxx0; // turn x0, x1 from coords to indices x1 -= bboxx0; // in the alpha array.
*** 1252,1262 **** _alpha[pix_x ] += tmp; _alpha[pix_x + 1] -= tmp; if (useBlkFlags) { // flag used blocks: ! _blkFlags[pix_x >> _BLK_SIZE_LG] = 1; } } else { tmp = (x0 & _SUBPIXEL_MASK_X); _alpha[pix_x ] += (_SUBPIXEL_POSITIONS_X - tmp); --- 1247,1258 ---- _alpha[pix_x ] += tmp; _alpha[pix_x + 1] -= tmp; if (useBlkFlags) { // flag used blocks: ! _blkFlags[pix_x >> _BLK_SIZE_LG] = 1; ! _blkFlags[(pix_x + 1) >> _BLK_SIZE_LG] = 1; } } else { tmp = (x0 & _SUBPIXEL_MASK_X); _alpha[pix_x ] += (_SUBPIXEL_POSITIONS_X - tmp);
*** 1271,1282 **** _alpha[pix_xmax + 1] -= tmp; if (useBlkFlags) { // flag used blocks: ! _blkFlags[pix_x >> _BLK_SIZE_LG] = 1; ! _blkFlags[pix_xmax >> _BLK_SIZE_LG] = 1; } } } prev = _MAX_VALUE; } --- 1267,1280 ---- _alpha[pix_xmax + 1] -= tmp; if (useBlkFlags) { // flag used blocks: ! _blkFlags[ pix_x >> _BLK_SIZE_LG] = 1; ! _blkFlags[(pix_x + 1) >> _BLK_SIZE_LG] = 1; ! _blkFlags[pix_xmax >> _BLK_SIZE_LG] = 1; ! _blkFlags[(pix_xmax + 1) >> _BLK_SIZE_LG] = 1; } } } prev = _MAX_VALUE; }
*** 1294,1316 **** } } // numCrossings > 0 // even if this last row had no crossings, alpha will be zeroed // from the last emitRow call. But this doesn't matter because ! // maxX < minX, so no row will be emitted to the MarlinCache. if ((y & _SUBPIXEL_MASK_Y) == _SUBPIXEL_MASK_Y) { lastY = y >> _SUBPIXEL_LG_POSITIONS_Y; // convert subpixel to pixel coordinate within boundaries: minX = FloatMath.max(minX, bboxx0) >> _SUBPIXEL_LG_POSITIONS_X; maxX = FloatMath.min(maxX, bboxx1) >> _SUBPIXEL_LG_POSITIONS_X; if (maxX >= minX) { // note: alpha array will be zeroed by copyAARow() ! // +2 because alpha [pix_minX; pix_maxX+1] // fix range [x0; x1[ ! copyAARow(_alpha, lastY, minX, maxX + 2, useBlkFlags); // speculative for next pixel row (scanline coherence): if (_enableBlkFlagsHeuristics) { // Use block flags if large pixel span and few crossings: // ie mean(distance between crossings) is larger than --- 1292,1317 ---- } } // numCrossings > 0 // even if this last row had no crossings, alpha will be zeroed // from the last emitRow call. But this doesn't matter because ! // maxX < minX, so no row will be emitted to the AlphaConsumer. if ((y & _SUBPIXEL_MASK_Y) == _SUBPIXEL_MASK_Y) { lastY = y >> _SUBPIXEL_LG_POSITIONS_Y; // convert subpixel to pixel coordinate within boundaries: minX = FloatMath.max(minX, bboxx0) >> _SUBPIXEL_LG_POSITIONS_X; maxX = FloatMath.min(maxX, bboxx1) >> _SUBPIXEL_LG_POSITIONS_X; if (maxX >= minX) { // note: alpha array will be zeroed by copyAARow() ! // +1 because alpha [pix_minX; pix_maxX[ // fix range [x0; x1[ ! // note: if x1=bboxx1, then alpha is written up to bboxx1+1 ! // inclusive: alpha[bboxx1] ignored, alpha[bboxx1+1] == 0 ! // (normally so never cleared below) ! copyAARow(_alpha, lastY, minX, maxX + 1, useBlkFlags, ac); // speculative for next pixel row (scanline coherence): if (_enableBlkFlagsHeuristics) { // Use block flags if large pixel span and few crossings: // ie mean(distance between crossings) is larger than
*** 1331,1341 **** rdrCtx.stats.hist_tile_generator_encoding_dist .add(maxX / tmp); } } } else { ! _cache.clearAARow(lastY); } minX = _MAX_VALUE; maxX = _MIN_VALUE; } } // scan line iterator --- 1332,1342 ---- rdrCtx.stats.hist_tile_generator_encoding_dist .add(maxX / tmp); } } } else { ! ac.clearAlphas(lastY); } minX = _MAX_VALUE; maxX = _MIN_VALUE; } } // scan line iterator
*** 1348,1362 **** minX = FloatMath.max(minX, bboxx0) >> _SUBPIXEL_LG_POSITIONS_X; maxX = FloatMath.min(maxX, bboxx1) >> _SUBPIXEL_LG_POSITIONS_X; if (maxX >= minX) { // note: alpha array will be zeroed by copyAARow() ! // +2 because alpha [pix_minX; pix_maxX+1] // fix range [x0; x1[ ! copyAARow(_alpha, y, minX, maxX + 2, useBlkFlags); } else if (y != lastY) { ! _cache.clearAARow(y); } // update member: edgeCount = numCrossings; prevUseBlkFlags = useBlkFlags; --- 1349,1366 ---- minX = FloatMath.max(minX, bboxx0) >> _SUBPIXEL_LG_POSITIONS_X; maxX = FloatMath.min(maxX, bboxx1) >> _SUBPIXEL_LG_POSITIONS_X; if (maxX >= minX) { // note: alpha array will be zeroed by copyAARow() ! // +1 because alpha [pix_minX; pix_maxX[ // fix range [x0; x1[ ! // note: if x1=bboxx1, then alpha is written up to bboxx1+1 ! // inclusive: alpha[bboxx1] ignored then cleared and ! // alpha[bboxx1+1] == 0 (normally so never cleared after) ! copyAARow(_alpha, y, minX, maxX + 1, useBlkFlags, ac); } else if (y != lastY) { ! ac.clearAlphas(y); } // update member: edgeCount = numCrossings; prevUseBlkFlags = useBlkFlags;
*** 1365,1380 **** // update max used mark activeEdgeMaxUsed = _arrayMaxUsed; } } ! boolean endRendering() { if (DO_MONITORS) { rdrCtx.stats.mon_rdr_endRendering.start(); } if (edgeMinY == Integer.MAX_VALUE) { ! return false; // undefined edges bounds } final int _boundsMinY = boundsMinY; final int _boundsMaxY = boundsMaxY; --- 1369,1384 ---- // update max used mark activeEdgeMaxUsed = _arrayMaxUsed; } } ! void endRendering() { if (DO_MONITORS) { rdrCtx.stats.mon_rdr_endRendering.start(); } if (edgeMinY == Integer.MAX_VALUE) { ! return; // undefined edges bounds } final int _boundsMinY = boundsMinY; final int _boundsMaxY = boundsMaxY;
*** 1403,1413 **** + "][" + spminY + " ... " + spmaxY + "]"); } // test clipping for shapes out of bounds if ((spminX > spmaxX) || (spminY > spmaxY)) { ! return false; } // half open intervals // inclusive: final int pminX = spminX >> SUBPIXEL_LG_POSITIONS_X; --- 1407,1417 ---- + "][" + spminY + " ... " + spmaxY + "]"); } // test clipping for shapes out of bounds if ((spminX > spmaxX) || (spminY > spmaxY)) { ! return; } // half open intervals // inclusive: final int pminX = spminX >> SUBPIXEL_LG_POSITIONS_X;
*** 1417,1439 **** final int pminY = spminY >> SUBPIXEL_LG_POSITIONS_Y; // exclusive: final int pmaxY = (spmaxY + SUBPIXEL_MASK_Y) >> SUBPIXEL_LG_POSITIONS_Y; // store BBox to answer ptg.getBBox(): ! this.cache.init(pminX, pminY, pmaxX, pmaxY, edgeSumDeltaY); // Heuristics for using block flags: if (ENABLE_BLOCK_FLAGS) { ! enableBlkFlags = this.cache.useRLE; prevUseBlkFlags = enableBlkFlags && !ENABLE_BLOCK_FLAGS_HEURISTICS; if (enableBlkFlags) { // ensure blockFlags array is large enough: // note: +2 to ensure enough space left at end ! final int nxTiles = ((pmaxX - pminX) >> TILE_SIZE_LG) + 2; ! if (nxTiles > INITIAL_ARRAY) { ! blkFlags = blkFlags_ref.getArray(nxTiles); } } } // memorize the rendering bounding box: --- 1421,1443 ---- final int pminY = spminY >> SUBPIXEL_LG_POSITIONS_Y; // exclusive: final int pmaxY = (spmaxY + SUBPIXEL_MASK_Y) >> SUBPIXEL_LG_POSITIONS_Y; // store BBox to answer ptg.getBBox(): ! initConsumer(pminX, pminY, pmaxX, pmaxY); // Heuristics for using block flags: if (ENABLE_BLOCK_FLAGS) { ! enableBlkFlags = this.useRLE; prevUseBlkFlags = enableBlkFlags && !ENABLE_BLOCK_FLAGS_HEURISTICS; if (enableBlkFlags) { // ensure blockFlags array is large enough: // note: +2 to ensure enough space left at end ! final int blkLen = ((pmaxX - pminX) >> BLOCK_SIZE_LG) + 2; ! if (blkLen > INITIAL_ARRAY) { ! blkFlags = blkFlags_ref.getArray(blkLen); } } } // memorize the rendering bounding box:
*** 1465,1519 **** if (DO_STATS) { rdrCtx.stats.stat_array_renderer_alphaline.add(width); } alphaLine = alphaLine_ref.getArray(width); } ! // process first tile line: ! endRendering(pminY); ! return true; } private int bbox_spminX, bbox_spmaxX, bbox_spminY, bbox_spmaxY; ! void endRendering(final int pminY) { if (DO_MONITORS) { rdrCtx.stats.mon_rdr_endRendering_Y.start(); } ! final int spminY = pminY << SUBPIXEL_LG_POSITIONS_Y; ! final int fixed_spminY = FloatMath.max(bbox_spminY, spminY); ! ! // avoid rendering for last call to nextTile() ! if (fixed_spminY < bbox_spmaxY) { ! // process a complete tile line ie scanlines for 32 rows ! final int spmaxY = FloatMath.min(bbox_spmaxY, spminY + SUBPIXEL_TILE); - // process tile line [0 - 32] - cache.resetTileLine(pminY); - - // Process only one tile line: - _endRendering(fixed_spminY, spmaxY); - } if (DO_MONITORS) { rdrCtx.stats.mon_rdr_endRendering_Y.stop(); } } void copyAARow(final int[] alphaRow, final int pix_y, final int pix_from, final int pix_to, ! final boolean useBlockFlags) { if (useBlockFlags) { if (DO_STATS) { rdrCtx.stats.hist_tile_generator_encoding.add(1); } ! cache.copyAARowRLE_WithBlockFlags(blkFlags, alphaRow, pix_y, pix_from, pix_to); } else { if (DO_STATS) { rdrCtx.stats.hist_tile_generator_encoding.add(0); } ! cache.copyAARowNoRLE(alphaRow, pix_y, pix_from, pix_to); } } } --- 1469,1576 ---- if (DO_STATS) { rdrCtx.stats.stat_array_renderer_alphaline.add(width); } alphaLine = alphaLine_ref.getArray(width); } + } ! void initConsumer(int minx, int miny, int maxx, int maxy) ! { ! // assert maxy >= miny && maxx >= minx; ! bboxX0 = minx; ! bboxX1 = maxx; ! bboxY0 = miny; ! bboxY1 = maxy; ! ! final int width = (maxx - minx); ! ! if (FORCE_NO_RLE) { ! useRLE = false; ! } else if (FORCE_RLE) { ! useRLE = true; ! } else { ! // heuristics: use both bbox area and complexity ! // ie number of primitives: ! // fast check min width: ! if (width <= RLE_MIN_WIDTH) { ! useRLE = false; ! } else { ! useRLE = true; ! } ! } } private int bbox_spminX, bbox_spmaxX, bbox_spminY, bbox_spmaxY; ! public void produceAlphas(final MarlinAlphaConsumer ac) { ! ac.setMaxAlpha(MAX_AA_ALPHA); ! ! if (enableBlkFlags && !ac.supportBlockFlags()) { ! // consumer does not support block flag optimization: ! enableBlkFlags = false; ! prevUseBlkFlags = false; ! } ! if (DO_MONITORS) { rdrCtx.stats.mon_rdr_endRendering_Y.start(); } ! // Process all scan lines: ! _endRendering(bbox_spminY, bbox_spmaxY, ac); if (DO_MONITORS) { rdrCtx.stats.mon_rdr_endRendering_Y.stop(); } } void copyAARow(final int[] alphaRow, final int pix_y, final int pix_from, final int pix_to, ! final boolean useBlockFlags, ! final MarlinAlphaConsumer ac) { + if (DO_MONITORS) { + rdrCtx.stats.mon_rdr_copyAARow.start(); + } + if (DO_STATS) { + rdrCtx.stats.stat_cache_rowAA.add(pix_to - pix_from); + } + if (useBlockFlags) { if (DO_STATS) { rdrCtx.stats.hist_tile_generator_encoding.add(1); } ! ac.setAndClearRelativeAlphas(blkFlags, alphaRow, pix_y, pix_from, pix_to); } else { if (DO_STATS) { rdrCtx.stats.hist_tile_generator_encoding.add(0); } ! ac.setAndClearRelativeAlphas(alphaRow, pix_y, pix_from, pix_to); ! } ! if (DO_MONITORS) { ! rdrCtx.stats.mon_rdr_copyAARow.stop(); } } + + // output pixel bounding box: + int bboxX0, bboxX1, bboxY0, bboxY1; + + @Override + public int getOutpixMinX() { + return bboxX0; + } + + @Override + public int getOutpixMaxX() { + return bboxX1; + } + + @Override + public int getOutpixMinY() { + return bboxY0; + } + + @Override + public int getOutpixMaxY() { + return bboxY1; + } }
< prev index next >