187 while (maxDD >= _DEC_BND) { |
187 while (maxDD >= _DEC_BND) { |
188 // divide step by half: |
188 // divide step by half: |
189 maxDD /= 4f; // error divided by 2^2 = 4 |
189 maxDD /= 4f; // error divided by 2^2 = 4 |
190 |
190 |
191 count <<= 1; |
191 count <<= 1; |
192 if (doStats) { |
192 if (DO_STATS) { |
193 RendererContext.stats.stat_rdr_quadBreak_dec.add(count); |
193 rdrCtx.stats.stat_rdr_quadBreak_dec.add(count); |
194 } |
194 } |
195 } |
195 } |
196 |
196 |
197 int nL = 0; // line count |
197 int nL = 0; // line count |
198 if (count > 1) { |
198 if (count > 1) { |
212 y1 = y0 + dy; |
212 y1 = y0 + dy; |
213 dy += ddy; |
213 dy += ddy; |
214 |
214 |
215 addLine(x0, y0, x1, y1); |
215 addLine(x0, y0, x1, y1); |
216 |
216 |
217 if (doStats) { nL++; } |
217 if (DO_STATS) { nL++; } |
218 x0 = x1; |
218 x0 = x1; |
219 y0 = y1; |
219 y0 = y1; |
220 } |
220 } |
221 } |
221 } |
222 addLine(x0, y0, x2, y2); |
222 addLine(x0, y0, x2, y2); |
223 |
223 |
224 if (doStats) { |
224 if (DO_STATS) { |
225 RendererContext.stats.stat_rdr_quadBreak.add(nL + 1); |
225 rdrCtx.stats.stat_rdr_quadBreak.add(nL + 1); |
226 } |
226 } |
227 } |
227 } |
228 |
228 |
229 // x0, y0 and x3,y3 are the endpoints of the curve. We could compute these |
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 |
230 // using c.xat(0),c.yat(0) and c.xat(1),c.yat(1), but this might introduce |
305 y1 = y3; |
305 y1 = y3; |
306 } |
306 } |
307 |
307 |
308 addLine(x0, y0, x1, y1); |
308 addLine(x0, y0, x1, y1); |
309 |
309 |
310 if (doStats) { nL++; } |
310 if (DO_STATS) { nL++; } |
311 x0 = x1; |
311 x0 = x1; |
312 y0 = y1; |
312 y0 = y1; |
313 } |
313 } |
314 if (doStats) { |
314 if (DO_STATS) { |
315 RendererContext.stats.stat_rdr_curveBreak.add(nL); |
315 rdrCtx.stats.stat_rdr_curveBreak.add(nL); |
316 } |
316 } |
317 } |
317 } |
318 |
318 |
319 private void addLine(float x1, float y1, float x2, float y2) { |
319 private void addLine(float x1, float y1, float x2, float y2) { |
320 if (doMonitors) { |
320 if (DO_MONITORS) { |
321 RendererContext.stats.mon_rdr_addLine.start(); |
321 rdrCtx.stats.mon_rdr_addLine.start(); |
322 } |
322 } |
323 if (doStats) { |
323 if (DO_STATS) { |
324 RendererContext.stats.stat_rdr_addLine.add(1); |
324 rdrCtx.stats.stat_rdr_addLine.add(1); |
325 } |
325 } |
326 int or = 1; // orientation of the line. 1 if y increases, 0 otherwise. |
326 int or = 1; // orientation of the line. 1 if y increases, 0 otherwise. |
327 if (y2 < y1) { |
327 if (y2 < y1) { |
328 or = 0; |
328 or = 0; |
329 float tmp = y2; |
329 float tmp = y2; |
347 final int lastCrossing = FloatMath.min(FloatMath.ceil_int(y2), boundsMaxY); |
347 final int lastCrossing = FloatMath.min(FloatMath.ceil_int(y2), boundsMaxY); |
348 |
348 |
349 /* skip horizontal lines in pixel space and clip edges |
349 /* skip horizontal lines in pixel space and clip edges |
350 out of y range [boundsMinY; boundsMaxY] */ |
350 out of y range [boundsMinY; boundsMaxY] */ |
351 if (firstCrossing >= lastCrossing) { |
351 if (firstCrossing >= lastCrossing) { |
352 if (doMonitors) { |
352 if (DO_MONITORS) { |
353 RendererContext.stats.mon_rdr_addLine.stop(); |
353 rdrCtx.stats.mon_rdr_addLine.stop(); |
354 } |
354 } |
355 if (doStats) { |
355 if (DO_STATS) { |
356 RendererContext.stats.stat_rdr_addLine_skip.add(1); |
356 rdrCtx.stats.stat_rdr_addLine_skip.add(1); |
357 } |
357 } |
358 return; |
358 return; |
359 } |
359 } |
360 |
360 |
361 // edge min/max X/Y are in subpixel space (inclusive) within bounds: |
361 // edge min/max X/Y are in subpixel space (inclusive) within bounds: |
403 // so doubling size is enough to add needed bytes |
403 // so doubling size is enough to add needed bytes |
404 // note: throw IOOB if neededSize > 2Gb: |
404 // note: throw IOOB if neededSize > 2Gb: |
405 final long edgeNewSize = ArrayCache.getNewLargeSize(_edges.length, |
405 final long edgeNewSize = ArrayCache.getNewLargeSize(_edges.length, |
406 edgePtr + _SIZEOF_EDGE_BYTES); |
406 edgePtr + _SIZEOF_EDGE_BYTES); |
407 |
407 |
408 if (doStats) { |
408 if (DO_STATS) { |
409 RendererContext.stats.stat_rdr_edges_resizes.add(edgeNewSize); |
409 rdrCtx.stats.stat_rdr_edges_resizes.add(edgeNewSize); |
410 } |
410 } |
411 _edges.resize(edgeNewSize); |
411 _edges.resize(edgeNewSize); |
412 } |
412 } |
413 |
413 |
414 |
414 |
415 final Unsafe _unsafe = OffHeapArray.unsafe; |
415 final Unsafe _unsafe = OffHeapArray.UNSAFE; |
416 final long SIZE_INT = 4L; |
416 final long SIZE_INT = 4L; |
417 long addr = _edges.address + edgePtr; |
417 long addr = _edges.address + edgePtr; |
418 |
418 |
419 // The x value must be bumped up to its position at the next HPC we will evaluate. |
419 // The x value must be bumped up to its position at the next HPC we will evaluate. |
420 // "firstcrossing" is the (sub)pixel number where the next crossing occurs |
420 // "firstcrossing" is the (sub)pixel number where the next crossing occurs |
484 edgeSumDeltaY += (lastCrossing - firstCrossing); |
484 edgeSumDeltaY += (lastCrossing - firstCrossing); |
485 |
485 |
486 // update free pointer (ie length in bytes) |
486 // update free pointer (ie length in bytes) |
487 _edges.used += _SIZEOF_EDGE_BYTES; |
487 _edges.used += _SIZEOF_EDGE_BYTES; |
488 |
488 |
489 if (doMonitors) { |
489 if (DO_MONITORS) { |
490 RendererContext.stats.mon_rdr_addLine.stop(); |
490 rdrCtx.stats.mon_rdr_addLine.stop(); |
491 } |
491 } |
492 } |
492 } |
493 |
493 |
494 // END EDGE LIST |
494 // END EDGE LIST |
495 ////////////////////////////////////////////////////////////////////////////// |
495 ////////////////////////////////////////////////////////////////////////////// |
550 (pix_boundsX + pix_boundsWidth) << SUBPIXEL_LG_POSITIONS_X; |
550 (pix_boundsX + pix_boundsWidth) << SUBPIXEL_LG_POSITIONS_X; |
551 this.boundsMinY = pix_boundsY << SUBPIXEL_LG_POSITIONS_Y; |
551 this.boundsMinY = pix_boundsY << SUBPIXEL_LG_POSITIONS_Y; |
552 this.boundsMaxY = |
552 this.boundsMaxY = |
553 (pix_boundsY + pix_boundsHeight) << SUBPIXEL_LG_POSITIONS_Y; |
553 (pix_boundsY + pix_boundsHeight) << SUBPIXEL_LG_POSITIONS_Y; |
554 |
554 |
555 if (doLogBounds) { |
555 if (DO_LOG_BOUNDS) { |
556 MarlinUtils.logInfo("boundsXY = [" + boundsMinX + " ... " |
556 MarlinUtils.logInfo("boundsXY = [" + boundsMinX + " ... " |
557 + boundsMaxX + "[ [" + boundsMinY + " ... " |
557 + boundsMaxX + "[ [" + boundsMinY + " ... " |
558 + boundsMaxY + "["); |
558 + boundsMaxY + "["); |
559 } |
559 } |
560 |
560 |
561 // see addLine: ceil(boundsMaxY) => boundsMaxY + 1 |
561 // see addLine: ceil(boundsMaxY) => boundsMaxY + 1 |
562 // +1 for edgeBucketCounts |
562 // +1 for edgeBucketCounts |
563 final int edgeBucketsLength = (boundsMaxY - boundsMinY) + 1; |
563 final int edgeBucketsLength = (boundsMaxY - boundsMinY) + 1; |
564 |
564 |
565 if (edgeBucketsLength > INITIAL_BUCKET_ARRAY) { |
565 if (edgeBucketsLength > INITIAL_BUCKET_ARRAY) { |
566 if (doStats) { |
566 if (DO_STATS) { |
567 RendererContext.stats.stat_array_renderer_edgeBuckets |
567 rdrCtx.stats.stat_array_renderer_edgeBuckets |
568 .add(edgeBucketsLength); |
568 .add(edgeBucketsLength); |
569 RendererContext.stats.stat_array_renderer_edgeBucketCounts |
569 rdrCtx.stats.stat_array_renderer_edgeBucketCounts |
570 .add(edgeBucketsLength); |
570 .add(edgeBucketsLength); |
571 } |
571 } |
572 edgeBuckets = rdrCtx.getIntArray(edgeBucketsLength); |
572 edgeBuckets = rdrCtx.getIntArray(edgeBucketsLength); |
573 edgeBucketCounts = rdrCtx.getIntArray(edgeBucketsLength); |
573 edgeBucketCounts = rdrCtx.getIntArray(edgeBucketsLength); |
574 } |
574 } |
590 |
590 |
591 /** |
591 /** |
592 * Disposes this renderer and recycle it clean up before reusing this instance |
592 * Disposes this renderer and recycle it clean up before reusing this instance |
593 */ |
593 */ |
594 void dispose() { |
594 void dispose() { |
595 if (doStats) { |
595 if (DO_STATS) { |
596 RendererContext.stats.stat_rdr_activeEdges.add(activeEdgeMaxUsed); |
596 rdrCtx.stats.stat_rdr_activeEdges.add(activeEdgeMaxUsed); |
597 RendererContext.stats.stat_rdr_edges.add(edges.used); |
597 rdrCtx.stats.stat_rdr_edges.add(edges.used); |
598 RendererContext.stats.stat_rdr_edges_count |
598 rdrCtx.stats.stat_rdr_edges_count |
599 .add(edges.used / SIZEOF_EDGE_BYTES); |
599 .add(edges.used / SIZEOF_EDGE_BYTES); |
600 } |
600 } |
601 if (doCleanDirty) { |
601 if (DO_CLEAN_DIRTY) { |
602 // Force zero-fill dirty arrays: |
602 // Force zero-fill dirty arrays: |
603 Arrays.fill(crossings, 0); |
603 Arrays.fill(crossings, 0); |
604 Arrays.fill(aux_crossings, 0); |
604 Arrays.fill(aux_crossings, 0); |
605 Arrays.fill(edgePtrs, 0); |
605 Arrays.fill(edgePtrs, 0); |
606 Arrays.fill(aux_edgePtrs, 0); |
606 Arrays.fill(aux_edgePtrs, 0); |
668 // At last: resize back off-heap edges to initial size |
668 // At last: resize back off-heap edges to initial size |
669 if (edges.length != INITIAL_EDGES_CAPACITY) { |
669 if (edges.length != INITIAL_EDGES_CAPACITY) { |
670 // note: may throw OOME: |
670 // note: may throw OOME: |
671 edges.resize(INITIAL_EDGES_CAPACITY); |
671 edges.resize(INITIAL_EDGES_CAPACITY); |
672 } |
672 } |
673 if (doCleanDirty) { |
673 if (DO_CLEAN_DIRTY) { |
674 // Force zero-fill dirty arrays: |
674 // Force zero-fill dirty arrays: |
675 edges.fill(BYTE_0); |
675 edges.fill(BYTE_0); |
676 } |
676 } |
677 if (doMonitors) { |
677 if (DO_MONITORS) { |
678 RendererContext.stats.mon_rdr_endRendering.stop(); |
678 rdrCtx.stats.mon_rdr_endRendering.stop(); |
679 } |
679 } |
680 } |
680 } |
681 |
681 |
682 private static float tosubpixx(final float pix_x) { |
682 private static float tosubpixx(final float pix_x) { |
683 return f_SUBPIXEL_POSITIONS_X * pix_x; |
683 return f_SUBPIXEL_POSITIONS_X * pix_x; |
791 |
791 |
792 final int _ALL_BUT_LSB = ALL_BUT_LSB; |
792 final int _ALL_BUT_LSB = ALL_BUT_LSB; |
793 final int _ERR_STEP_MAX = ERR_STEP_MAX; |
793 final int _ERR_STEP_MAX = ERR_STEP_MAX; |
794 |
794 |
795 // unsafe I/O: |
795 // unsafe I/O: |
796 final Unsafe _unsafe = OffHeapArray.unsafe; |
796 final Unsafe _unsafe = OffHeapArray.UNSAFE; |
797 final long addr0 = _edges.address; |
797 final long addr0 = _edges.address; |
798 long addr; |
798 long addr; |
799 final int _SUBPIXEL_LG_POSITIONS_X = SUBPIXEL_LG_POSITIONS_X; |
799 final int _SUBPIXEL_LG_POSITIONS_X = SUBPIXEL_LG_POSITIONS_X; |
800 final int _SUBPIXEL_LG_POSITIONS_Y = SUBPIXEL_LG_POSITIONS_Y; |
800 final int _SUBPIXEL_LG_POSITIONS_Y = SUBPIXEL_LG_POSITIONS_Y; |
801 final int _SUBPIXEL_MASK_X = SUBPIXEL_MASK_X; |
801 final int _SUBPIXEL_MASK_X = SUBPIXEL_MASK_X; |
854 // marker on previously sorted edges: |
854 // marker on previously sorted edges: |
855 prevNumCrossings = numCrossings; |
855 prevNumCrossings = numCrossings; |
856 |
856 |
857 // bucketCount indicates new edge / edge end: |
857 // bucketCount indicates new edge / edge end: |
858 if (bucketcount != 0) { |
858 if (bucketcount != 0) { |
859 if (doStats) { |
859 if (DO_STATS) { |
860 RendererContext.stats.stat_rdr_activeEdges_updates |
860 rdrCtx.stats.stat_rdr_activeEdges_updates |
861 .add(numCrossings); |
861 .add(numCrossings); |
862 } |
862 } |
863 |
863 |
864 // last bit set to 1 means that edges ends |
864 // last bit set to 1 means that edges ends |
865 if ((bucketcount & 0x1) != 0) { |
865 if ((bucketcount & 0x1) != 0) { |
880 } |
880 } |
881 |
881 |
882 ptrLen = bucketcount >> 1; // number of new edge |
882 ptrLen = bucketcount >> 1; // number of new edge |
883 |
883 |
884 if (ptrLen != 0) { |
884 if (ptrLen != 0) { |
885 if (doStats) { |
885 if (DO_STATS) { |
886 RendererContext.stats.stat_rdr_activeEdges_adds |
886 rdrCtx.stats.stat_rdr_activeEdges_adds |
887 .add(ptrLen); |
887 .add(ptrLen); |
888 if (ptrLen > 10) { |
888 if (ptrLen > 10) { |
889 RendererContext.stats.stat_rdr_activeEdges_adds_high |
889 rdrCtx.stats.stat_rdr_activeEdges_adds_high |
890 .add(ptrLen); |
890 .add(ptrLen); |
891 } |
891 } |
892 } |
892 } |
893 ptrEnd = numCrossings + ptrLen; |
893 ptrEnd = numCrossings + ptrLen; |
894 |
894 |
895 if (edgePtrsLen < ptrEnd) { |
895 if (edgePtrsLen < ptrEnd) { |
896 if (doStats) { |
896 if (DO_STATS) { |
897 RendererContext.stats.stat_array_renderer_edgePtrs |
897 rdrCtx.stats.stat_array_renderer_edgePtrs |
898 .add(ptrEnd); |
898 .add(ptrEnd); |
899 } |
899 } |
900 this.edgePtrs = _edgePtrs |
900 this.edgePtrs = _edgePtrs |
901 = rdrCtx.widenDirtyIntArray(_edgePtrs, numCrossings, |
901 = rdrCtx.widenDirtyIntArray(_edgePtrs, numCrossings, |
902 ptrEnd); |
902 ptrEnd); |
906 if (_aux_edgePtrs != aux_edgePtrs_initial) { |
906 if (_aux_edgePtrs != aux_edgePtrs_initial) { |
907 rdrCtx.putDirtyIntArray(_aux_edgePtrs); |
907 rdrCtx.putDirtyIntArray(_aux_edgePtrs); |
908 } |
908 } |
909 // use ArrayCache.getNewSize() to use the same growing |
909 // use ArrayCache.getNewSize() to use the same growing |
910 // factor than widenDirtyIntArray(): |
910 // factor than widenDirtyIntArray(): |
911 if (doStats) { |
911 if (DO_STATS) { |
912 RendererContext.stats.stat_array_renderer_aux_edgePtrs |
912 rdrCtx.stats.stat_array_renderer_aux_edgePtrs |
913 .add(ptrEnd); |
913 .add(ptrEnd); |
914 } |
914 } |
915 this.aux_edgePtrs = _aux_edgePtrs |
915 this.aux_edgePtrs = _aux_edgePtrs |
916 = rdrCtx.getDirtyIntArray( |
916 = rdrCtx.getDirtyIntArray( |
917 ArrayCache.getNewSize(numCrossings, ptrEnd) |
917 ArrayCache.getNewSize(numCrossings, ptrEnd) |
934 if (crossingsLen < numCrossings) { |
934 if (crossingsLen < numCrossings) { |
935 // Get larger array: |
935 // Get larger array: |
936 if (_crossings != crossings_initial) { |
936 if (_crossings != crossings_initial) { |
937 rdrCtx.putDirtyIntArray(_crossings); |
937 rdrCtx.putDirtyIntArray(_crossings); |
938 } |
938 } |
939 if (doStats) { |
939 if (DO_STATS) { |
940 RendererContext.stats.stat_array_renderer_crossings |
940 rdrCtx.stats.stat_array_renderer_crossings |
941 .add(numCrossings); |
941 .add(numCrossings); |
942 } |
942 } |
943 this.crossings = _crossings |
943 this.crossings = _crossings |
944 = rdrCtx.getDirtyIntArray(numCrossings); |
944 = rdrCtx.getDirtyIntArray(numCrossings); |
945 |
945 |
946 // Get larger auxiliary storage: |
946 // Get larger auxiliary storage: |
947 if (_aux_crossings != aux_crossings_initial) { |
947 if (_aux_crossings != aux_crossings_initial) { |
948 rdrCtx.putDirtyIntArray(_aux_crossings); |
948 rdrCtx.putDirtyIntArray(_aux_crossings); |
949 } |
949 } |
950 if (doStats) { |
950 if (DO_STATS) { |
951 RendererContext.stats.stat_array_renderer_aux_crossings |
951 rdrCtx.stats.stat_array_renderer_aux_crossings |
952 .add(numCrossings); |
952 .add(numCrossings); |
953 } |
953 } |
954 this.aux_crossings = _aux_crossings |
954 this.aux_crossings = _aux_crossings |
955 = rdrCtx.getDirtyIntArray(numCrossings); |
955 = rdrCtx.getDirtyIntArray(numCrossings); |
956 |
956 |
957 crossingsLen = _crossings.length; |
957 crossingsLen = _crossings.length; |
958 } |
958 } |
959 if (doStats) { |
959 if (DO_STATS) { |
960 // update max used mark |
960 // update max used mark |
961 if (numCrossings > _arrayMaxUsed) { |
961 if (numCrossings > _arrayMaxUsed) { |
962 _arrayMaxUsed = numCrossings; |
962 _arrayMaxUsed = numCrossings; |
963 } |
963 } |
964 } |
964 } |
970 /* |
970 /* |
971 * thresholds to switch to optimized merge sort |
971 * thresholds to switch to optimized merge sort |
972 * for newly added edges + final merge pass. |
972 * for newly added edges + final merge pass. |
973 */ |
973 */ |
974 if ((ptrLen < 10) || (numCrossings < 40)) { |
974 if ((ptrLen < 10) || (numCrossings < 40)) { |
975 if (doStats) { |
975 if (DO_STATS) { |
976 RendererContext.stats.hist_rdr_crossings |
976 rdrCtx.stats.hist_rdr_crossings |
977 .add(numCrossings); |
977 .add(numCrossings); |
978 RendererContext.stats.hist_rdr_crossings_adds |
978 rdrCtx.stats.hist_rdr_crossings_adds |
979 .add(ptrLen); |
979 .add(ptrLen); |
980 } |
980 } |
981 |
981 |
982 /* |
982 /* |
983 * threshold to use binary insertion sort instead of |
983 * threshold to use binary insertion sort instead of |
1016 // Manual carry handling: |
1016 // Manual carry handling: |
1017 // keep sign and carry bit only and ignore last bit (preserve orientation): |
1017 // keep sign and carry bit only and ignore last bit (preserve orientation): |
1018 _unsafe.putInt(addr, curx - ((err >> 30) & _ALL_BUT_LSB)); |
1018 _unsafe.putInt(addr, curx - ((err >> 30) & _ALL_BUT_LSB)); |
1019 _unsafe.putInt(addr + _OFF_ERROR, (err & _ERR_STEP_MAX)); |
1019 _unsafe.putInt(addr + _OFF_ERROR, (err & _ERR_STEP_MAX)); |
1020 |
1020 |
1021 if (doStats) { |
1021 if (DO_STATS) { |
1022 RendererContext.stats.stat_rdr_crossings_updates |
1022 rdrCtx.stats.stat_rdr_crossings_updates |
1023 .add(numCrossings); |
1023 .add(numCrossings); |
1024 } |
1024 } |
1025 |
1025 |
1026 // insertion sort of crossings: |
1026 // insertion sort of crossings: |
1027 if (cross < lastCross) { |
1027 if (cross < lastCross) { |
1028 if (doStats) { |
1028 if (DO_STATS) { |
1029 RendererContext.stats.stat_rdr_crossings_sorts |
1029 rdrCtx.stats.stat_rdr_crossings_sorts |
1030 .add(i); |
1030 .add(i); |
1031 } |
1031 } |
1032 |
1032 |
1033 /* use binary search for newly added edges |
1033 /* use binary search for newly added edges |
1034 in crossings if arrays are large enough */ |
1034 in crossings if arrays are large enough */ |
1035 if (useBinarySearch && (i >= prevNumCrossings)) { |
1035 if (useBinarySearch && (i >= prevNumCrossings)) { |
1036 if (doStats) { |
1036 if (DO_STATS) { |
1037 RendererContext.stats. |
1037 rdrCtx.stats. |
1038 stat_rdr_crossings_bsearch.add(i); |
1038 stat_rdr_crossings_bsearch.add(i); |
1039 } |
1039 } |
1040 low = 0; |
1040 low = 0; |
1041 high = i - 1; |
1041 high = i - 1; |
1042 |
1042 |
1075 } else { |
1075 } else { |
1076 _crossings[i] = lastCross = cross; |
1076 _crossings[i] = lastCross = cross; |
1077 } |
1077 } |
1078 } |
1078 } |
1079 } else { |
1079 } else { |
1080 if (doStats) { |
1080 if (DO_STATS) { |
1081 RendererContext.stats.stat_rdr_crossings_msorts |
1081 rdrCtx.stats.stat_rdr_crossings_msorts |
1082 .add(numCrossings); |
1082 .add(numCrossings); |
1083 RendererContext.stats.hist_rdr_crossings_ratio |
1083 rdrCtx.stats.hist_rdr_crossings_ratio |
1084 .add((1000 * ptrLen) / numCrossings); |
1084 .add((1000 * ptrLen) / numCrossings); |
1085 RendererContext.stats.hist_rdr_crossings_msorts |
1085 rdrCtx.stats.hist_rdr_crossings_msorts |
1086 .add(numCrossings); |
1086 .add(numCrossings); |
1087 RendererContext.stats.hist_rdr_crossings_msorts_adds |
1087 rdrCtx.stats.hist_rdr_crossings_msorts_adds |
1088 .add(ptrLen); |
1088 .add(ptrLen); |
1089 } |
1089 } |
1090 |
1090 |
1091 // Copy sorted data in auxiliary arrays |
1091 // Copy sorted data in auxiliary arrays |
1092 // and perform insertion sort on almost sorted data |
1092 // and perform insertion sort on almost sorted data |
1122 // Manual carry handling: |
1122 // Manual carry handling: |
1123 // keep sign and carry bit only and ignore last bit (preserve orientation): |
1123 // keep sign and carry bit only and ignore last bit (preserve orientation): |
1124 _unsafe.putInt(addr, curx - ((err >> 30) & _ALL_BUT_LSB)); |
1124 _unsafe.putInt(addr, curx - ((err >> 30) & _ALL_BUT_LSB)); |
1125 _unsafe.putInt(addr + _OFF_ERROR, (err & _ERR_STEP_MAX)); |
1125 _unsafe.putInt(addr + _OFF_ERROR, (err & _ERR_STEP_MAX)); |
1126 |
1126 |
1127 if (doStats) { |
1127 if (DO_STATS) { |
1128 RendererContext.stats.stat_rdr_crossings_updates |
1128 rdrCtx.stats.stat_rdr_crossings_updates |
1129 .add(numCrossings); |
1129 .add(numCrossings); |
1130 } |
1130 } |
1131 |
1131 |
1132 if (i >= prevNumCrossings) { |
1132 if (i >= prevNumCrossings) { |
1133 // simply store crossing as edgePtrs is in-place: |
1133 // simply store crossing as edgePtrs is in-place: |
1134 // will be copied and sorted efficiently by mergesort later: |
1134 // will be copied and sorted efficiently by mergesort later: |
1135 _crossings[i] = cross; |
1135 _crossings[i] = cross; |
1136 |
1136 |
1137 } else if (cross < lastCross) { |
1137 } else if (cross < lastCross) { |
1138 if (doStats) { |
1138 if (DO_STATS) { |
1139 RendererContext.stats.stat_rdr_crossings_sorts |
1139 rdrCtx.stats.stat_rdr_crossings_sorts |
1140 .add(i); |
1140 .add(i); |
1141 } |
1141 } |
1142 |
1142 |
1143 // (straight) insertion sort of crossings: |
1143 // (straight) insertion sort of crossings: |
1144 j = i - 1; |
1144 j = i - 1; |
1354 // => shift numCrossings by 1 |
1354 // => shift numCrossings by 1 |
1355 // condition = (width / (numCrossings - 1)) > blockSize |
1355 // condition = (width / (numCrossings - 1)) > blockSize |
1356 useBlkFlags = (maxX > _BLK_SIZE) && (maxX > |
1356 useBlkFlags = (maxX > _BLK_SIZE) && (maxX > |
1357 (((numCrossings >> stroking) - 1) << _BLK_SIZE_LG)); |
1357 (((numCrossings >> stroking) - 1) << _BLK_SIZE_LG)); |
1358 |
1358 |
1359 if (doStats) { |
1359 if (DO_STATS) { |
1360 tmp = FloatMath.max(1, |
1360 tmp = FloatMath.max(1, |
1361 ((numCrossings >> stroking) - 1)); |
1361 ((numCrossings >> stroking) - 1)); |
1362 RendererContext.stats.hist_tile_generator_encoding_dist |
1362 rdrCtx.stats.hist_tile_generator_encoding_dist |
1363 .add(maxX / tmp); |
1363 .add(maxX / tmp); |
1364 } |
1364 } |
1365 } |
1365 } |
1366 } else { |
1366 } else { |
1367 _cache.clearAARow(lastY); |
1367 _cache.clearAARow(lastY); |
1390 |
1390 |
1391 // update member: |
1391 // update member: |
1392 edgeCount = numCrossings; |
1392 edgeCount = numCrossings; |
1393 prevUseBlkFlags = useBlkFlags; |
1393 prevUseBlkFlags = useBlkFlags; |
1394 |
1394 |
1395 if (doStats) { |
1395 if (DO_STATS) { |
1396 // update max used mark |
1396 // update max used mark |
1397 activeEdgeMaxUsed = _arrayMaxUsed; |
1397 activeEdgeMaxUsed = _arrayMaxUsed; |
1398 } |
1398 } |
1399 } |
1399 } |
1400 |
1400 |
1401 boolean endRendering() { |
1401 boolean endRendering() { |
1402 if (doMonitors) { |
1402 if (DO_MONITORS) { |
1403 RendererContext.stats.mon_rdr_endRendering.start(); |
1403 rdrCtx.stats.mon_rdr_endRendering.start(); |
1404 } |
1404 } |
1405 if (edgeMinY == Integer.MAX_VALUE) { |
1405 if (edgeMinY == Integer.MAX_VALUE) { |
1406 return false; // undefined edges bounds |
1406 return false; // undefined edges bounds |
1407 } |
1407 } |
1408 |
1408 |
1425 maxY = _boundsMaxY; |
1425 maxY = _boundsMaxY; |
1426 } |
1426 } |
1427 buckets_minY = spminY - _boundsMinY; |
1427 buckets_minY = spminY - _boundsMinY; |
1428 buckets_maxY = maxY - _boundsMinY; |
1428 buckets_maxY = maxY - _boundsMinY; |
1429 |
1429 |
1430 if (doLogBounds) { |
1430 if (DO_LOG_BOUNDS) { |
1431 MarlinUtils.logInfo("edgesXY = [" + edgeMinX + " ... " + edgeMaxX |
1431 MarlinUtils.logInfo("edgesXY = [" + edgeMinX + " ... " + edgeMaxX |
1432 + "][" + edgeMinY + " ... " + edgeMaxY + "]"); |
1432 + "][" + edgeMinY + " ... " + edgeMaxY + "]"); |
1433 MarlinUtils.logInfo("spXY = [" + spminX + " ... " + spmaxX |
1433 MarlinUtils.logInfo("spXY = [" + spminX + " ... " + spmaxX |
1434 + "][" + spminY + " ... " + spmaxY + "]"); |
1434 + "][" + spminY + " ... " + spmaxY + "]"); |
1435 } |
1435 } |
1477 // inclusive: |
1477 // inclusive: |
1478 bbox_spminY = spminY; |
1478 bbox_spminY = spminY; |
1479 // exclusive: |
1479 // exclusive: |
1480 bbox_spmaxY = FloatMath.min(spmaxY + 1, pmaxY << SUBPIXEL_LG_POSITIONS_Y); |
1480 bbox_spmaxY = FloatMath.min(spmaxY + 1, pmaxY << SUBPIXEL_LG_POSITIONS_Y); |
1481 |
1481 |
1482 if (doLogBounds) { |
1482 if (DO_LOG_BOUNDS) { |
1483 MarlinUtils.logInfo("pXY = [" + pminX + " ... " + pmaxX |
1483 MarlinUtils.logInfo("pXY = [" + pminX + " ... " + pmaxX |
1484 + "[ [" + pminY + " ... " + pmaxY + "["); |
1484 + "[ [" + pminY + " ... " + pmaxY + "["); |
1485 MarlinUtils.logInfo("bbox_spXY = [" + bbox_spminX + " ... " |
1485 MarlinUtils.logInfo("bbox_spXY = [" + bbox_spminX + " ... " |
1486 + bbox_spmaxX + "[ [" + bbox_spminY + " ... " |
1486 + bbox_spmaxX + "[ [" + bbox_spminY + " ... " |
1487 + bbox_spmaxY + "["); |
1487 + bbox_spmaxY + "["); |
1491 // add 2 to better deal with the last pixel in a pixel row. |
1491 // add 2 to better deal with the last pixel in a pixel row. |
1492 final int width = (pmaxX - pminX) + 2; |
1492 final int width = (pmaxX - pminX) + 2; |
1493 |
1493 |
1494 // Useful when processing tile line by tile line |
1494 // Useful when processing tile line by tile line |
1495 if (width > INITIAL_AA_ARRAY) { |
1495 if (width > INITIAL_AA_ARRAY) { |
1496 if (doStats) { |
1496 if (DO_STATS) { |
1497 RendererContext.stats.stat_array_renderer_alphaline |
1497 rdrCtx.stats.stat_array_renderer_alphaline |
1498 .add(width); |
1498 .add(width); |
1499 } |
1499 } |
1500 alphaLine = rdrCtx.getIntArray(width); |
1500 alphaLine = rdrCtx.getIntArray(width); |
1501 } |
1501 } |
1502 |
1502 |
1507 } |
1507 } |
1508 |
1508 |
1509 private int bbox_spminX, bbox_spmaxX, bbox_spminY, bbox_spmaxY; |
1509 private int bbox_spminX, bbox_spmaxX, bbox_spminY, bbox_spmaxY; |
1510 |
1510 |
1511 void endRendering(final int pminY) { |
1511 void endRendering(final int pminY) { |
1512 if (doMonitors) { |
1512 if (DO_MONITORS) { |
1513 RendererContext.stats.mon_rdr_endRendering_Y.start(); |
1513 rdrCtx.stats.mon_rdr_endRendering_Y.start(); |
1514 } |
1514 } |
1515 |
1515 |
1516 final int spminY = pminY << SUBPIXEL_LG_POSITIONS_Y; |
1516 final int spminY = pminY << SUBPIXEL_LG_POSITIONS_Y; |
1517 final int fixed_spminY = FloatMath.max(bbox_spminY, spminY); |
1517 final int fixed_spminY = FloatMath.max(bbox_spminY, spminY); |
1518 |
1518 |
1525 cache.resetTileLine(pminY); |
1525 cache.resetTileLine(pminY); |
1526 |
1526 |
1527 // Process only one tile line: |
1527 // Process only one tile line: |
1528 _endRendering(fixed_spminY, spmaxY); |
1528 _endRendering(fixed_spminY, spmaxY); |
1529 } |
1529 } |
1530 if (doMonitors) { |
1530 if (DO_MONITORS) { |
1531 RendererContext.stats.mon_rdr_endRendering_Y.stop(); |
1531 rdrCtx.stats.mon_rdr_endRendering_Y.stop(); |
1532 } |
1532 } |
1533 } |
1533 } |
1534 |
1534 |
1535 private boolean enableBlkFlags = false; |
1535 private boolean enableBlkFlags = false; |
1536 private boolean prevUseBlkFlags = false; |
1536 private boolean prevUseBlkFlags = false; |
1542 void copyAARow(final int[] alphaRow, |
1542 void copyAARow(final int[] alphaRow, |
1543 final int pix_y, final int pix_from, final int pix_to, |
1543 final int pix_y, final int pix_from, final int pix_to, |
1544 final boolean useBlockFlags) |
1544 final boolean useBlockFlags) |
1545 { |
1545 { |
1546 if (useBlockFlags) { |
1546 if (useBlockFlags) { |
1547 if (doStats) { |
1547 if (DO_STATS) { |
1548 RendererContext.stats.hist_tile_generator_encoding.add(1); |
1548 rdrCtx.stats.hist_tile_generator_encoding.add(1); |
1549 } |
1549 } |
1550 cache.copyAARowRLE_WithBlockFlags(blkFlags, alphaRow, pix_y, pix_from, pix_to); |
1550 cache.copyAARowRLE_WithBlockFlags(blkFlags, alphaRow, pix_y, pix_from, pix_to); |
1551 } else { |
1551 } else { |
1552 if (doStats) { |
1552 if (DO_STATS) { |
1553 RendererContext.stats.hist_tile_generator_encoding.add(0); |
1553 rdrCtx.stats.hist_tile_generator_encoding.add(0); |
1554 } |
1554 } |
1555 cache.copyAARowNoRLE(alphaRow, pix_y, pix_from, pix_to); |
1555 cache.copyAARowNoRLE(alphaRow, pix_y, pix_from, pix_to); |
1556 } |
1556 } |
1557 } |
1557 } |
1558 } |
1558 } |