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

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

Issue 139483002: change isRect to return true for 3-sided rectangular paths (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: handle overshoot on a incomplete/overcomplete rect Created 6 years, 11 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | tests/PathTest.cpp » ('j') | 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 2006 The Android Open Source Project 3 * Copyright 2006 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 "SkBuffer.h" 10 #include "SkBuffer.h"
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 352
353 A rectangle cycles up/right/down/left or up/left/down/right. 353 A rectangle cycles up/right/down/left or up/left/down/right.
354 354
355 The test fails if: 355 The test fails if:
356 The path is closed, and followed by a line. 356 The path is closed, and followed by a line.
357 A second move creates a new endpoint. 357 A second move creates a new endpoint.
358 A diagonal line is parsed. 358 A diagonal line is parsed.
359 There's more than four changes of direction. 359 There's more than four changes of direction.
360 There's a discontinuity on the line (e.g., a move in the middle) 360 There's a discontinuity on the line (e.g., a move in the middle)
361 The line reverses direction. 361 The line reverses direction.
362 The rectangle doesn't complete a cycle.
363 The path contains a quadratic or cubic. 362 The path contains a quadratic or cubic.
364 The path contains fewer than four points. 363 The path contains fewer than four points.
365 The final point isn't equal to the first point. 364 *The rectangle doesn't complete a cycle.
365 *The final point isn't equal to the first point.
366
367 *These last two conditions we relax if we have a 3-edge path that would
368 form a rectangle if it were closed (as we do when we fill a path)
366 369
367 It's OK if the path has: 370 It's OK if the path has:
368 Several colinear line segments composing a rectangle side. 371 Several colinear line segments composing a rectangle side.
369 Single points on the rectangle side. 372 Single points on the rectangle side.
370 373
371 The direction takes advantage of the corners found since opposite sides 374 The direction takes advantage of the corners found since opposite sides
372 must travel in opposite directions. 375 must travel in opposite directions.
373 376
374 FIXME: Allow colinear quads and cubics to be treated like lines. 377 FIXME: Allow colinear quads and cubics to be treated like lines.
375 FIXME: If the API passes fill-only, return true if the filled stroke 378 FIXME: If the API passes fill-only, return true if the filled stroke
376 is a rectangle, though the caller failed to close the path. 379 is a rectangle, though the caller failed to close the path.
380
381 first,last,next direction state-machine:
382 0x1 is set if the segment is horizontal
383 0x2 is set if the segment is moving to the right or down
384 thus:
385 two directions are opposites iff (dirA ^ dirB) == 0x2
386 two directions are perpendicular iff (dirA ^ dirB) == 0x1
387
377 */ 388 */
389 static int rect_make_dir(SkScalar dx, SkScalar dy) {
390 return ((0 != dx) << 0) | ((dx > 0 || dy > 0) << 1);
391 }
378 bool SkPath::isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts Ptr, 392 bool SkPath::isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts Ptr,
379 bool* isClosed, Direction* direction) const { 393 bool* isClosed, Direction* direction) const {
380 int corners = 0; 394 int corners = 0;
381 SkPoint first, last; 395 SkPoint first, last;
382 const SkPoint* pts = *ptsPtr; 396 const SkPoint* pts = *ptsPtr;
383 const SkPoint* savePts = NULL; 397 const SkPoint* savePts = NULL;
384 first.set(0, 0); 398 first.set(0, 0);
385 last.set(0, 0); 399 last.set(0, 0);
386 int firstDirection = 0; 400 int firstDirection = 0;
387 int lastDirection = 0; 401 int lastDirection = 0;
(...skipping 12 matching lines...) Expand all
400 SkScalar top = last.fY; 414 SkScalar top = last.fY;
401 SkScalar right = pts->fX; 415 SkScalar right = pts->fX;
402 SkScalar bottom = pts->fY; 416 SkScalar bottom = pts->fY;
403 ++pts; 417 ++pts;
404 if (left != right && top != bottom) { 418 if (left != right && top != bottom) {
405 return false; // diagonal 419 return false; // diagonal
406 } 420 }
407 if (left == right && top == bottom) { 421 if (left == right && top == bottom) {
408 break; // single point on side OK 422 break; // single point on side OK
409 } 423 }
410 nextDirection = (left != right) << 0 | 424 nextDirection = rect_make_dir(right - left, bottom - top);
411 (left < right || top < bottom) << 1;
412 if (0 == corners) { 425 if (0 == corners) {
413 firstDirection = nextDirection; 426 firstDirection = nextDirection;
414 first = last; 427 first = last;
415 last = pts[-1]; 428 last = pts[-1];
416 corners = 1; 429 corners = 1;
417 closedOrMoved = false; 430 closedOrMoved = false;
418 break; 431 break;
419 } 432 }
420 if (closedOrMoved) { 433 if (closedOrMoved) {
421 return false; // closed followed by a line 434 return false; // closed followed by a line
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 break; 466 break;
454 default: 467 default:
455 SkDEBUGFAIL("unexpected verb"); 468 SkDEBUGFAIL("unexpected verb");
456 break; 469 break;
457 } 470 }
458 *currVerb += 1; 471 *currVerb += 1;
459 lastDirection = nextDirection; 472 lastDirection = nextDirection;
460 } 473 }
461 // Success if 4 corners and first point equals last 474 // Success if 4 corners and first point equals last
462 bool result = 4 == corners && (first == last || autoClose); 475 bool result = 4 == corners && (first == last || autoClose);
476 if (!result) {
477 // check if we are just an incomplete rectangle, in which case we can
478 // return true, but not claim to be closed.
479 // e.g.
480 // 3 sided rectangle
481 // 4 sided but the last edge is not long enough to reach the start
482 //
483 SkScalar closeX = first.x() - last.x();
484 SkScalar closeY = first.y() - last.y();
485 if (closeX && closeY) {
486 return false; // we're diagonal, abort (can we ever reach this?)
487 }
488 int closeDirection = rect_make_dir(closeX, closeY);
489 // make sure the close-segment doesn't double-back on itself
490 if (3 == corners || (4 == corners && closeDirection == lastDirection)) {
491 result = true;
492 autoClose = false; // we are not closed
493 }
494 }
463 if (savePts) { 495 if (savePts) {
464 *ptsPtr = savePts; 496 *ptsPtr = savePts;
465 } 497 }
466 if (result && isClosed) { 498 if (result && isClosed) {
467 *isClosed = autoClose; 499 *isClosed = autoClose;
468 } 500 }
469 if (result && direction) { 501 if (result && direction) {
470 *direction = firstDirection == ((lastDirection + 1) & 3) ? kCCW_Directio n : kCW_Direction; 502 *direction = firstDirection == ((lastDirection + 1) & 3) ? kCCW_Directio n : kCW_Direction;
471 } 503 }
472 return result; 504 return result;
(...skipping 2380 matching lines...) Expand 10 before | Expand all | Expand 10 after
2853 switch (this->getFillType()) { 2885 switch (this->getFillType()) {
2854 case SkPath::kEvenOdd_FillType: 2886 case SkPath::kEvenOdd_FillType:
2855 case SkPath::kInverseEvenOdd_FillType: 2887 case SkPath::kInverseEvenOdd_FillType:
2856 w &= 1; 2888 w &= 1;
2857 break; 2889 break;
2858 default: 2890 default:
2859 break; 2891 break;
2860 } 2892 }
2861 return SkToBool(w); 2893 return SkToBool(w);
2862 } 2894 }
OLDNEW
« no previous file with comments | « no previous file | tests/PathTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698