Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(395)

Side by Side Diff: src/core/SkScan_Hairline.cpp

Issue 1092483003: Revert of Speeup hairline curves (quads and cubics) (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/core/SkGeometry.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1
1 /* 2 /*
2 * Copyright 2006 The Android Open Source Project 3 * Copyright 2006 The Android Open Source Project
3 * 4 *
4 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 6 * found in the LICENSE file.
6 */ 7 */
7 8
9
8 #include "SkScan.h" 10 #include "SkScan.h"
9 #include "SkBlitter.h" 11 #include "SkBlitter.h"
10 #include "SkRasterClip.h" 12 #include "SkRasterClip.h"
11 #include "SkFDot6.h" 13 #include "SkFDot6.h"
12 #include "SkLineClipper.h" 14 #include "SkLineClipper.h"
13 15
14 static void horiline(int x, int stopx, SkFixed fy, SkFixed dy, 16 static void horiline(int x, int stopx, SkFixed fy, SkFixed dy,
15 SkBlitter* blitter) { 17 SkBlitter* blitter) {
16 SkASSERT(x < stopx); 18 SkASSERT(x < stopx);
17 19
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 blitter->blitH(r.fLeft, r.fTop, width); // top 185 blitter->blitH(r.fLeft, r.fTop, width); // top
184 blitter->blitRect(r.fLeft, r.fTop + 1, 1, height - 2); // left 186 blitter->blitRect(r.fLeft, r.fTop + 1, 1, height - 2); // left
185 blitter->blitRect(r.fRight - 1, r.fTop + 1, 1, height - 2); // right 187 blitter->blitRect(r.fRight - 1, r.fTop + 1, 1, height - 2); // right
186 blitter->blitH(r.fLeft, r.fBottom - 1, width); // bottom 188 blitter->blitH(r.fLeft, r.fBottom - 1, width); // bottom
187 } 189 }
188 190
189 /////////////////////////////////////////////////////////////////////////////// 191 ///////////////////////////////////////////////////////////////////////////////
190 192
191 #include "SkPath.h" 193 #include "SkPath.h"
192 #include "SkGeometry.h" 194 #include "SkGeometry.h"
193 #include "SkNx.h"
194
195 #define kMaxCubicSubdivideLevel 6
196 #define kMaxQuadSubdivideLevel 5
197 195
198 static int compute_int_quad_dist(const SkPoint pts[3]) { 196 static int compute_int_quad_dist(const SkPoint pts[3]) {
199 // compute the vector between the control point ([1]) and the middle of the 197 // compute the vector between the control point ([1]) and the middle of the
200 // line connecting the start and end ([0] and [2]) 198 // line connecting the start and end ([0] and [2])
201 SkScalar dx = SkScalarHalf(pts[0].fX + pts[2].fX) - pts[1].fX; 199 SkScalar dx = SkScalarHalf(pts[0].fX + pts[2].fX) - pts[1].fX;
202 SkScalar dy = SkScalarHalf(pts[0].fY + pts[2].fY) - pts[1].fY; 200 SkScalar dy = SkScalarHalf(pts[0].fY + pts[2].fY) - pts[1].fY;
203 // we want everyone to be positive 201 // we want everyone to be positive
204 dx = SkScalarAbs(dx); 202 dx = SkScalarAbs(dx);
205 dy = SkScalarAbs(dy); 203 dy = SkScalarAbs(dy);
206 // convert to whole pixel values (use ceiling to be conservative) 204 // convert to whole pixel values (use ceiling to be conservative)
207 int idx = SkScalarCeilToInt(dx); 205 int idx = SkScalarCeilToInt(dx);
208 int idy = SkScalarCeilToInt(dy); 206 int idy = SkScalarCeilToInt(dy);
209 // use the cheap approx for distance 207 // use the cheap approx for distance
210 if (idx > idy) { 208 if (idx > idy) {
211 return idx + (idy >> 1); 209 return idx + (idy >> 1);
212 } else { 210 } else {
213 return idy + (idx >> 1); 211 return idy + (idx >> 1);
214 } 212 }
215 } 213 }
216 214
217 static void hairquad(const SkPoint pts[3], const SkRegion* clip, 215 static void hairquad(const SkPoint pts[3], const SkRegion* clip,
218 SkBlitter* blitter, int level, SkScan::HairRgnProc lineproc ) { 216 SkBlitter* blitter, int level, SkScan::HairRgnProc lineproc ) {
219 SkASSERT(level <= kMaxQuadSubdivideLevel);
220
221 #ifdef SK_SUPPORT_LEGACY_BLITANTIH2V2
222 if (level > 0) { 217 if (level > 0) {
223 SkPoint tmp[5]; 218 SkPoint tmp[5];
224 219
225 SkChopQuadAtHalf(pts, tmp); 220 SkChopQuadAtHalf(pts, tmp);
226 hairquad(tmp, clip, blitter, level - 1, lineproc); 221 hairquad(tmp, clip, blitter, level - 1, lineproc);
227 hairquad(&tmp[2], clip, blitter, level - 1, lineproc); 222 hairquad(&tmp[2], clip, blitter, level - 1, lineproc);
228 } else { 223 } else {
229 SkPoint tmp[] = { pts[0], pts[2] }; 224 SkPoint tmp[] = { pts[0], pts[2] };
230 lineproc(tmp, 2, clip, blitter); 225 lineproc(tmp, 2, clip, blitter);
231 } 226 }
232 #else
233 SkPoint coeff[3];
234 SkQuadToCoeff(pts, coeff);
235
236 const int lines = 1 << level;
237 Sk2s t(0);
238 Sk2s dt(SK_Scalar1 / lines);
239
240 SkPoint tmp[(1 << kMaxQuadSubdivideLevel) + 1];
241 SkASSERT((unsigned)lines < SK_ARRAY_COUNT(tmp));
242
243 tmp[0] = pts[0];
244 Sk2s A = Sk2s::Load(&coeff[0].fX);
245 Sk2s B = Sk2s::Load(&coeff[1].fX);
246 Sk2s C = Sk2s::Load(&coeff[2].fX);
247 for (int i = 1; i < lines; ++i) {
248 t += dt;
249 ((A * t + B) * t + C).store(&tmp[i].fX);
250 }
251 tmp[lines] = pts[2];
252 lineproc(tmp, lines + 1, clip, blitter);
253 #endif
254 } 227 }
255 228
256 #ifndef SK_SUPPORT_LEGACY_BLITANTIH2V2 229 static void haircubic(const SkPoint pts[4], const SkRegion* clip,
257 static inline Sk2s abs(const Sk2s& value) {
258 return Sk2s::Max(value, -value);
259 }
260
261 static inline SkScalar max_component(const Sk2s& value) {
262 SkScalar components[2];
263 value.store(components);
264 return SkTMax(components[0], components[1]);
265 }
266
267 static inline int compute_cubic_segs(const SkPoint pts[4]) {
268 Sk2s p0 = from_point(pts[0]);
269 Sk2s p1 = from_point(pts[1]);
270 Sk2s p2 = from_point(pts[2]);
271 Sk2s p3 = from_point(pts[3]);
272
273 const Sk2s oneThird(1.0f / 3.0f);
274 const Sk2s twoThird(2.0f / 3.0f);
275
276 Sk2s p13 = oneThird * p3 + twoThird * p0;
277 Sk2s p23 = oneThird * p0 + twoThird * p3;
278
279 SkScalar diff = max_component(Sk2s::Max(abs(p1 - p13), abs(p2 - p23)));
280 SkScalar tol = SK_Scalar1 / 8;
281
282 for (int i = 0; i < kMaxCubicSubdivideLevel; ++i) {
283 if (diff < tol) {
284 return 1 << i;
285 }
286 tol *= 4;
287 }
288 return 1 << kMaxCubicSubdivideLevel;
289 }
290
291 static bool lt_90(SkPoint p0, SkPoint pivot, SkPoint p2) {
292 return SkVector::DotProduct(p0 - pivot, p2 - pivot) >= 0;
293 }
294
295 // The off-curve points are "inside" the limits of the on-curve pts
296 static bool quick_cubic_niceness_check(const SkPoint pts[4]) {
297 return lt_90(pts[1], pts[0], pts[3]) &&
298 lt_90(pts[2], pts[0], pts[3]) &&
299 lt_90(pts[1], pts[3], pts[0]) &&
300 lt_90(pts[2], pts[3], pts[0]);
301 }
302
303 static void hair_cubic(const SkPoint pts[4], const SkRegion* clip, SkBlitter* bl itter,
304 SkScan::HairRgnProc lineproc) {
305 const int lines = compute_cubic_segs(pts);
306 SkASSERT(lines > 0);
307 if (1 == lines) {
308 SkPoint tmp[2] = { pts[0], pts[3] };
309 lineproc(tmp, 2, clip, blitter);
310 return;
311 }
312
313 SkPoint coeff[4];
314 SkCubicToCoeff(pts, coeff);
315
316 const Sk2s dt(SK_Scalar1 / lines);
317 Sk2s t(0);
318
319 SkPoint tmp[(1 << kMaxCubicSubdivideLevel) + 1];
320 SkASSERT((unsigned)lines < SK_ARRAY_COUNT(tmp));
321
322 tmp[0] = pts[0];
323 Sk2s A = Sk2s::Load(&coeff[0].fX);
324 Sk2s B = Sk2s::Load(&coeff[1].fX);
325 Sk2s C = Sk2s::Load(&coeff[2].fX);
326 Sk2s D = Sk2s::Load(&coeff[3].fX);
327 for (int i = 1; i < lines; ++i) {
328 t += dt;
329 (((A * t + B) * t + C) * t + D).store(&tmp[i].fX);
330 }
331 tmp[lines] = pts[3];
332 lineproc(tmp, lines + 1, clip, blitter);
333 }
334 #endif
335
336 static inline void haircubic(const SkPoint pts[4], const SkRegion* clip,
337 SkBlitter* blitter, int level, SkScan::HairRgnProc linepro c) { 230 SkBlitter* blitter, int level, SkScan::HairRgnProc linepro c) {
338 #ifdef SK_SUPPORT_LEGACY_BLITANTIH2V2
339 if (level > 0) { 231 if (level > 0) {
340 SkPoint tmp[7]; 232 SkPoint tmp[7];
341 233
342 SkChopCubicAt(pts, tmp, SK_Scalar1/2); 234 SkChopCubicAt(pts, tmp, SK_Scalar1/2);
343 haircubic(tmp, clip, blitter, level - 1, lineproc); 235 haircubic(tmp, clip, blitter, level - 1, lineproc);
344 haircubic(&tmp[3], clip, blitter, level - 1, lineproc); 236 haircubic(&tmp[3], clip, blitter, level - 1, lineproc);
345 } else { 237 } else {
346 SkPoint tmp[] = { pts[0], pts[3] }; 238 SkPoint tmp[] = { pts[0], pts[3] };
347 lineproc(tmp, 2, clip, blitter); 239 lineproc(tmp, 2, clip, blitter);
348 } 240 }
349 #else 241 }
350 if (quick_cubic_niceness_check(pts)) {
351 hair_cubic(pts, clip, blitter, lineproc);
352 } else {
353 SkPoint tmp[13];
354 SkScalar tValues[3];
355 242
356 int count = SkChopCubicAtMaxCurvature(pts, tmp, tValues); 243 #define kMaxCubicSubdivideLevel 6
357 for (int i = 0; i < count; i++) { 244 #define kMaxQuadSubdivideLevel 5
358 hair_cubic(&tmp[i * 3], clip, blitter, lineproc);
359 }
360 }
361 #endif
362 }
363 245
364 static int compute_quad_level(const SkPoint pts[3]) { 246 static int compute_quad_level(const SkPoint pts[3]) {
365 int d = compute_int_quad_dist(pts); 247 int d = compute_int_quad_dist(pts);
366 /* quadratics approach the line connecting their start and end points 248 /* quadratics approach the line connecting their start and end points
367 4x closer with each subdivision, so we compute the number of 249 4x closer with each subdivision, so we compute the number of
368 subdivisions to be the minimum need to get that distance to be less 250 subdivisions to be the minimum need to get that distance to be less
369 than a pixel. 251 than a pixel.
370 */ 252 */
371 int level = (33 - SkCLZ(d)) >> 1; 253 int level = (33 - SkCLZ(d)) >> 1;
372 // sanity check on level (from the previous version) 254 // sanity check on level (from the previous version)
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 const SkScalar tol = SK_Scalar1 / 4; 304 const SkScalar tol = SK_Scalar1 / 4;
423 const SkPoint* quadPts = converter.computeQuads(pts, 305 const SkPoint* quadPts = converter.computeQuads(pts,
424 iter.conicWeight(), tol); 306 iter.conicWeight(), tol);
425 for (int i = 0; i < converter.countQuads(); ++i) { 307 for (int i = 0; i < converter.countQuads(); ++i) {
426 int level = compute_quad_level(quadPts); 308 int level = compute_quad_level(quadPts);
427 hairquad(quadPts, clip, blitter, level, lineproc); 309 hairquad(quadPts, clip, blitter, level, lineproc);
428 quadPts += 2; 310 quadPts += 2;
429 } 311 }
430 break; 312 break;
431 } 313 }
432 case SkPath::kCubic_Verb: { 314 case SkPath::kCubic_Verb:
433 haircubic(pts, clip, blitter, kMaxCubicSubdivideLevel, lineproc) ; 315 haircubic(pts, clip, blitter, kMaxCubicSubdivideLevel, lineproc) ;
434 } break; 316 break;
435 case SkPath::kClose_Verb: 317 case SkPath::kClose_Verb:
436 break; 318 break;
437 case SkPath::kDone_Verb: 319 case SkPath::kDone_Verb:
438 break; 320 break;
439 } 321 }
440 } 322 }
441 } 323 }
442 324
443 void SkScan::HairPath(const SkPath& path, const SkRasterClip& clip, SkBlitter* b litter) { 325 void SkScan::HairPath(const SkPath& path, const SkRasterClip& clip, SkBlitter* b litter) {
444 hair_path(path, clip, blitter, SkScan::HairLineRgn); 326 hair_path(path, clip, blitter, SkScan::HairLineRgn);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
518 400
519 SkAAClipBlitterWrapper wrap; 401 SkAAClipBlitterWrapper wrap;
520 if (!clip.quickContains(r.roundOut().makeOutset(1, 1))) { 402 if (!clip.quickContains(r.roundOut().makeOutset(1, 1))) {
521 wrap.init(clip, blitter); 403 wrap.init(clip, blitter);
522 blitter = wrap.getBlitter(); 404 blitter = wrap.getBlitter();
523 clipRgn = &wrap.getRgn(); 405 clipRgn = &wrap.getRgn();
524 } 406 }
525 AntiHairLineRgn(pts, count, clipRgn, blitter); 407 AntiHairLineRgn(pts, count, clipRgn, blitter);
526 } 408 }
527 } 409 }
OLDNEW
« no previous file with comments | « src/core/SkGeometry.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698