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

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

Issue 1303873003: fix cubic clip in y (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fix override Created 5 years, 4 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 | « gm/cubicpaths.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 /*
3 * Copyright 2009 The Android Open Source Project 3 * Copyright 2009 The Android Open Source Project
4 * 4 *
5 * 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
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 9
10 #include "SkEdgeClipper.h" 10 #include "SkEdgeClipper.h"
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 } 218 }
219 219
220 *fCurrVerb = SkPath::kDone_Verb; 220 *fCurrVerb = SkPath::kDone_Verb;
221 fCurrPoint = fPoints; 221 fCurrPoint = fPoints;
222 fCurrVerb = fVerbs; 222 fCurrVerb = fVerbs;
223 return SkPath::kDone_Verb != fVerbs[0]; 223 return SkPath::kDone_Verb != fVerbs[0];
224 } 224 }
225 225
226 /////////////////////////////////////////////////////////////////////////////// 226 ///////////////////////////////////////////////////////////////////////////////
227 227
228 // Modify pts[] in place so that it is clipped in Y to the clip rect 228 static SkScalar mono_cubic_closestT(const SkScalar src[], SkScalar x) {
229 static void chop_cubic_in_Y(SkPoint pts[4], const SkRect& clip) {
230
231 // are we partially above
232 if (pts[0].fY < clip.fTop) {
233 SkPoint tmp[7];
234 if (SkChopMonoCubicAtY(pts, clip.fTop, tmp)) {
235 // tmp[3, 4].fY should all be to the below clip.fTop.
236 // Since we can't trust the numerics of
237 // the chopper, we force those conditions now
238 tmp[3].fY = clip.fTop;
239 clamp_ge(tmp[4].fY, clip.fTop);
240
241 pts[0] = tmp[3];
242 pts[1] = tmp[4];
243 pts[2] = tmp[5];
244 } else {
245 // if chopMonoCubicAtY failed, then we may have hit inexact numerics
246 // so we just clamp against the top
247 for (int i = 0; i < 4; i++) {
248 clamp_ge(pts[i].fY, clip.fTop);
249 }
250 }
251 }
252
253 // are we partially below
254 if (pts[3].fY > clip.fBottom) {
255 SkPoint tmp[7];
256 if (SkChopMonoCubicAtY(pts, clip.fBottom, tmp)) {
257 tmp[3].fY = clip.fBottom;
258 clamp_le(tmp[2].fY, clip.fBottom);
259
260 pts[1] = tmp[1];
261 pts[2] = tmp[2];
262 pts[3] = tmp[3];
263 } else {
264 // if chopMonoCubicAtY failed, then we may have hit inexact numerics
265 // so we just clamp against the bottom
266 for (int i = 0; i < 4; i++) {
267 clamp_le(pts[i].fY, clip.fBottom);
268 }
269 }
270 }
271 }
272
273 static void chop_mono_cubic_at_x(SkPoint pts[4], SkScalar x, SkPoint tmp[7]) {
274 if (SkChopMonoCubicAtX(pts, x, tmp)) {
275 return;
276 }
277 SkScalar t = 0.5f; 229 SkScalar t = 0.5f;
278 SkScalar lastT; 230 SkScalar lastT;
279 SkScalar bestT SK_INIT_TO_AVOID_WARNING; 231 SkScalar bestT SK_INIT_TO_AVOID_WARNING;
280 SkScalar step = 0.25f; 232 SkScalar step = 0.25f;
281 SkScalar D = pts[0].fX; 233 SkScalar D = src[0];
282 SkScalar A = pts[3].fX + 3*(pts[1].fX - pts[2].fX) - D; 234 SkScalar A = src[6] + 3*(src[2] - src[4]) - D;
283 SkScalar B = 3*(pts[2].fX - pts[1].fX - pts[1].fX + D); 235 SkScalar B = 3*(src[4] - src[2] - src[2] + D);
284 SkScalar C = 3*(pts[1].fX - D); 236 SkScalar C = 3*(src[2] - D);
285 x -= D; 237 x -= D;
286 SkScalar closest = SK_ScalarMax; 238 SkScalar closest = SK_ScalarMax;
287 do { 239 do {
288 SkScalar loc = ((A * t + B) * t + C) * t; 240 SkScalar loc = ((A * t + B) * t + C) * t;
289 SkScalar dist = SkScalarAbs(loc - x); 241 SkScalar dist = SkScalarAbs(loc - x);
290 if (closest > dist) { 242 if (closest > dist) {
291 closest = dist; 243 closest = dist;
292 bestT = t; 244 bestT = t;
293 } 245 }
294 lastT = t; 246 lastT = t;
295 t += loc < x ? step : -step; 247 t += loc < x ? step : -step;
296 step *= 0.5f; 248 step *= 0.5f;
297 } while (closest > 0.25f && lastT != t); 249 } while (closest > 0.25f && lastT != t);
298 SkChopCubicAt(pts, tmp, bestT); 250 return bestT;
251 }
252
253 static void chop_mono_cubic_at_y(SkPoint src[4], SkScalar y, SkPoint dst[7]) {
254 if (SkChopMonoCubicAtY(src, y, dst)) {
255 return;
256 }
257 SkChopCubicAt(src, dst, mono_cubic_closestT(&src->fY, y));
258 }
259
260 // Modify pts[] in place so that it is clipped in Y to the clip rect
261 static void chop_cubic_in_Y(SkPoint pts[4], const SkRect& clip) {
262
263 // are we partially above
264 if (pts[0].fY < clip.fTop) {
265 SkPoint tmp[7];
266 chop_mono_cubic_at_y(pts, clip.fTop, tmp);
267 // tmp[3, 4].fY should all be to the below clip.fTop.
268 // Since we can't trust the numerics of
269 // the chopper, we force those conditions now
270 tmp[3].fY = clip.fTop;
271 clamp_ge(tmp[4].fY, clip.fTop);
272
273 pts[0] = tmp[3];
274 pts[1] = tmp[4];
275 pts[2] = tmp[5];
276 }
277
278 // are we partially below
279 if (pts[3].fY > clip.fBottom) {
280 SkPoint tmp[7];
281 chop_mono_cubic_at_y(pts, clip.fBottom, tmp);
282 tmp[3].fY = clip.fBottom;
283 clamp_le(tmp[2].fY, clip.fBottom);
284
285 pts[1] = tmp[1];
286 pts[2] = tmp[2];
287 pts[3] = tmp[3];
288 }
289 }
290
291 static void chop_mono_cubic_at_x(SkPoint src[4], SkScalar x, SkPoint dst[7]) {
292 if (SkChopMonoCubicAtX(src, x, dst)) {
293 return;
294 }
295 SkChopCubicAt(src, dst, mono_cubic_closestT(&src->fX, x));
299 } 296 }
300 297
301 // srcPts[] must be monotonic in X and Y 298 // srcPts[] must be monotonic in X and Y
302 void SkEdgeClipper::clipMonoCubic(const SkPoint src[4], const SkRect& clip) { 299 void SkEdgeClipper::clipMonoCubic(const SkPoint src[4], const SkRect& clip) {
303 SkPoint pts[4]; 300 SkPoint pts[4];
304 bool reverse = sort_increasing_Y(pts, src, 4); 301 bool reverse = sort_increasing_Y(pts, src, 4);
305 302
306 // are we completely above or below 303 // are we completely above or below
307 if (pts[3].fY <= clip.fTop || pts[0].fY >= clip.fBottom) { 304 if (pts[3].fY <= clip.fTop || pts[0].fY >= clip.fBottom) {
308 return; 305 return;
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
481 assert_monotonic(&pts[0].fY, count); 478 assert_monotonic(&pts[0].fY, count);
482 } 479 }
483 } 480 }
484 481
485 void sk_assert_monotonic_x(const SkPoint pts[], int count) { 482 void sk_assert_monotonic_x(const SkPoint pts[], int count) {
486 if (count > 1) { 483 if (count > 1) {
487 assert_monotonic(&pts[0].fX, count); 484 assert_monotonic(&pts[0].fX, count);
488 } 485 }
489 } 486 }
490 #endif 487 #endif
OLDNEW
« no previous file with comments | « gm/cubicpaths.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698