42
43 // crossing capacity = edges count / 4 ~ 1024
44 static final int INITIAL_CROSSING_COUNT = INITIAL_EDGES_COUNT >> 2;
45
46 // common to all types of input path segments.
47 // OFFSET as bytes
48 // only integer values:
49 public static final long OFF_CURX_OR = 0;
50 public static final long OFF_ERROR = OFF_CURX_OR + SIZE_INT;
51 public static final long OFF_BUMP_X = OFF_ERROR + SIZE_INT;
52 public static final long OFF_BUMP_ERR = OFF_BUMP_X + SIZE_INT;
53 public static final long OFF_NEXT = OFF_BUMP_ERR + SIZE_INT;
54 public static final long OFF_YMAX = OFF_NEXT + SIZE_INT;
55
56 // size of one edge in bytes
57 public static final int SIZEOF_EDGE_BYTES = (int)(OFF_YMAX + SIZE_INT);
58
59 // curve break into lines
60 // cubic error in subpixels to decrement step
61 private static final float CUB_DEC_ERR_SUBPIX
62 = 1f * (1f / 8f); // 1 pixel for typical 1x1 subpixels
63 // cubic error in subpixels to increment step
64 private static final float CUB_INC_ERR_SUBPIX
65 = 0.4f * (1f / 8f); // 0.4 pixel for typical 1x1 subpixels
66
67 // cubic bind length to decrement step = 8 * error in subpixels
68 // multiply by 8 = error scale factor:
69 public static final float CUB_DEC_BND
70 = 8f * CUB_DEC_ERR_SUBPIX;
71 // cubic bind length to increment step = 8 * error in subpixels
72 public static final float CUB_INC_BND
73 = 8f * CUB_INC_ERR_SUBPIX;
74
75 // cubic countlg
76 public static final int CUB_COUNT_LG = 2;
77 // cubic count = 2^countlg
78 private static final int CUB_COUNT = 1 << CUB_COUNT_LG;
79 // cubic count^2 = 4^countlg
80 private static final int CUB_COUNT_2 = 1 << (2 * CUB_COUNT_LG);
81 // cubic count^3 = 8^countlg
82 private static final int CUB_COUNT_3 = 1 << (3 * CUB_COUNT_LG);
83 // cubic dt = 1 / count
84 private static final float CUB_INV_COUNT = 1f / CUB_COUNT;
85 // cubic dt^2 = 1 / count^2 = 1 / 4^countlg
86 private static final float CUB_INV_COUNT_2 = 1f / CUB_COUNT_2;
87 // cubic dt^3 = 1 / count^3 = 1 / 8^countlg
88 private static final float CUB_INV_COUNT_3 = 1f / CUB_COUNT_3;
89
90 // quad break into lines
91 // quadratic error in subpixels
92 private static final float QUAD_DEC_ERR_SUBPIX
93 = 1f * (1f / 8f); // 1 pixel for typical 1x1 subpixels
94
95 // quadratic bind length to decrement step = 8 * error in subpixels
96 public static final float QUAD_DEC_BND
97 = 8f * QUAD_DEC_ERR_SUBPIX;
98
99 //////////////////////////////////////////////////////////////////////////////
100 // SCAN LINE
101 //////////////////////////////////////////////////////////////////////////////
102 // crossings ie subpixel edge x coordinates
103 private int[] crossings;
104 // auxiliary storage for crossings (merge sort)
105 private int[] aux_crossings;
106
107 // indices into the segment pointer lists. They indicate the "active"
108 // sublist in the segment lists (the portion of the list that contains
109 // all the segments that cross the next scan line).
110 private int edgeCount;
111 private int[] edgePtrs;
112 // auxiliary storage for edge pointers (merge sort)
113 private int[] aux_edgePtrs;
114
115 // max used for both edgePtrs and crossings (stats only)
142 private int buckets_minY;
143 private int buckets_maxY;
144
145 // edgeBuckets ref (clean)
146 private final IntArrayCache.Reference edgeBuckets_ref;
147 // edgeBucketCounts ref (clean)
148 private final IntArrayCache.Reference edgeBucketCounts_ref;
149
150 boolean useRLE = false;
151
152 // Flattens using adaptive forward differencing. This only carries out
153 // one iteration of the AFD loop. All it does is update AFD variables (i.e.
154 // X0, Y0, D*[X|Y], COUNT; not variables used for computing scanline crossings).
155 private void quadBreakIntoLinesAndAdd(float x0, float y0,
156 final Curve c,
157 final float x2, final float y2)
158 {
159 int count = 1; // dt = 1 / count
160
161 // maximum(ddX|Y) = norm(dbx, dby) * dt^2 (= 1)
162 float maxDD = FloatMath.max(Math.abs(c.dbx), Math.abs(c.dby));
163
164 final float _DEC_BND = QUAD_DEC_BND;
165
166 while (maxDD >= _DEC_BND) {
167 // divide step by half:
168 maxDD /= 4f; // error divided by 2^2 = 4
169
170 count <<= 1;
171 if (DO_STATS) {
172 rdrCtx.stats.stat_rdr_quadBreak_dec.add(count);
173 }
174 }
175
176 int nL = 0; // line count
177 if (count > 1) {
178 final float icount = 1f / count; // dt
179 final float icount2 = icount * icount; // dt^2
180
181 final float ddx = c.dbx * icount2;
182 final float ddy = c.dby * icount2;
221
222 // the dx and dy refer to forward differencing variables, not the last
223 // coefficients of the "points" polynomial
224 float dddx, dddy, ddx, ddy, dx, dy;
225 dddx = 2f * c.dax * icount3;
226 dddy = 2f * c.day * icount3;
227 ddx = dddx + c.dbx * icount2;
228 ddy = dddy + c.dby * icount2;
229 dx = c.ax * icount3 + c.bx * icount2 + c.cx * icount;
230 dy = c.ay * icount3 + c.by * icount2 + c.cy * icount;
231
232 // we use x0, y0 to walk the line
233 float x1 = x0, y1 = y0;
234 int nL = 0; // line count
235
236 final float _DEC_BND = CUB_DEC_BND;
237 final float _INC_BND = CUB_INC_BND;
238
239 while (count > 0) {
240 // divide step by half:
241 while (Math.abs(ddx) >= _DEC_BND || Math.abs(ddy) >= _DEC_BND) {
242 dddx /= 8f;
243 dddy /= 8f;
244 ddx = ddx/4f - dddx;
245 ddy = ddy/4f - dddy;
246 dx = (dx - ddx) / 2f;
247 dy = (dy - ddy) / 2f;
248
249 count <<= 1;
250 if (DO_STATS) {
251 rdrCtx.stats.stat_rdr_curveBreak_dec.add(count);
252 }
253 }
254
255 // double step:
256 // TODO: why use first derivative dX|Y instead of second ddX|Y ?
257 // both scale changes should use speed or acceleration to have the same metric.
258
259 // can only do this on even "count" values, because we must divide count by 2
260 while (count % 2 == 0
261 && Math.abs(dx) <= _INC_BND && Math.abs(dy) <= _INC_BND)
262 {
263 dx = 2f * dx + ddx;
264 dy = 2f * dy + ddy;
265 ddx = 4f * (ddx + dddx);
266 ddy = 4f * (ddy + dddy);
267 dddx *= 8f;
268 dddy *= 8f;
269
270 count >>= 1;
271 if (DO_STATS) {
272 rdrCtx.stats.stat_rdr_curveBreak_inc.add(count);
273 }
274 }
275 if (--count > 0) {
276 x1 += dx;
277 dx += ddx;
278 ddx += dddx;
279 y1 += dy;
280 dy += ddy;
281 ddy += dddy;
|
42
43 // crossing capacity = edges count / 4 ~ 1024
44 static final int INITIAL_CROSSING_COUNT = INITIAL_EDGES_COUNT >> 2;
45
46 // common to all types of input path segments.
47 // OFFSET as bytes
48 // only integer values:
49 public static final long OFF_CURX_OR = 0;
50 public static final long OFF_ERROR = OFF_CURX_OR + SIZE_INT;
51 public static final long OFF_BUMP_X = OFF_ERROR + SIZE_INT;
52 public static final long OFF_BUMP_ERR = OFF_BUMP_X + SIZE_INT;
53 public static final long OFF_NEXT = OFF_BUMP_ERR + SIZE_INT;
54 public static final long OFF_YMAX = OFF_NEXT + SIZE_INT;
55
56 // size of one edge in bytes
57 public static final int SIZEOF_EDGE_BYTES = (int)(OFF_YMAX + SIZE_INT);
58
59 // curve break into lines
60 // cubic error in subpixels to decrement step
61 private static final float CUB_DEC_ERR_SUBPIX
62 = 1f * (1f / 8f); // 1 pixel
63 // cubic error in subpixels to increment step
64 private static final float CUB_INC_ERR_SUBPIX
65 = 0.4f * (1f / 8f); // 0.4 pixel
66
67 // bad paths (59294/100000 == 59,29%, 94335 bad pixels (avg = 1,59), 3966 warnings (avg = 0,07)
68
69 // cubic bind length to decrement step
70 public static final float CUB_DEC_BND
71 = 8f * CUB_DEC_ERR_SUBPIX;
72 // cubic bind length to increment step
73 public static final float CUB_INC_BND
74 = 8f * CUB_INC_ERR_SUBPIX;
75
76 // cubic countlg
77 public static final int CUB_COUNT_LG = 2;
78 // cubic count = 2^countlg
79 private static final int CUB_COUNT = 1 << CUB_COUNT_LG;
80 // cubic count^2 = 4^countlg
81 private static final int CUB_COUNT_2 = 1 << (2 * CUB_COUNT_LG);
82 // cubic count^3 = 8^countlg
83 private static final int CUB_COUNT_3 = 1 << (3 * CUB_COUNT_LG);
84 // cubic dt = 1 / count
85 private static final float CUB_INV_COUNT = 1f / CUB_COUNT;
86 // cubic dt^2 = 1 / count^2 = 1 / 4^countlg
87 private static final float CUB_INV_COUNT_2 = 1f / CUB_COUNT_2;
88 // cubic dt^3 = 1 / count^3 = 1 / 8^countlg
89 private static final float CUB_INV_COUNT_3 = 1f / CUB_COUNT_3;
90
91 // quad break into lines
92 // quadratic error in subpixels
93 private static final float QUAD_DEC_ERR_SUBPIX
94 = 0.5f * (1f / 8f); // 0.5 pixel
95
96 // bad paths (62916/100000 == 62,92%, 103818 bad pixels (avg = 1,65), 6514 warnings (avg = 0,10)
97
98 // quadratic bind length to decrement step
99 public static final float QUAD_DEC_BND
100 = 8f * QUAD_DEC_ERR_SUBPIX;
101
102 //////////////////////////////////////////////////////////////////////////////
103 // SCAN LINE
104 //////////////////////////////////////////////////////////////////////////////
105 // crossings ie subpixel edge x coordinates
106 private int[] crossings;
107 // auxiliary storage for crossings (merge sort)
108 private int[] aux_crossings;
109
110 // indices into the segment pointer lists. They indicate the "active"
111 // sublist in the segment lists (the portion of the list that contains
112 // all the segments that cross the next scan line).
113 private int edgeCount;
114 private int[] edgePtrs;
115 // auxiliary storage for edge pointers (merge sort)
116 private int[] aux_edgePtrs;
117
118 // max used for both edgePtrs and crossings (stats only)
145 private int buckets_minY;
146 private int buckets_maxY;
147
148 // edgeBuckets ref (clean)
149 private final IntArrayCache.Reference edgeBuckets_ref;
150 // edgeBucketCounts ref (clean)
151 private final IntArrayCache.Reference edgeBucketCounts_ref;
152
153 boolean useRLE = false;
154
155 // Flattens using adaptive forward differencing. This only carries out
156 // one iteration of the AFD loop. All it does is update AFD variables (i.e.
157 // X0, Y0, D*[X|Y], COUNT; not variables used for computing scanline crossings).
158 private void quadBreakIntoLinesAndAdd(float x0, float y0,
159 final Curve c,
160 final float x2, final float y2)
161 {
162 int count = 1; // dt = 1 / count
163
164 // maximum(ddX|Y) = norm(dbx, dby) * dt^2 (= 1)
165 float maxDD = Math.abs(c.dbx) + Math.abs(c.dby);
166
167 final float _DEC_BND = QUAD_DEC_BND;
168
169 while (maxDD >= _DEC_BND) {
170 // divide step by half:
171 maxDD /= 4f; // error divided by 2^2 = 4
172
173 count <<= 1;
174 if (DO_STATS) {
175 rdrCtx.stats.stat_rdr_quadBreak_dec.add(count);
176 }
177 }
178
179 int nL = 0; // line count
180 if (count > 1) {
181 final float icount = 1f / count; // dt
182 final float icount2 = icount * icount; // dt^2
183
184 final float ddx = c.dbx * icount2;
185 final float ddy = c.dby * icount2;
224
225 // the dx and dy refer to forward differencing variables, not the last
226 // coefficients of the "points" polynomial
227 float dddx, dddy, ddx, ddy, dx, dy;
228 dddx = 2f * c.dax * icount3;
229 dddy = 2f * c.day * icount3;
230 ddx = dddx + c.dbx * icount2;
231 ddy = dddy + c.dby * icount2;
232 dx = c.ax * icount3 + c.bx * icount2 + c.cx * icount;
233 dy = c.ay * icount3 + c.by * icount2 + c.cy * icount;
234
235 // we use x0, y0 to walk the line
236 float x1 = x0, y1 = y0;
237 int nL = 0; // line count
238
239 final float _DEC_BND = CUB_DEC_BND;
240 final float _INC_BND = CUB_INC_BND;
241
242 while (count > 0) {
243 // divide step by half:
244 while (Math.abs(ddx) + Math.abs(ddy) >= _DEC_BND) {
245 dddx /= 8f;
246 dddy /= 8f;
247 ddx = ddx/4f - dddx;
248 ddy = ddy/4f - dddy;
249 dx = (dx - ddx) / 2f;
250 dy = (dy - ddy) / 2f;
251
252 count <<= 1;
253 if (DO_STATS) {
254 rdrCtx.stats.stat_rdr_curveBreak_dec.add(count);
255 }
256 }
257
258 // double step:
259 // TODO: why use first derivative dX|Y instead of second ddX|Y ?
260 // both scale changes should use speed or acceleration to have the same metric.
261
262 // can only do this on even "count" values, because we must divide count by 2
263 while (count % 2 == 0
264 && Math.abs(dx) + Math.abs(dy) <= _INC_BND)
265 {
266 dx = 2f * dx + ddx;
267 dy = 2f * dy + ddy;
268 ddx = 4f * (ddx + dddx);
269 ddy = 4f * (ddy + dddy);
270 dddx *= 8f;
271 dddy *= 8f;
272
273 count >>= 1;
274 if (DO_STATS) {
275 rdrCtx.stats.stat_rdr_curveBreak_inc.add(count);
276 }
277 }
278 if (--count > 0) {
279 x1 += dx;
280 dx += ddx;
281 ddx += dddx;
282 y1 += dy;
283 dy += ddy;
284 ddy += dddy;
|