SkPath.h revision 7e6c4d16010550ee148f1c79cf088c0320fed5c1
1 2/* 3 * Copyright 2006 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10#ifndef SkPath_DEFINED 11#define SkPath_DEFINED 12 13#include "SkMatrix.h" 14#include "SkTDArray.h" 15 16#ifdef SK_BUILD_FOR_ANDROID 17#define GEN_ID_INC fGenerationID++ 18#define GEN_ID_PTR_INC(ptr) ptr->fGenerationID++ 19#else 20#define GEN_ID_INC 21#define GEN_ID_PTR_INC(ptr) 22#endif 23 24class SkReader32; 25class SkWriter32; 26class SkAutoPathBoundsUpdate; 27class SkString; 28 29/** \class SkPath 30 31 The SkPath class encapsulates compound (multiple contour) geometric paths 32 consisting of straight line segments, quadratic curves, and cubic curves. 33*/ 34class SK_API SkPath { 35public: 36 SkPath(); 37 SkPath(const SkPath&); 38 ~SkPath(); 39 40 SkPath& operator=(const SkPath&); 41 42 friend bool operator==(const SkPath&, const SkPath&); 43 friend bool operator!=(const SkPath& a, const SkPath& b) { 44 return !(a == b); 45 } 46 47 enum FillType { 48 /** Specifies that "inside" is computed by a non-zero sum of signed 49 edge crossings 50 */ 51 kWinding_FillType, 52 /** Specifies that "inside" is computed by an odd number of edge 53 crossings 54 */ 55 kEvenOdd_FillType, 56 /** Same as Winding, but draws outside of the path, rather than inside 57 */ 58 kInverseWinding_FillType, 59 /** Same as EvenOdd, but draws outside of the path, rather than inside 60 */ 61 kInverseEvenOdd_FillType 62 }; 63 64 /** Return the path's fill type. This is used to define how "inside" is 65 computed. The default value is kWinding_FillType. 66 67 @return the path's fill type 68 */ 69 FillType getFillType() const { return (FillType)fFillType; } 70 71 /** Set the path's fill type. This is used to define how "inside" is 72 computed. The default value is kWinding_FillType. 73 74 @param ft The new fill type for this path 75 */ 76 void setFillType(FillType ft) { 77 fFillType = SkToU8(ft); 78 GEN_ID_INC; 79 } 80 81 /** Returns true if the filltype is one of the Inverse variants */ 82 bool isInverseFillType() const { return (fFillType & 2) != 0; } 83 84 /** 85 * Toggle between inverse and normal filltypes. This reverse the return 86 * value of isInverseFillType() 87 */ 88 void toggleInverseFillType() { 89 fFillType ^= 2; 90 GEN_ID_INC; 91 } 92 93 enum Convexity { 94 kUnknown_Convexity, 95 kConvex_Convexity, 96 kConcave_Convexity 97 }; 98 99 /** 100 * Return the path's convexity, as stored in the path. If it is currently 101 * unknown, and the computeIfUnknown bool is true, then this will first 102 * call ComputeConvexity() and then return that (cached) value. 103 */ 104 Convexity getConvexity() const { 105 if (kUnknown_Convexity == fConvexity) { 106 fConvexity = (uint8_t)ComputeConvexity(*this); 107 } 108 return (Convexity)fConvexity; 109 } 110 111 /** 112 * Return the currently cached value for convexity, even if that is set to 113 * kUnknown_Convexity. Note: getConvexity() will automatically call 114 * ComputeConvexity and cache its return value if the current setting is 115 * kUnknown. 116 */ 117 Convexity getConvexityOrUnknown() const { return (Convexity)fConvexity; } 118 119 /** 120 * Store a convexity setting in the path. There is no automatic check to 121 * see if this value actually agress with the return value from 122 * ComputeConvexity(). 123 * 124 * Note: even if this is set to a "known" value, if the path is later 125 * changed (e.g. lineTo(), addRect(), etc.) then the cached value will be 126 * reset to kUnknown_Convexity. 127 */ 128 void setConvexity(Convexity); 129 130 /** 131 * Compute the convexity of the specified path. This does not look at the 132 * value stored in the path, but computes it directly from the path's data. 133 * 134 * This never returns kUnknown_Convexity. 135 * 136 * If there is more than one contour, this returns kConcave_Convexity. 137 * If the contour is degenerate (e.g. there are fewer than 3 non-degenerate 138 * segments), then this returns kConvex_Convexity. 139 * The contour is treated as if it were closed, even if there is no kClose 140 * verb. 141 */ 142 static Convexity ComputeConvexity(const SkPath&); 143 144 /** 145 * DEPRECATED: use getConvexity() 146 * Returns true if the path is flagged as being convex. This is not a 147 * confirmed by any analysis, it is just the value set earlier. 148 */ 149 bool isConvex() const { 150 return kConvex_Convexity == this->getConvexity(); 151 } 152 153 /** 154 * DEPRECATED: use setConvexity() 155 * Set the isConvex flag to true or false. Convex paths may draw faster if 156 * this flag is set, though setting this to true on a path that is in fact 157 * not convex can give undefined results when drawn. Paths default to 158 * isConvex == false 159 */ 160 void setIsConvex(bool isConvex) { 161 this->setConvexity(isConvex ? kConvex_Convexity : kConcave_Convexity); 162 } 163 164 /** Returns true if the path is an oval. 165 * 166 * @param rect returns the bounding rect of this oval. It's a circle 167 * if the height and width are the same. 168 * 169 * @return true if this path is an oval. 170 * Tracking whether a path is an oval is considered an 171 * optimization for performance and so some paths that are in 172 * fact ovals can report false. 173 */ 174 bool isOval(SkRect* rect) const; 175 176 /** Clear any lines and curves from the path, making it empty. This frees up 177 internal storage associated with those segments. 178 This does NOT change the fill-type setting nor isConvex 179 */ 180 void reset(); 181 182 /** Similar to reset(), in that all lines and curves are removed from the 183 path. However, any internal storage for those lines/curves is retained, 184 making reuse of the path potentially faster. 185 This does NOT change the fill-type setting nor isConvex 186 */ 187 void rewind(); 188 189 /** Returns true if the path is empty (contains no lines or curves) 190 191 @return true if the path is empty (contains no lines or curves) 192 */ 193 bool isEmpty() const; 194 195 /** Test a line for zero length 196 197 @return true if the line is of zero length; otherwise false. 198 */ 199 static bool IsLineDegenerate(const SkPoint& p1, const SkPoint& p2) { 200 return p1.equalsWithinTolerance(p2); 201 } 202 203 /** Test a quad for zero length 204 205 @return true if the quad is of zero length; otherwise false. 206 */ 207 static bool IsQuadDegenerate(const SkPoint& p1, const SkPoint& p2, 208 const SkPoint& p3) { 209 return p1.equalsWithinTolerance(p2) && 210 p2.equalsWithinTolerance(p3); 211 } 212 213 /** Test a cubic curve for zero length 214 215 @return true if the cubic is of zero length; otherwise false. 216 */ 217 static bool IsCubicDegenerate(const SkPoint& p1, const SkPoint& p2, 218 const SkPoint& p3, const SkPoint& p4) { 219 return p1.equalsWithinTolerance(p2) && 220 p2.equalsWithinTolerance(p3) && 221 p3.equalsWithinTolerance(p4); 222 } 223 224 /** 225 * Returns true if the path specifies a single line (i.e. it contains just 226 * a moveTo and a lineTo). If so, and line[] is not null, it sets the 2 227 * points in line[] to the end-points of the line. If the path is not a 228 * line, returns false and ignores line[]. 229 */ 230 bool isLine(SkPoint line[2]) const; 231 232 /** Returns true if the path specifies a rectangle. If so, and if rect is 233 not null, set rect to the bounds of the path. If the path does not 234 specify a rectangle, return false and ignore rect. 235 236 @param rect If not null, returns the bounds of the path if it specifies 237 a rectangle 238 @return true if the path specifies a rectangle 239 */ 240 bool isRect(SkRect* rect) const; 241 242 /** Return the number of points in the path 243 */ 244 int countPoints() const { 245 return this->getPoints(NULL, 0); 246 } 247 248 /** Return the point at the specified index. If the index is out of range 249 (i.e. is not 0 <= index < countPoints()) then the returned coordinates 250 will be (0,0) 251 */ 252 SkPoint getPoint(int index) const; 253 254 /** Returns the number of points in the path. Up to max points are copied. 255 256 @param points If not null, receives up to max points 257 @param max The maximum number of points to copy into points 258 @return the actual number of points in the path 259 */ 260 int getPoints(SkPoint points[], int max) const; 261 262 //! Swap contents of this and other. Guaranteed not to throw 263 void swap(SkPath& other); 264 265 /** Returns the bounds of the path's points. If the path contains 0 or 1 266 points, the bounds is set to (0,0,0,0), and isEmpty() will return true. 267 Note: this bounds may be larger than the actual shape, since curves 268 do not extend as far as their control points. 269 */ 270 const SkRect& getBounds() const { 271 if (fBoundsIsDirty) { 272 this->computeBounds(); 273 } 274 return fBounds; 275 } 276 277 /** Calling this will, if the internal cache of the bounds is out of date, 278 update it so that subsequent calls to getBounds will be instanteous. 279 This also means that any copies or simple transformations of the path 280 will inherit the cached bounds. 281 */ 282 void updateBoundsCache() const { 283 // for now, just calling getBounds() is sufficient 284 this->getBounds(); 285 } 286 287 // Construction methods 288 289 /** Hint to the path to prepare for adding more points. This can allow the 290 path to more efficiently grow its storage. 291 292 @param extraPtCount The number of extra points the path should 293 preallocate for. 294 */ 295 void incReserve(unsigned extraPtCount); 296 297 /** Set the beginning of the next contour to the point (x,y). 298 299 @param x The x-coordinate of the start of a new contour 300 @param y The y-coordinate of the start of a new contour 301 */ 302 void moveTo(SkScalar x, SkScalar y); 303 304 /** Set the beginning of the next contour to the point 305 306 @param p The start of a new contour 307 */ 308 void moveTo(const SkPoint& p) { 309 this->moveTo(p.fX, p.fY); 310 } 311 312 /** Set the beginning of the next contour relative to the last point on the 313 previous contour. If there is no previous contour, this is treated the 314 same as moveTo(). 315 316 @param dx The amount to add to the x-coordinate of the end of the 317 previous contour, to specify the start of a new contour 318 @param dy The amount to add to the y-coordinate of the end of the 319 previous contour, to specify the start of a new contour 320 */ 321 void rMoveTo(SkScalar dx, SkScalar dy); 322 323 /** Add a line from the last point to the specified point (x,y). If no 324 moveTo() call has been made for this contour, the first point is 325 automatically set to (0,0). 326 327 @param x The x-coordinate of the end of a line 328 @param y The y-coordinate of the end of a line 329 */ 330 void lineTo(SkScalar x, SkScalar y); 331 332 /** Add a line from the last point to the specified point. If no moveTo() 333 call has been made for this contour, the first point is automatically 334 set to (0,0). 335 336 @param p The end of a line 337 */ 338 void lineTo(const SkPoint& p) { 339 this->lineTo(p.fX, p.fY); 340 } 341 342 /** Same as lineTo, but the coordinates are considered relative to the last 343 point on this contour. If there is no previous point, then a moveTo(0,0) 344 is inserted automatically. 345 346 @param dx The amount to add to the x-coordinate of the previous point 347 on this contour, to specify a line 348 @param dy The amount to add to the y-coordinate of the previous point 349 on this contour, to specify a line 350 */ 351 void rLineTo(SkScalar dx, SkScalar dy); 352 353 /** Add a quadratic bezier from the last point, approaching control point 354 (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for 355 this contour, the first point is automatically set to (0,0). 356 357 @param x1 The x-coordinate of the control point on a quadratic curve 358 @param y1 The y-coordinate of the control point on a quadratic curve 359 @param x2 The x-coordinate of the end point on a quadratic curve 360 @param y2 The y-coordinate of the end point on a quadratic curve 361 */ 362 void quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2); 363 364 /** Add a quadratic bezier from the last point, approaching control point 365 p1, and ending at p2. If no moveTo() call has been made for this 366 contour, the first point is automatically set to (0,0). 367 368 @param p1 The control point on a quadratic curve 369 @param p2 The end point on a quadratic curve 370 */ 371 void quadTo(const SkPoint& p1, const SkPoint& p2) { 372 this->quadTo(p1.fX, p1.fY, p2.fX, p2.fY); 373 } 374 375 /** Same as quadTo, but the coordinates are considered relative to the last 376 point on this contour. If there is no previous point, then a moveTo(0,0) 377 is inserted automatically. 378 379 @param dx1 The amount to add to the x-coordinate of the last point on 380 this contour, to specify the control point of a quadratic curve 381 @param dy1 The amount to add to the y-coordinate of the last point on 382 this contour, to specify the control point of a quadratic curve 383 @param dx2 The amount to add to the x-coordinate of the last point on 384 this contour, to specify the end point of a quadratic curve 385 @param dy2 The amount to add to the y-coordinate of the last point on 386 this contour, to specify the end point of a quadratic curve 387 */ 388 void rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2); 389 390 /** Add a cubic bezier from the last point, approaching control points 391 (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been 392 made for this contour, the first point is automatically set to (0,0). 393 394 @param x1 The x-coordinate of the 1st control point on a cubic curve 395 @param y1 The y-coordinate of the 1st control point on a cubic curve 396 @param x2 The x-coordinate of the 2nd control point on a cubic curve 397 @param y2 The y-coordinate of the 2nd control point on a cubic curve 398 @param x3 The x-coordinate of the end point on a cubic curve 399 @param y3 The y-coordinate of the end point on a cubic curve 400 */ 401 void cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, 402 SkScalar x3, SkScalar y3); 403 404 /** Add a cubic bezier from the last point, approaching control points p1 405 and p2, and ending at p3. If no moveTo() call has been made for this 406 contour, the first point is automatically set to (0,0). 407 408 @param p1 The 1st control point on a cubic curve 409 @param p2 The 2nd control point on a cubic curve 410 @param p3 The end point on a cubic curve 411 */ 412 void cubicTo(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3) { 413 this->cubicTo(p1.fX, p1.fY, p2.fX, p2.fY, p3.fX, p3.fY); 414 } 415 416 /** Same as cubicTo, but the coordinates are considered relative to the 417 current point on this contour. If there is no previous point, then a 418 moveTo(0,0) is inserted automatically. 419 420 @param dx1 The amount to add to the x-coordinate of the last point on 421 this contour, to specify the 1st control point of a cubic curve 422 @param dy1 The amount to add to the y-coordinate of the last point on 423 this contour, to specify the 1st control point of a cubic curve 424 @param dx2 The amount to add to the x-coordinate of the last point on 425 this contour, to specify the 2nd control point of a cubic curve 426 @param dy2 The amount to add to the y-coordinate of the last point on 427 this contour, to specify the 2nd control point of a cubic curve 428 @param dx3 The amount to add to the x-coordinate of the last point on 429 this contour, to specify the end point of a cubic curve 430 @param dy3 The amount to add to the y-coordinate of the last point on 431 this contour, to specify the end point of a cubic curve 432 */ 433 void rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, 434 SkScalar x3, SkScalar y3); 435 436 /** Append the specified arc to the path as a new contour. If the start of 437 the path is different from the path's current last point, then an 438 automatic lineTo() is added to connect the current contour to the start 439 of the arc. However, if the path is empty, then we call moveTo() with 440 the first point of the arc. The sweep angle is treated mod 360. 441 442 @param oval The bounding oval defining the shape and size of the arc 443 @param startAngle Starting angle (in degrees) where the arc begins 444 @param sweepAngle Sweep angle (in degrees) measured clockwise. This is 445 treated mod 360. 446 @param forceMoveTo If true, always begin a new contour with the arc 447 */ 448 void arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, 449 bool forceMoveTo); 450 451 /** Append a line and arc to the current path. This is the same as the 452 PostScript call "arct". 453 */ 454 void arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, 455 SkScalar radius); 456 457 /** Append a line and arc to the current path. This is the same as the 458 PostScript call "arct". 459 */ 460 void arcTo(const SkPoint p1, const SkPoint p2, SkScalar radius) { 461 this->arcTo(p1.fX, p1.fY, p2.fX, p2.fY, radius); 462 } 463 464 /** Close the current contour. If the current point is not equal to the 465 first point of the contour, a line segment is automatically added. 466 */ 467 void close(); 468 469 enum Direction { 470 /** clockwise direction for adding closed contours */ 471 kCW_Direction, 472 /** counter-clockwise direction for adding closed contours */ 473 kCCW_Direction 474 }; 475 476 /** 477 * Tries to quickly compute the direction of the first non-degenerate 478 * contour. If it can be computed, return true and set dir to that 479 * direction. If it cannot be (quickly) determined, return false and ignore 480 * the dir parameter. 481 */ 482 bool cheapComputeDirection(Direction* dir) const; 483 484 /** 485 * Returns true if the path's direction can be computed via 486 * cheapComputDirection() and if that computed direction matches the 487 * specified direction. 488 */ 489 bool cheapIsDirection(Direction dir) const { 490 Direction computedDir; 491 return this->cheapComputeDirection(&computedDir) && computedDir == dir; 492 } 493 494 /** Add a closed rectangle contour to the path 495 @param rect The rectangle to add as a closed contour to the path 496 @param dir The direction to wind the rectangle's contour 497 */ 498 void addRect(const SkRect& rect, Direction dir = kCW_Direction); 499 500 /** Add a closed rectangle contour to the path 501 502 @param left The left side of a rectangle to add as a closed contour 503 to the path 504 @param top The top of a rectangle to add as a closed contour to the 505 path 506 @param right The right side of a rectangle to add as a closed contour 507 to the path 508 @param bottom The bottom of a rectangle to add as a closed contour to 509 the path 510 @param dir The direction to wind the rectangle's contour 511 */ 512 void addRect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom, 513 Direction dir = kCW_Direction); 514 515 /** Add a closed oval contour to the path 516 517 @param oval The bounding oval to add as a closed contour to the path 518 @param dir The direction to wind the oval's contour 519 */ 520 void addOval(const SkRect& oval, Direction dir = kCW_Direction); 521 522 /** Add a closed circle contour to the path 523 524 @param x The x-coordinate of the center of a circle to add as a 525 closed contour to the path 526 @param y The y-coordinate of the center of a circle to add as a 527 closed contour to the path 528 @param radius The radius of a circle to add as a closed contour to the 529 path 530 @param dir The direction to wind the circle's contour 531 */ 532 void addCircle(SkScalar x, SkScalar y, SkScalar radius, 533 Direction dir = kCW_Direction); 534 535 /** Add the specified arc to the path as a new contour. 536 537 @param oval The bounds of oval used to define the size of the arc 538 @param startAngle Starting angle (in degrees) where the arc begins 539 @param sweepAngle Sweep angle (in degrees) measured clockwise 540 */ 541 void addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle); 542 543 /** Add a closed round-rectangle contour to the path 544 @param rect The bounds of a round-rectangle to add as a closed contour 545 @param rx The x-radius of the rounded corners on the round-rectangle 546 @param ry The y-radius of the rounded corners on the round-rectangle 547 @param dir The direction to wind the round-rectangle's contour 548 */ 549 void addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, 550 Direction dir = kCW_Direction); 551 552 /** Add a closed round-rectangle contour to the path. Each corner receives 553 two radius values [X, Y]. The corners are ordered top-left, top-right, 554 bottom-right, bottom-left. 555 @param rect The bounds of a round-rectangle to add as a closed contour 556 @param radii Array of 8 scalars, 4 [X,Y] pairs for each corner 557 @param dir The direction to wind the round-rectangle's contour 558 */ 559 void addRoundRect(const SkRect& rect, const SkScalar radii[], 560 Direction dir = kCW_Direction); 561 562 /** Add a copy of src to the path, offset by (dx,dy) 563 @param src The path to add as a new contour 564 @param dx The amount to translate the path in X as it is added 565 @param dx The amount to translate the path in Y as it is added 566 */ 567 void addPath(const SkPath& src, SkScalar dx, SkScalar dy); 568 569 /** Add a copy of src to the path 570 */ 571 void addPath(const SkPath& src) { 572 SkMatrix m; 573 m.reset(); 574 this->addPath(src, m); 575 } 576 577 /** Add a copy of src to the path, transformed by matrix 578 @param src The path to add as a new contour 579 */ 580 void addPath(const SkPath& src, const SkMatrix& matrix); 581 582 /** 583 * Same as addPath(), but reverses the src input 584 */ 585 void reverseAddPath(const SkPath& src); 586 587 /** Offset the path by (dx,dy), returning true on success 588 589 @param dx The amount in the X direction to offset the entire path 590 @param dy The amount in the Y direction to offset the entire path 591 @param dst The translated path is written here 592 */ 593 void offset(SkScalar dx, SkScalar dy, SkPath* dst) const; 594 595 /** Offset the path by (dx,dy), returning true on success 596 597 @param dx The amount in the X direction to offset the entire path 598 @param dy The amount in the Y direction to offset the entire path 599 */ 600 void offset(SkScalar dx, SkScalar dy) { 601 this->offset(dx, dy, this); 602 } 603 604 /** Transform the points in this path by matrix, and write the answer into 605 dst. 606 607 @param matrix The matrix to apply to the path 608 @param dst The transformed path is written here 609 */ 610 void transform(const SkMatrix& matrix, SkPath* dst) const; 611 612 /** Transform the points in this path by matrix 613 614 @param matrix The matrix to apply to the path 615 */ 616 void transform(const SkMatrix& matrix) { 617 this->transform(matrix, this); 618 } 619 620 /** Return the last point on the path. If no points have been added, (0,0) 621 is returned. If there are no points, this returns false, otherwise it 622 returns true. 623 624 @param lastPt The last point on the path is returned here 625 */ 626 bool getLastPt(SkPoint* lastPt) const; 627 628 /** Set the last point on the path. If no points have been added, 629 moveTo(x,y) is automatically called. 630 631 @param x The new x-coordinate for the last point 632 @param y The new y-coordinate for the last point 633 */ 634 void setLastPt(SkScalar x, SkScalar y); 635 636 /** Set the last point on the path. If no points have been added, moveTo(p) 637 is automatically called. 638 639 @param p The new location for the last point 640 */ 641 void setLastPt(const SkPoint& p) { 642 this->setLastPt(p.fX, p.fY); 643 } 644 645 enum SegmentMask { 646 kLine_SegmentMask = 1 << 0, 647 kQuad_SegmentMask = 1 << 1, 648 kCubic_SegmentMask = 1 << 2 649 }; 650 651 /** 652 * Returns a mask, where each bit corresponding to a SegmentMask is 653 * set if the path contains 1 or more segments of that type. 654 * Returns 0 for an empty path (no segments). 655 */ 656 uint32_t getSegmentMasks() const { return fSegmentMask; } 657 658 enum Verb { 659 kMove_Verb, //!< iter.next returns 1 point 660 kLine_Verb, //!< iter.next returns 2 points 661 kQuad_Verb, //!< iter.next returns 3 points 662 kCubic_Verb, //!< iter.next returns 4 points 663 kClose_Verb, //!< iter.next returns 1 point (contour's moveTo pt) 664 kDone_Verb //!< iter.next returns 0 points 665 }; 666 667 /** Iterate through all of the segments (lines, quadratics, cubics) of 668 each contours in a path. 669 670 The iterator cleans up the segments along the way, removing degenerate 671 segments and adding close verbs where necessary. When the forceClose 672 argument is provided, each contour (as defined by a new starting 673 move command) will be completed with a close verb regardless of the 674 contour's contents. 675 */ 676 class SK_API Iter { 677 public: 678 Iter(); 679 Iter(const SkPath&, bool forceClose); 680 681 void setPath(const SkPath&, bool forceClose); 682 683 /** Return the next verb in this iteration of the path. When all 684 segments have been visited, return kDone_Verb. 685 686 @param pts The points representing the current verb and/or segment 687 @return The verb for the current segment 688 */ 689 Verb next(SkPoint pts[4]); 690 691 /** If next() returns kLine_Verb, then this query returns true if the 692 line was the result of a close() command (i.e. the end point is the 693 initial moveto for this contour). If next() returned a different 694 verb, this returns an undefined value. 695 696 @return If the last call to next() returned kLine_Verb, return true 697 if it was the result of an explicit close command. 698 */ 699 bool isCloseLine() const { return SkToBool(fCloseLine); } 700 701 /** Returns true if the current contour is closed (has a kClose_Verb) 702 @return true if the current contour is closed (has a kClose_Verb) 703 */ 704 bool isClosedContour() const; 705 706 private: 707 const SkPoint* fPts; 708 const uint8_t* fVerbs; 709 const uint8_t* fVerbStop; 710 SkPoint fMoveTo; 711 SkPoint fLastPt; 712 SkBool8 fForceClose; 713 SkBool8 fNeedClose; 714 SkBool8 fCloseLine; 715 SkBool8 fSegmentState; 716 717 bool cons_moveTo(SkPoint pts[1]); 718 Verb autoClose(SkPoint pts[2]); 719 void consumeDegenerateSegments(); 720 }; 721 722 /** Iterate through the verbs in the path, providing the associated points. 723 */ 724 class SK_API RawIter { 725 public: 726 RawIter(); 727 RawIter(const SkPath&); 728 729 void setPath(const SkPath&); 730 731 /** Return the next verb in this iteration of the path. When all 732 segments have been visited, return kDone_Verb. 733 734 @param pts The points representing the current verb and/or segment 735 @return The verb for the current segment 736 */ 737 Verb next(SkPoint pts[4]); 738 739 private: 740 const SkPoint* fPts; 741 const uint8_t* fVerbs; 742 const uint8_t* fVerbStop; 743 SkPoint fMoveTo; 744 SkPoint fLastPt; 745 }; 746 747 void dump(bool forceClose, const char title[] = NULL) const; 748 void dump() const; 749 750 void flatten(SkWriter32&) const; 751 void unflatten(SkReader32&); 752 753#ifdef SK_BUILD_FOR_ANDROID 754 uint32_t getGenerationID() const; 755 const SkPath* getSourcePath() const; 756 void setSourcePath(const SkPath* path); 757#endif 758 759 SkDEBUGCODE(void validate() const;) 760 761private: 762 SkTDArray<SkPoint> fPts; 763 SkTDArray<uint8_t> fVerbs; 764 mutable SkRect fBounds; 765 int fLastMoveToIndex; 766 uint8_t fFillType; 767 uint8_t fSegmentMask; 768 mutable uint8_t fBoundsIsDirty; 769 mutable uint8_t fConvexity; 770 771 mutable SkBool8 fIsOval; 772#ifdef SK_BUILD_FOR_ANDROID 773 uint32_t fGenerationID; 774 const SkPath* fSourcePath; 775#endif 776 777 // called, if dirty, by getBounds() 778 void computeBounds() const; 779 780 friend class Iter; 781 782 friend class SkPathStroker; 783 /* Append the first contour of path, ignoring path's initial point. If no 784 moveTo() call has been made for this contour, the first point is 785 automatically set to (0,0). 786 */ 787 void pathTo(const SkPath& path); 788 789 /* Append, in reverse order, the first contour of path, ignoring path's 790 last point. If no moveTo() call has been made for this contour, the 791 first point is automatically set to (0,0). 792 */ 793 void reversePathTo(const SkPath&); 794 795 // called before we add points for lineTo, quadTo, cubicTo, checking to see 796 // if we need to inject a leading moveTo first 797 // 798 // SkPath path; path.lineTo(...); <--- need a leading moveTo(0, 0) 799 // SkPath path; ... path.close(); path.lineTo(...) <-- need a moveTo(previous moveTo) 800 // 801 inline void injectMoveToIfNeeded(); 802 803 inline bool hasOnlyMoveTos() const; 804 805 friend class SkAutoPathBoundsUpdate; 806 friend class SkAutoDisableOvalCheck; 807}; 808 809#endif 810