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