1 /* 2 * Copyright 2006 The Android Open Source Project 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SkPath_DEFINED 9 #define SkPath_DEFINED 10 11 #include "include/core/SkMatrix.h" 12 #include "include/core/SkPathTypes.h" 13 #include "include/private/SkPathRef.h" 14 #include "include/private/SkTo.h" 15 16 #include <initializer_list> 17 18 class SkAutoPathBoundsUpdate; 19 class SkData; 20 class SkRRect; 21 class SkWStream; 22 23 /** \class SkPath 24 SkPath contain geometry. SkPath may be empty, or contain one or more verbs that 25 outline a figure. SkPath always starts with a move verb to a Cartesian coordinate, 26 and may be followed by additional verbs that add lines or curves. 27 Adding a close verb makes the geometry into a continuous loop, a closed contour. 28 SkPath may contain any number of contours, each beginning with a move verb. 29 30 SkPath contours may contain only a move verb, or may also contain lines, 31 quadratic beziers, conics, and cubic beziers. SkPath contours may be open or 32 closed. 33 34 When used to draw a filled area, SkPath describes whether the fill is inside or 35 outside the geometry. SkPath also describes the winding rule used to fill 36 overlapping contours. 37 38 Internally, SkPath lazily computes metrics likes bounds and convexity. Call 39 SkPath::updateBoundsCache to make SkPath thread safe. 40 */ 41 class SK_API SkPath { 42 public: 43 44 /** Constructs an empty SkPath. By default, SkPath has no verbs, no SkPoint, and no weights. 45 FillType is set to kWinding. 46 47 @return empty SkPath 48 49 example: https://fiddle.skia.org/c/@Path_empty_constructor 50 */ 51 SkPath(); 52 53 /** Constructs a copy of an existing path. 54 Copy constructor makes two paths identical by value. Internally, path and 55 the returned result share pointer values. The underlying verb array, SkPoint array 56 and weights are copied when modified. 57 58 Creating a SkPath copy is very efficient and never allocates memory. 59 SkPath are always copied by value from the interface; the underlying shared 60 pointers are not exposed. 61 62 @param path SkPath to copy by value 63 @return copy of SkPath 64 65 example: https://fiddle.skia.org/c/@Path_copy_const_SkPath 66 */ 67 SkPath(const SkPath& path); 68 69 /** Releases ownership of any shared data and deletes data if SkPath is sole owner. 70 71 example: https://fiddle.skia.org/c/@Path_destructor 72 */ 73 ~SkPath(); 74 75 /** Constructs a copy of an existing path. 76 SkPath assignment makes two paths identical by value. Internally, assignment 77 shares pointer values. The underlying verb array, SkPoint array and weights 78 are copied when modified. 79 80 Copying SkPath by assignment is very efficient and never allocates memory. 81 SkPath are always copied by value from the interface; the underlying shared 82 pointers are not exposed. 83 84 @param path verb array, SkPoint array, weights, and SkPath::FillType to copy 85 @return SkPath copied by value 86 87 example: https://fiddle.skia.org/c/@Path_copy_operator 88 */ 89 SkPath& operator=(const SkPath& path); 90 91 /** Compares a and b; returns true if SkPath::FillType, verb array, SkPoint array, and weights 92 are equivalent. 93 94 @param a SkPath to compare 95 @param b SkPath to compare 96 @return true if SkPath pair are equivalent 97 */ 98 friend SK_API bool operator==(const SkPath& a, const SkPath& b); 99 100 /** Compares a and b; returns true if SkPath::FillType, verb array, SkPoint array, and weights 101 are not equivalent. 102 103 @param a SkPath to compare 104 @param b SkPath to compare 105 @return true if SkPath pair are not equivalent 106 */ 107 friend bool operator!=(const SkPath& a, const SkPath& b) { 108 return !(a == b); 109 } 110 111 /** Returns true if SkPath contain equal verbs and equal weights. 112 If SkPath contain one or more conics, the weights must match. 113 114 conicTo() may add different verbs depending on conic weight, so it is not 115 trivial to interpolate a pair of SkPath containing conics with different 116 conic weight values. 117 118 @param compare SkPath to compare 119 @return true if SkPath verb array and weights are equivalent 120 121 example: https://fiddle.skia.org/c/@Path_isInterpolatable 122 */ 123 bool isInterpolatable(const SkPath& compare) const; 124 125 /** Interpolates between SkPath with SkPoint array of equal size. 126 Copy verb array and weights to out, and set out SkPoint array to a weighted 127 average of this SkPoint array and ending SkPoint array, using the formula: 128 (Path Point * weight) + ending Point * (1 - weight). 129 130 weight is most useful when between zero (ending SkPoint array) and 131 one (this Point_Array); will work with values outside of this 132 range. 133 134 interpolate() returns false and leaves out unchanged if SkPoint array is not 135 the same size as ending SkPoint array. Call isInterpolatable() to check SkPath 136 compatibility prior to calling interpolate(). 137 138 @param ending SkPoint array averaged with this SkPoint array 139 @param weight contribution of this SkPoint array, and 140 one minus contribution of ending SkPoint array 141 @param out SkPath replaced by interpolated averages 142 @return true if SkPath contain same number of SkPoint 143 144 example: https://fiddle.skia.org/c/@Path_interpolate 145 */ 146 bool interpolate(const SkPath& ending, SkScalar weight, SkPath* out) const; 147 148 /** Returns SkPathFillType, the rule used to fill SkPath. 149 150 @return current SkPathFillType setting 151 */ getFillType()152 SkPathFillType getFillType() const { return (SkPathFillType)fFillType; } 153 154 /** Sets FillType, the rule used to fill SkPath. While there is no check 155 that ft is legal, values outside of FillType are not supported. 156 */ setFillType(SkPathFillType ft)157 void setFillType(SkPathFillType ft) { 158 fFillType = SkToU8(ft); 159 } 160 161 /** Returns if FillType describes area outside SkPath geometry. The inverse fill area 162 extends indefinitely. 163 164 @return true if FillType is kInverseWinding or kInverseEvenOdd 165 */ isInverseFillType()166 bool isInverseFillType() const { return SkPathFillType_IsInverse(this->getFillType()); } 167 168 /** Replaces FillType with its inverse. The inverse of FillType describes the area 169 unmodified by the original FillType. 170 */ toggleInverseFillType()171 void toggleInverseFillType() { 172 fFillType ^= 2; 173 } 174 175 /** Returns the comvexity type, computing if needed. Never returns kUnknown. 176 @return path's convexity type (convex or concave) 177 */ getConvexityType()178 SkPathConvexityType getConvexityType() const { 179 SkPathConvexityType convexity = this->getConvexityTypeOrUnknown(); 180 if (convexity != SkPathConvexityType::kUnknown) { 181 return convexity; 182 } 183 return this->internalGetConvexity(); 184 } 185 186 /** If the path's convexity is already known, return it, else return kUnknown. 187 * If you always want to know the convexity, even if that means having to compute it, 188 * call getConvexitytype(). 189 * 190 * @return known convexity, or kUnknown 191 */ getConvexityTypeOrUnknown()192 SkPathConvexityType getConvexityTypeOrUnknown() const { 193 return (SkPathConvexityType)fConvexity.load(std::memory_order_relaxed); 194 } 195 196 /** Stores a convexity type for this path. This is what will be returned if 197 * getConvexityTypeOrUnknown() is called. If you pass kUnknown, then if getContexityType() 198 * is called, the real convexity will be computed. 199 * 200 * example: https://fiddle.skia.org/c/@Path_setConvexity 201 */ 202 void setConvexityType(SkPathConvexityType convexity); 203 204 /** Returns true if the path is convex. If necessary, it will first compute the convexity. 205 */ isConvex()206 bool isConvex() const { 207 return SkPathConvexityType::kConvex == this->getConvexityType(); 208 } 209 210 /** Returns true if this path is recognized as an oval or circle. 211 212 bounds receives bounds of oval. 213 214 bounds is unmodified if oval is not found. 215 216 @param bounds storage for bounding SkRect of oval; may be nullptr 217 @return true if SkPath is recognized as an oval or circle 218 219 example: https://fiddle.skia.org/c/@Path_isOval 220 */ 221 bool isOval(SkRect* bounds) const; 222 223 /** Returns true if path is representable as SkRRect. 224 Returns false if path is representable as oval, circle, or SkRect. 225 226 rrect receives bounds of SkRRect. 227 228 rrect is unmodified if SkRRect is not found. 229 230 @param rrect storage for bounding SkRect of SkRRect; may be nullptr 231 @return true if SkPath contains only SkRRect 232 233 example: https://fiddle.skia.org/c/@Path_isRRect 234 */ 235 bool isRRect(SkRRect* rrect) const; 236 237 /** Sets SkPath to its initial state. 238 Removes verb array, SkPoint array, and weights, and sets FillType to kWinding. 239 Internal storage associated with SkPath is released. 240 241 @return reference to SkPath 242 243 example: https://fiddle.skia.org/c/@Path_reset 244 */ 245 SkPath& reset(); 246 247 /** Sets SkPath to its initial state, preserving internal storage. 248 Removes verb array, SkPoint array, and weights, and sets FillType to kWinding. 249 Internal storage associated with SkPath is retained. 250 251 Use rewind() instead of reset() if SkPath storage will be reused and performance 252 is critical. 253 254 @return reference to SkPath 255 256 example: https://fiddle.skia.org/c/@Path_rewind 257 */ 258 SkPath& rewind(); 259 260 /** Returns if SkPath is empty. 261 Empty SkPath may have FillType but has no SkPoint, SkPath::Verb, or conic weight. 262 SkPath() constructs empty SkPath; reset() and rewind() make SkPath empty. 263 264 @return true if the path contains no SkPath::Verb array 265 */ isEmpty()266 bool isEmpty() const { 267 SkDEBUGCODE(this->validate();) 268 return 0 == fPathRef->countVerbs(); 269 } 270 271 /** Returns if contour is closed. 272 Contour is closed if SkPath SkPath::Verb array was last modified by close(). When stroked, 273 closed contour draws SkPaint::Join instead of SkPaint::Cap at first and last SkPoint. 274 275 @return true if the last contour ends with a kClose_Verb 276 277 example: https://fiddle.skia.org/c/@Path_isLastContourClosed 278 */ 279 bool isLastContourClosed() const; 280 281 /** Returns true for finite SkPoint array values between negative SK_ScalarMax and 282 positive SK_ScalarMax. Returns false for any SkPoint array value of 283 SK_ScalarInfinity, SK_ScalarNegativeInfinity, or SK_ScalarNaN. 284 285 @return true if all SkPoint values are finite 286 */ isFinite()287 bool isFinite() const { 288 SkDEBUGCODE(this->validate();) 289 return fPathRef->isFinite(); 290 } 291 292 /** Returns true if the path is volatile; it will not be altered or discarded 293 by the caller after it is drawn. SkPath by default have volatile set false, allowing 294 SkSurface to attach a cache of data which speeds repeated drawing. If true, SkSurface 295 may not speed repeated drawing. 296 297 @return true if caller will alter SkPath after drawing 298 */ isVolatile()299 bool isVolatile() const { 300 return SkToBool(fIsVolatile); 301 } 302 303 /** Specifies whether SkPath is volatile; whether it will be altered or discarded 304 by the caller after it is drawn. SkPath by default have volatile set false, allowing 305 SkBaseDevice to attach a cache of data which speeds repeated drawing. 306 307 Mark temporary paths, discarded or modified after use, as volatile 308 to inform SkBaseDevice that the path need not be cached. 309 310 Mark animating SkPath volatile to improve performance. 311 Mark unchanging SkPath non-volatile to improve repeated rendering. 312 313 raster surface SkPath draws are affected by volatile for some shadows. 314 GPU surface SkPath draws are affected by volatile for some shadows and concave geometries. 315 316 @param isVolatile true if caller will alter SkPath after drawing 317 */ setIsVolatile(bool isVolatile)318 void setIsVolatile(bool isVolatile) { 319 fIsVolatile = isVolatile; 320 } 321 322 /** Tests if line between SkPoint pair is degenerate. 323 Line with no length or that moves a very short distance is degenerate; it is 324 treated as a point. 325 326 exact changes the equality test. If true, returns true only if p1 equals p2. 327 If false, returns true if p1 equals or nearly equals p2. 328 329 @param p1 line start point 330 @param p2 line end point 331 @param exact if false, allow nearly equals 332 @return true if line is degenerate; its length is effectively zero 333 334 example: https://fiddle.skia.org/c/@Path_IsLineDegenerate 335 */ 336 static bool IsLineDegenerate(const SkPoint& p1, const SkPoint& p2, bool exact); 337 338 /** Tests if quad is degenerate. 339 Quad with no length or that moves a very short distance is degenerate; it is 340 treated as a point. 341 342 @param p1 quad start point 343 @param p2 quad control point 344 @param p3 quad end point 345 @param exact if true, returns true only if p1, p2, and p3 are equal; 346 if false, returns true if p1, p2, and p3 are equal or nearly equal 347 @return true if quad is degenerate; its length is effectively zero 348 */ 349 static bool IsQuadDegenerate(const SkPoint& p1, const SkPoint& p2, 350 const SkPoint& p3, bool exact); 351 352 /** Tests if cubic is degenerate. 353 Cubic with no length or that moves a very short distance is degenerate; it is 354 treated as a point. 355 356 @param p1 cubic start point 357 @param p2 cubic control point 1 358 @param p3 cubic control point 2 359 @param p4 cubic end point 360 @param exact if true, returns true only if p1, p2, p3, and p4 are equal; 361 if false, returns true if p1, p2, p3, and p4 are equal or nearly equal 362 @return true if cubic is degenerate; its length is effectively zero 363 */ 364 static bool IsCubicDegenerate(const SkPoint& p1, const SkPoint& p2, 365 const SkPoint& p3, const SkPoint& p4, bool exact); 366 367 /** Returns true if SkPath contains only one line; 368 SkPath::Verb array has two entries: kMove_Verb, kLine_Verb. 369 If SkPath contains one line and line is not nullptr, line is set to 370 line start point and line end point. 371 Returns false if SkPath is not one line; line is unaltered. 372 373 @param line storage for line. May be nullptr 374 @return true if SkPath contains exactly one line 375 376 example: https://fiddle.skia.org/c/@Path_isLine 377 */ 378 bool isLine(SkPoint line[2]) const; 379 380 /** Returns the number of points in SkPath. 381 SkPoint count is initially zero. 382 383 @return SkPath SkPoint array length 384 385 example: https://fiddle.skia.org/c/@Path_countPoints 386 */ 387 int countPoints() const; 388 389 /** Returns SkPoint at index in SkPoint array. Valid range for index is 390 0 to countPoints() - 1. 391 Returns (0, 0) if index is out of range. 392 393 @param index SkPoint array element selector 394 @return SkPoint array value or (0, 0) 395 396 example: https://fiddle.skia.org/c/@Path_getPoint 397 */ 398 SkPoint getPoint(int index) const; 399 400 /** Returns number of points in SkPath. Up to max points are copied. 401 points may be nullptr; then, max must be zero. 402 If max is greater than number of points, excess points storage is unaltered. 403 404 @param points storage for SkPath SkPoint array. May be nullptr 405 @param max maximum to copy; must be greater than or equal to zero 406 @return SkPath SkPoint array length 407 408 example: https://fiddle.skia.org/c/@Path_getPoints 409 */ 410 int getPoints(SkPoint points[], int max) const; 411 412 /** Returns the number of verbs: kMove_Verb, kLine_Verb, kQuad_Verb, kConic_Verb, 413 kCubic_Verb, and kClose_Verb; added to SkPath. 414 415 @return length of verb array 416 417 example: https://fiddle.skia.org/c/@Path_countVerbs 418 */ 419 int countVerbs() const; 420 421 /** Returns the number of verbs in the path. Up to max verbs are copied. The 422 verbs are copied as one byte per verb. 423 424 @param verbs storage for verbs, may be nullptr 425 @param max maximum number to copy into verbs 426 @return the actual number of verbs in the path 427 428 example: https://fiddle.skia.org/c/@Path_getVerbs 429 */ 430 int getVerbs(uint8_t verbs[], int max) const; 431 432 /** Returns the approximate byte size of the SkPath in memory. 433 434 @return approximate size 435 */ 436 size_t approximateBytesUsed() const; 437 438 /** Exchanges the verb array, SkPoint array, weights, and SkPath::FillType with other. 439 Cached state is also exchanged. swap() internally exchanges pointers, so 440 it is lightweight and does not allocate memory. 441 442 swap() usage has largely been replaced by operator=(const SkPath& path). 443 SkPath do not copy their content on assignment until they are written to, 444 making assignment as efficient as swap(). 445 446 @param other SkPath exchanged by value 447 448 example: https://fiddle.skia.org/c/@Path_swap 449 */ 450 void swap(SkPath& other); 451 452 /** Returns minimum and maximum axes values of SkPoint array. 453 Returns (0, 0, 0, 0) if SkPath contains no points. Returned bounds width and height may 454 be larger or smaller than area affected when SkPath is drawn. 455 456 SkRect returned includes all SkPoint added to SkPath, including SkPoint associated with 457 kMove_Verb that define empty contours. 458 459 @return bounds of all SkPoint in SkPoint array 460 */ getBounds()461 const SkRect& getBounds() const { 462 return fPathRef->getBounds(); 463 } 464 465 /** Updates internal bounds so that subsequent calls to getBounds() are instantaneous. 466 Unaltered copies of SkPath may also access cached bounds through getBounds(). 467 468 For now, identical to calling getBounds() and ignoring the returned value. 469 470 Call to prepare SkPath subsequently drawn from multiple threads, 471 to avoid a race condition where each draw separately computes the bounds. 472 */ updateBoundsCache()473 void updateBoundsCache() const { 474 // for now, just calling getBounds() is sufficient 475 this->getBounds(); 476 } 477 478 /** Returns minimum and maximum axes values of the lines and curves in SkPath. 479 Returns (0, 0, 0, 0) if SkPath contains no points. 480 Returned bounds width and height may be larger or smaller than area affected 481 when SkPath is drawn. 482 483 Includes SkPoint associated with kMove_Verb that define empty 484 contours. 485 486 Behaves identically to getBounds() when SkPath contains 487 only lines. If SkPath contains curves, computed bounds includes 488 the maximum extent of the quad, conic, or cubic; is slower than getBounds(); 489 and unlike getBounds(), does not cache the result. 490 491 @return tight bounds of curves in SkPath 492 493 example: https://fiddle.skia.org/c/@Path_computeTightBounds 494 */ 495 SkRect computeTightBounds() const; 496 497 /** Returns true if rect is contained by SkPath. 498 May return false when rect is contained by SkPath. 499 500 For now, only returns true if SkPath has one contour and is convex. 501 rect may share points and edges with SkPath and be contained. 502 Returns true if rect is empty, that is, it has zero width or height; and 503 the SkPoint or line described by rect is contained by SkPath. 504 505 @param rect SkRect, line, or SkPoint checked for containment 506 @return true if rect is contained 507 508 example: https://fiddle.skia.org/c/@Path_conservativelyContainsRect 509 */ 510 bool conservativelyContainsRect(const SkRect& rect) const; 511 512 /** Grows SkPath verb array and SkPoint array to contain extraPtCount additional SkPoint. 513 May improve performance and use less memory by 514 reducing the number and size of allocations when creating SkPath. 515 516 @param extraPtCount number of additional SkPoint to allocate 517 518 example: https://fiddle.skia.org/c/@Path_incReserve 519 */ 520 void incReserve(int extraPtCount); 521 522 /** Shrinks SkPath verb array and SkPoint array storage to discard unused capacity. 523 May reduce the heap overhead for SkPath known to be fully constructed. 524 */ 525 void shrinkToFit(); 526 527 /** Adds beginning of contour at SkPoint (x, y). 528 529 @param x x-axis value of contour start 530 @param y y-axis value of contour start 531 @return reference to SkPath 532 533 example: https://fiddle.skia.org/c/@Path_moveTo 534 */ 535 SkPath& moveTo(SkScalar x, SkScalar y); 536 537 /** Adds beginning of contour at SkPoint p. 538 539 @param p contour start 540 @return reference to SkPath 541 */ moveTo(const SkPoint & p)542 SkPath& moveTo(const SkPoint& p) { 543 return this->moveTo(p.fX, p.fY); 544 } 545 546 /** Adds beginning of contour relative to last point. 547 If SkPath is empty, starts contour at (dx, dy). 548 Otherwise, start contour at last point offset by (dx, dy). 549 Function name stands for "relative move to". 550 551 @param dx offset from last point to contour start on x-axis 552 @param dy offset from last point to contour start on y-axis 553 @return reference to SkPath 554 555 example: https://fiddle.skia.org/c/@Path_rMoveTo 556 */ 557 SkPath& rMoveTo(SkScalar dx, SkScalar dy); 558 559 /** Adds line from last point to (x, y). If SkPath is empty, or last SkPath::Verb is 560 kClose_Verb, last point is set to (0, 0) before adding line. 561 562 lineTo() appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed. 563 lineTo() then appends kLine_Verb to verb array and (x, y) to SkPoint array. 564 565 @param x end of added line on x-axis 566 @param y end of added line on y-axis 567 @return reference to SkPath 568 569 example: https://fiddle.skia.org/c/@Path_lineTo 570 */ 571 SkPath& lineTo(SkScalar x, SkScalar y); 572 573 /** Adds line from last point to SkPoint p. If SkPath is empty, or last SkPath::Verb is 574 kClose_Verb, last point is set to (0, 0) before adding line. 575 576 lineTo() first appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed. 577 lineTo() then appends kLine_Verb to verb array and SkPoint p to SkPoint array. 578 579 @param p end SkPoint of added line 580 @return reference to SkPath 581 */ lineTo(const SkPoint & p)582 SkPath& lineTo(const SkPoint& p) { 583 return this->lineTo(p.fX, p.fY); 584 } 585 586 /** Adds line from last point to vector (dx, dy). If SkPath is empty, or last SkPath::Verb is 587 kClose_Verb, last point is set to (0, 0) before adding line. 588 589 Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed; 590 then appends kLine_Verb to verb array and line end to SkPoint array. 591 Line end is last point plus vector (dx, dy). 592 Function name stands for "relative line to". 593 594 @param dx offset from last point to line end on x-axis 595 @param dy offset from last point to line end on y-axis 596 @return reference to SkPath 597 598 example: https://fiddle.skia.org/c/@Path_rLineTo 599 example: https://fiddle.skia.org/c/@Quad_a 600 example: https://fiddle.skia.org/c/@Quad_b 601 */ 602 SkPath& rLineTo(SkScalar dx, SkScalar dy); 603 604 /** Adds quad from last point towards (x1, y1), to (x2, y2). 605 If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0) 606 before adding quad. 607 608 Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed; 609 then appends kQuad_Verb to verb array; and (x1, y1), (x2, y2) 610 to SkPoint array. 611 612 @param x1 control SkPoint of quad on x-axis 613 @param y1 control SkPoint of quad on y-axis 614 @param x2 end SkPoint of quad on x-axis 615 @param y2 end SkPoint of quad on y-axis 616 @return reference to SkPath 617 618 example: https://fiddle.skia.org/c/@Path_quadTo 619 */ 620 SkPath& quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2); 621 622 /** Adds quad from last point towards SkPoint p1, to SkPoint p2. 623 If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0) 624 before adding quad. 625 626 Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed; 627 then appends kQuad_Verb to verb array; and SkPoint p1, p2 628 to SkPoint array. 629 630 @param p1 control SkPoint of added quad 631 @param p2 end SkPoint of added quad 632 @return reference to SkPath 633 */ quadTo(const SkPoint & p1,const SkPoint & p2)634 SkPath& quadTo(const SkPoint& p1, const SkPoint& p2) { 635 return this->quadTo(p1.fX, p1.fY, p2.fX, p2.fY); 636 } 637 638 /** Adds quad from last point towards vector (dx1, dy1), to vector (dx2, dy2). 639 If SkPath is empty, or last SkPath::Verb 640 is kClose_Verb, last point is set to (0, 0) before adding quad. 641 642 Appends kMove_Verb to verb array and (0, 0) to SkPoint array, 643 if needed; then appends kQuad_Verb to verb array; and appends quad 644 control and quad end to SkPoint array. 645 Quad control is last point plus vector (dx1, dy1). 646 Quad end is last point plus vector (dx2, dy2). 647 Function name stands for "relative quad to". 648 649 @param dx1 offset from last point to quad control on x-axis 650 @param dy1 offset from last point to quad control on y-axis 651 @param dx2 offset from last point to quad end on x-axis 652 @param dy2 offset from last point to quad end on y-axis 653 @return reference to SkPath 654 655 example: https://fiddle.skia.org/c/@Conic_Weight_a 656 example: https://fiddle.skia.org/c/@Conic_Weight_b 657 example: https://fiddle.skia.org/c/@Conic_Weight_c 658 example: https://fiddle.skia.org/c/@Path_rQuadTo 659 */ 660 SkPath& rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2); 661 662 /** Adds conic from last point towards (x1, y1), to (x2, y2), weighted by w. 663 If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0) 664 before adding conic. 665 666 Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed. 667 668 If w is finite and not one, appends kConic_Verb to verb array; 669 and (x1, y1), (x2, y2) to SkPoint array; and w to conic weights. 670 671 If w is one, appends kQuad_Verb to verb array, and 672 (x1, y1), (x2, y2) to SkPoint array. 673 674 If w is not finite, appends kLine_Verb twice to verb array, and 675 (x1, y1), (x2, y2) to SkPoint array. 676 677 @param x1 control SkPoint of conic on x-axis 678 @param y1 control SkPoint of conic on y-axis 679 @param x2 end SkPoint of conic on x-axis 680 @param y2 end SkPoint of conic on y-axis 681 @param w weight of added conic 682 @return reference to SkPath 683 */ 684 SkPath& conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, 685 SkScalar w); 686 687 /** Adds conic from last point towards SkPoint p1, to SkPoint p2, weighted by w. 688 If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0) 689 before adding conic. 690 691 Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed. 692 693 If w is finite and not one, appends kConic_Verb to verb array; 694 and SkPoint p1, p2 to SkPoint array; and w to conic weights. 695 696 If w is one, appends kQuad_Verb to verb array, and SkPoint p1, p2 697 to SkPoint array. 698 699 If w is not finite, appends kLine_Verb twice to verb array, and 700 SkPoint p1, p2 to SkPoint array. 701 702 @param p1 control SkPoint of added conic 703 @param p2 end SkPoint of added conic 704 @param w weight of added conic 705 @return reference to SkPath 706 */ conicTo(const SkPoint & p1,const SkPoint & p2,SkScalar w)707 SkPath& conicTo(const SkPoint& p1, const SkPoint& p2, SkScalar w) { 708 return this->conicTo(p1.fX, p1.fY, p2.fX, p2.fY, w); 709 } 710 711 /** Adds conic from last point towards vector (dx1, dy1), to vector (dx2, dy2), 712 weighted by w. If SkPath is empty, or last SkPath::Verb 713 is kClose_Verb, last point is set to (0, 0) before adding conic. 714 715 Appends kMove_Verb to verb array and (0, 0) to SkPoint array, 716 if needed. 717 718 If w is finite and not one, next appends kConic_Verb to verb array, 719 and w is recorded as conic weight; otherwise, if w is one, appends 720 kQuad_Verb to verb array; or if w is not finite, appends kLine_Verb 721 twice to verb array. 722 723 In all cases appends SkPoint control and end to SkPoint array. 724 control is last point plus vector (dx1, dy1). 725 end is last point plus vector (dx2, dy2). 726 727 Function name stands for "relative conic to". 728 729 @param dx1 offset from last point to conic control on x-axis 730 @param dy1 offset from last point to conic control on y-axis 731 @param dx2 offset from last point to conic end on x-axis 732 @param dy2 offset from last point to conic end on y-axis 733 @param w weight of added conic 734 @return reference to SkPath 735 */ 736 SkPath& rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2, 737 SkScalar w); 738 739 /** Adds cubic from last point towards (x1, y1), then towards (x2, y2), ending at 740 (x3, y3). If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to 741 (0, 0) before adding cubic. 742 743 Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed; 744 then appends kCubic_Verb to verb array; and (x1, y1), (x2, y2), (x3, y3) 745 to SkPoint array. 746 747 @param x1 first control SkPoint of cubic on x-axis 748 @param y1 first control SkPoint of cubic on y-axis 749 @param x2 second control SkPoint of cubic on x-axis 750 @param y2 second control SkPoint of cubic on y-axis 751 @param x3 end SkPoint of cubic on x-axis 752 @param y3 end SkPoint of cubic on y-axis 753 @return reference to SkPath 754 */ 755 SkPath& cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, 756 SkScalar x3, SkScalar y3); 757 758 /** Adds cubic from last point towards SkPoint p1, then towards SkPoint p2, ending at 759 SkPoint p3. If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to 760 (0, 0) before adding cubic. 761 762 Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed; 763 then appends kCubic_Verb to verb array; and SkPoint p1, p2, p3 764 to SkPoint array. 765 766 @param p1 first control SkPoint of cubic 767 @param p2 second control SkPoint of cubic 768 @param p3 end SkPoint of cubic 769 @return reference to SkPath 770 */ cubicTo(const SkPoint & p1,const SkPoint & p2,const SkPoint & p3)771 SkPath& cubicTo(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3) { 772 return this->cubicTo(p1.fX, p1.fY, p2.fX, p2.fY, p3.fX, p3.fY); 773 } 774 775 /** Adds cubic from last point towards vector (dx1, dy1), then towards 776 vector (dx2, dy2), to vector (dx3, dy3). 777 If SkPath is empty, or last SkPath::Verb 778 is kClose_Verb, last point is set to (0, 0) before adding cubic. 779 780 Appends kMove_Verb to verb array and (0, 0) to SkPoint array, 781 if needed; then appends kCubic_Verb to verb array; and appends cubic 782 control and cubic end to SkPoint array. 783 Cubic control is last point plus vector (dx1, dy1). 784 Cubic end is last point plus vector (dx2, dy2). 785 Function name stands for "relative cubic to". 786 787 @param dx1 offset from last point to first cubic control on x-axis 788 @param dy1 offset from last point to first cubic control on y-axis 789 @param dx2 offset from last point to second cubic control on x-axis 790 @param dy2 offset from last point to second cubic control on y-axis 791 @param dx3 offset from last point to cubic end on x-axis 792 @param dy3 offset from last point to cubic end on y-axis 793 @return reference to SkPath 794 */ 795 SkPath& rCubicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2, 796 SkScalar dx3, SkScalar dy3); 797 798 /** Appends arc to SkPath. Arc added is part of ellipse 799 bounded by oval, from startAngle through sweepAngle. Both startAngle and 800 sweepAngle are measured in degrees, where zero degrees is aligned with the 801 positive x-axis, and positive sweeps extends arc clockwise. 802 803 arcTo() adds line connecting SkPath last SkPoint to initial arc SkPoint if forceMoveTo 804 is false and SkPath is not empty. Otherwise, added contour begins with first point 805 of arc. Angles greater than -360 and less than 360 are treated modulo 360. 806 807 @param oval bounds of ellipse containing arc 808 @param startAngle starting angle of arc in degrees 809 @param sweepAngle sweep, in degrees. Positive is clockwise; treated modulo 360 810 @param forceMoveTo true to start a new contour with arc 811 @return reference to SkPath 812 813 example: https://fiddle.skia.org/c/@Path_arcTo 814 */ 815 SkPath& arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo); 816 817 /** Appends arc to SkPath, after appending line if needed. Arc is implemented by conic 818 weighted to describe part of circle. Arc is contained by tangent from 819 last SkPath point to (x1, y1), and tangent from (x1, y1) to (x2, y2). Arc 820 is part of circle sized to radius, positioned so it touches both tangent lines. 821 822 If last Path Point does not start Arc, arcTo appends connecting Line to Path. 823 The length of Vector from (x1, y1) to (x2, y2) does not affect Arc. 824 825 Arc sweep is always less than 180 degrees. If radius is zero, or if 826 tangents are nearly parallel, arcTo appends Line from last Path Point to (x1, y1). 827 828 arcTo appends at most one Line and one conic. 829 arcTo implements the functionality of PostScript arct and HTML Canvas arcTo. 830 831 @param x1 x-axis value common to pair of tangents 832 @param y1 y-axis value common to pair of tangents 833 @param x2 x-axis value end of second tangent 834 @param y2 y-axis value end of second tangent 835 @param radius distance from arc to circle center 836 @return reference to SkPath 837 838 example: https://fiddle.skia.org/c/@Path_arcTo_2_a 839 example: https://fiddle.skia.org/c/@Path_arcTo_2_b 840 example: https://fiddle.skia.org/c/@Path_arcTo_2_c 841 */ 842 SkPath& arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar radius); 843 844 /** Appends arc to SkPath, after appending line if needed. Arc is implemented by conic 845 weighted to describe part of circle. Arc is contained by tangent from 846 last SkPath point to p1, and tangent from p1 to p2. Arc 847 is part of circle sized to radius, positioned so it touches both tangent lines. 848 849 If last SkPath SkPoint does not start arc, arcTo() appends connecting line to SkPath. 850 The length of vector from p1 to p2 does not affect arc. 851 852 Arc sweep is always less than 180 degrees. If radius is zero, or if 853 tangents are nearly parallel, arcTo() appends line from last SkPath SkPoint to p1. 854 855 arcTo() appends at most one line and one conic. 856 arcTo() implements the functionality of PostScript arct and HTML Canvas arcTo. 857 858 @param p1 SkPoint common to pair of tangents 859 @param p2 end of second tangent 860 @param radius distance from arc to circle center 861 @return reference to SkPath 862 */ arcTo(const SkPoint p1,const SkPoint p2,SkScalar radius)863 SkPath& arcTo(const SkPoint p1, const SkPoint p2, SkScalar radius) { 864 return this->arcTo(p1.fX, p1.fY, p2.fX, p2.fY, radius); 865 } 866 867 /** \enum SkPath::ArcSize 868 Four oval parts with radii (rx, ry) start at last SkPath SkPoint and ends at (x, y). 869 ArcSize and Direction select one of the four oval parts. 870 */ 871 enum ArcSize { 872 kSmall_ArcSize, //!< smaller of arc pair 873 kLarge_ArcSize, //!< larger of arc pair 874 }; 875 876 /** Appends arc to SkPath. Arc is implemented by one or more conics weighted to 877 describe part of oval with radii (rx, ry) rotated by xAxisRotate degrees. Arc 878 curves from last SkPath SkPoint to (x, y), choosing one of four possible routes: 879 clockwise or counterclockwise, and smaller or larger. 880 881 Arc sweep is always less than 360 degrees. arcTo() appends line to (x, y) if 882 either radii are zero, or if last SkPath SkPoint equals (x, y). arcTo() scales radii 883 (rx, ry) to fit last SkPath SkPoint and (x, y) if both are greater than zero but 884 too small. 885 886 arcTo() appends up to four conic curves. 887 arcTo() implements the functionality of SVG arc, although SVG sweep-flag value 888 is opposite the integer value of sweep; SVG sweep-flag uses 1 for clockwise, 889 while kCW_Direction cast to int is zero. 890 891 @param rx radius on x-axis before x-axis rotation 892 @param ry radius on y-axis before x-axis rotation 893 @param xAxisRotate x-axis rotation in degrees; positive values are clockwise 894 @param largeArc chooses smaller or larger arc 895 @param sweep chooses clockwise or counterclockwise arc 896 @param x end of arc 897 @param y end of arc 898 @return reference to SkPath 899 */ 900 SkPath& arcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc, 901 SkPathDirection sweep, SkScalar x, SkScalar y); 902 903 /** Appends arc to SkPath. Arc is implemented by one or more conic weighted to describe 904 part of oval with radii (r.fX, r.fY) rotated by xAxisRotate degrees. Arc curves 905 from last SkPath SkPoint to (xy.fX, xy.fY), choosing one of four possible routes: 906 clockwise or counterclockwise, 907 and smaller or larger. 908 909 Arc sweep is always less than 360 degrees. arcTo() appends line to xy if either 910 radii are zero, or if last SkPath SkPoint equals (xy.fX, xy.fY). arcTo() scales radii r to 911 fit last SkPath SkPoint and xy if both are greater than zero but too small to describe 912 an arc. 913 914 arcTo() appends up to four conic curves. 915 arcTo() implements the functionality of SVG arc, although SVG sweep-flag value is 916 opposite the integer value of sweep; SVG sweep-flag uses 1 for clockwise, while 917 kCW_Direction cast to int is zero. 918 919 @param r radii on axes before x-axis rotation 920 @param xAxisRotate x-axis rotation in degrees; positive values are clockwise 921 @param largeArc chooses smaller or larger arc 922 @param sweep chooses clockwise or counterclockwise arc 923 @param xy end of arc 924 @return reference to SkPath 925 */ arcTo(const SkPoint r,SkScalar xAxisRotate,ArcSize largeArc,SkPathDirection sweep,const SkPoint xy)926 SkPath& arcTo(const SkPoint r, SkScalar xAxisRotate, ArcSize largeArc, SkPathDirection sweep, 927 const SkPoint xy) { 928 return this->arcTo(r.fX, r.fY, xAxisRotate, largeArc, sweep, xy.fX, xy.fY); 929 } 930 931 /** Appends arc to SkPath, relative to last SkPath SkPoint. Arc is implemented by one or 932 more conic, weighted to describe part of oval with radii (rx, ry) rotated by 933 xAxisRotate degrees. Arc curves from last SkPath SkPoint to relative end SkPoint: 934 (dx, dy), choosing one of four possible routes: clockwise or 935 counterclockwise, and smaller or larger. If SkPath is empty, the start arc SkPoint 936 is (0, 0). 937 938 Arc sweep is always less than 360 degrees. arcTo() appends line to end SkPoint 939 if either radii are zero, or if last SkPath SkPoint equals end SkPoint. 940 arcTo() scales radii (rx, ry) to fit last SkPath SkPoint and end SkPoint if both are 941 greater than zero but too small to describe an arc. 942 943 arcTo() appends up to four conic curves. 944 arcTo() implements the functionality of svg arc, although SVG "sweep-flag" value is 945 opposite the integer value of sweep; SVG "sweep-flag" uses 1 for clockwise, while 946 kCW_Direction cast to int is zero. 947 948 @param rx radius before x-axis rotation 949 @param ry radius before x-axis rotation 950 @param xAxisRotate x-axis rotation in degrees; positive values are clockwise 951 @param largeArc chooses smaller or larger arc 952 @param sweep chooses clockwise or counterclockwise arc 953 @param dx x-axis offset end of arc from last SkPath SkPoint 954 @param dy y-axis offset end of arc from last SkPath SkPoint 955 @return reference to SkPath 956 */ 957 SkPath& rArcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc, 958 SkPathDirection sweep, SkScalar dx, SkScalar dy); 959 960 /** Appends kClose_Verb to SkPath. A closed contour connects the first and last SkPoint 961 with line, forming a continuous loop. Open and closed contour draw the same 962 with SkPaint::kFill_Style. With SkPaint::kStroke_Style, open contour draws 963 SkPaint::Cap at contour start and end; closed contour draws 964 SkPaint::Join at contour start and end. 965 966 close() has no effect if SkPath is empty or last SkPath SkPath::Verb is kClose_Verb. 967 968 @return reference to SkPath 969 970 example: https://fiddle.skia.org/c/@Path_close 971 */ 972 SkPath& close(); 973 974 /** Approximates conic with quad array. Conic is constructed from start SkPoint p0, 975 control SkPoint p1, end SkPoint p2, and weight w. 976 Quad array is stored in pts; this storage is supplied by caller. 977 Maximum quad count is 2 to the pow2. 978 Every third point in array shares last SkPoint of previous quad and first SkPoint of 979 next quad. Maximum pts storage size is given by: 980 (1 + 2 * (1 << pow2)) * sizeof(SkPoint). 981 982 Returns quad count used the approximation, which may be smaller 983 than the number requested. 984 985 conic weight determines the amount of influence conic control point has on the curve. 986 w less than one represents an elliptical section. w greater than one represents 987 a hyperbolic section. w equal to one represents a parabolic section. 988 989 Two quad curves are sufficient to approximate an elliptical conic with a sweep 990 of up to 90 degrees; in this case, set pow2 to one. 991 992 @param p0 conic start SkPoint 993 @param p1 conic control SkPoint 994 @param p2 conic end SkPoint 995 @param w conic weight 996 @param pts storage for quad array 997 @param pow2 quad count, as power of two, normally 0 to 5 (1 to 32 quad curves) 998 @return number of quad curves written to pts 999 */ 1000 static int ConvertConicToQuads(const SkPoint& p0, const SkPoint& p1, const SkPoint& p2, 1001 SkScalar w, SkPoint pts[], int pow2); 1002 1003 /** Returns true if SkPath is equivalent to SkRect when filled. 1004 If false: rect, isClosed, and direction are unchanged. 1005 If true: rect, isClosed, and direction are written to if not nullptr. 1006 1007 rect may be smaller than the SkPath bounds. SkPath bounds may include kMove_Verb points 1008 that do not alter the area drawn by the returned rect. 1009 1010 @param rect storage for bounds of SkRect; may be nullptr 1011 @param isClosed storage set to true if SkPath is closed; may be nullptr 1012 @param direction storage set to SkRect direction; may be nullptr 1013 @return true if SkPath contains SkRect 1014 1015 example: https://fiddle.skia.org/c/@Path_isRect 1016 */ 1017 bool isRect(SkRect* rect, bool* isClosed = nullptr, SkPathDirection* direction = nullptr) const; 1018 1019 /** Adds SkRect to SkPath, appending kMove_Verb, three kLine_Verb, and kClose_Verb, 1020 starting with top-left corner of SkRect; followed by top-right, bottom-right, 1021 and bottom-left if dir is kCW_Direction; or followed by bottom-left, 1022 bottom-right, and top-right if dir is kCCW_Direction. 1023 1024 @param rect SkRect to add as a closed contour 1025 @param dir SkPath::Direction to wind added contour 1026 @return reference to SkPath 1027 1028 example: https://fiddle.skia.org/c/@Path_addRect 1029 */ 1030 SkPath& addRect(const SkRect& rect, SkPathDirection dir = SkPathDirection::kCW); 1031 1032 /** Adds SkRect to SkPath, appending kMove_Verb, three kLine_Verb, and kClose_Verb. 1033 If dir is kCW_Direction, SkRect corners are added clockwise; if dir is 1034 kCCW_Direction, SkRect corners are added counterclockwise. 1035 start determines the first corner added. 1036 1037 @param rect SkRect to add as a closed contour 1038 @param dir SkPath::Direction to wind added contour 1039 @param start initial corner of SkRect to add 1040 @return reference to SkPath 1041 1042 example: https://fiddle.skia.org/c/@Path_addRect_2 1043 */ 1044 SkPath& addRect(const SkRect& rect, SkPathDirection dir, unsigned start); 1045 1046 /** Adds SkRect (left, top, right, bottom) to SkPath, 1047 appending kMove_Verb, three kLine_Verb, and kClose_Verb, 1048 starting with top-left corner of SkRect; followed by top-right, bottom-right, 1049 and bottom-left if dir is kCW_Direction; or followed by bottom-left, 1050 bottom-right, and top-right if dir is kCCW_Direction. 1051 1052 @param left smaller x-axis value of SkRect 1053 @param top smaller y-axis value of SkRect 1054 @param right larger x-axis value of SkRect 1055 @param bottom larger y-axis value of SkRect 1056 @param dir SkPath::Direction to wind added contour 1057 @return reference to SkPath 1058 */ 1059 SkPath& addRect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom, 1060 SkPathDirection dir = SkPathDirection::kCW); 1061 1062 /** Adds oval to path, appending kMove_Verb, four kConic_Verb, and kClose_Verb. 1063 Oval is upright ellipse bounded by SkRect oval with radii equal to half oval width 1064 and half oval height. Oval begins at (oval.fRight, oval.centerY()) and continues 1065 clockwise if dir is kCW_Direction, counterclockwise if dir is kCCW_Direction. 1066 1067 @param oval bounds of ellipse added 1068 @param dir SkPath::Direction to wind ellipse 1069 @return reference to SkPath 1070 1071 example: https://fiddle.skia.org/c/@Path_addOval 1072 */ 1073 SkPath& addOval(const SkRect& oval, SkPathDirection dir = SkPathDirection::kCW); 1074 1075 /** Adds oval to SkPath, appending kMove_Verb, four kConic_Verb, and kClose_Verb. 1076 Oval is upright ellipse bounded by SkRect oval with radii equal to half oval width 1077 and half oval height. Oval begins at start and continues 1078 clockwise if dir is kCW_Direction, counterclockwise if dir is kCCW_Direction. 1079 1080 @param oval bounds of ellipse added 1081 @param dir SkPath::Direction to wind ellipse 1082 @param start index of initial point of ellipse 1083 @return reference to SkPath 1084 1085 example: https://fiddle.skia.org/c/@Path_addOval_2 1086 */ 1087 SkPath& addOval(const SkRect& oval, SkPathDirection dir, unsigned start); 1088 1089 /** Adds circle centered at (x, y) of size radius to SkPath, appending kMove_Verb, 1090 four kConic_Verb, and kClose_Verb. Circle begins at: (x + radius, y), continuing 1091 clockwise if dir is kCW_Direction, and counterclockwise if dir is kCCW_Direction. 1092 1093 Has no effect if radius is zero or negative. 1094 1095 @param x center of circle 1096 @param y center of circle 1097 @param radius distance from center to edge 1098 @param dir SkPath::Direction to wind circle 1099 @return reference to SkPath 1100 */ 1101 SkPath& addCircle(SkScalar x, SkScalar y, SkScalar radius, 1102 SkPathDirection dir = SkPathDirection::kCW); 1103 1104 /** Appends arc to SkPath, as the start of new contour. Arc added is part of ellipse 1105 bounded by oval, from startAngle through sweepAngle. Both startAngle and 1106 sweepAngle are measured in degrees, where zero degrees is aligned with the 1107 positive x-axis, and positive sweeps extends arc clockwise. 1108 1109 If sweepAngle <= -360, or sweepAngle >= 360; and startAngle modulo 90 is nearly 1110 zero, append oval instead of arc. Otherwise, sweepAngle values are treated 1111 modulo 360, and arc may or may not draw depending on numeric rounding. 1112 1113 @param oval bounds of ellipse containing arc 1114 @param startAngle starting angle of arc in degrees 1115 @param sweepAngle sweep, in degrees. Positive is clockwise; treated modulo 360 1116 @return reference to SkPath 1117 1118 example: https://fiddle.skia.org/c/@Path_addArc 1119 */ 1120 SkPath& addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle); 1121 1122 /** Appends SkRRect to SkPath, creating a new closed contour. SkRRect has bounds 1123 equal to rect; each corner is 90 degrees of an ellipse with radii (rx, ry). If 1124 dir is kCW_Direction, SkRRect starts at top-left of the lower-left corner and 1125 winds clockwise. If dir is kCCW_Direction, SkRRect starts at the bottom-left 1126 of the upper-left corner and winds counterclockwise. 1127 1128 If either rx or ry is too large, rx and ry are scaled uniformly until the 1129 corners fit. If rx or ry is less than or equal to zero, addRoundRect() appends 1130 SkRect rect to SkPath. 1131 1132 After appending, SkPath may be empty, or may contain: SkRect, oval, or SkRRect. 1133 1134 @param rect bounds of SkRRect 1135 @param rx x-axis radius of rounded corners on the SkRRect 1136 @param ry y-axis radius of rounded corners on the SkRRect 1137 @param dir SkPath::Direction to wind SkRRect 1138 @return reference to SkPath 1139 */ 1140 SkPath& addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, 1141 SkPathDirection dir = SkPathDirection::kCW); 1142 1143 /** Appends SkRRect to SkPath, creating a new closed contour. SkRRect has bounds 1144 equal to rect; each corner is 90 degrees of an ellipse with radii from the 1145 array. 1146 1147 @param rect bounds of SkRRect 1148 @param radii array of 8 SkScalar values, a radius pair for each corner 1149 @param dir SkPath::Direction to wind SkRRect 1150 @return reference to SkPath 1151 */ 1152 SkPath& addRoundRect(const SkRect& rect, const SkScalar radii[], 1153 SkPathDirection dir = SkPathDirection::kCW); 1154 1155 /** Adds rrect to SkPath, creating a new closed contour. If 1156 dir is kCW_Direction, rrect starts at top-left of the lower-left corner and 1157 winds clockwise. If dir is kCCW_Direction, rrect starts at the bottom-left 1158 of the upper-left corner and winds counterclockwise. 1159 1160 After appending, SkPath may be empty, or may contain: SkRect, oval, or SkRRect. 1161 1162 @param rrect bounds and radii of rounded rectangle 1163 @param dir SkPath::Direction to wind SkRRect 1164 @return reference to SkPath 1165 1166 example: https://fiddle.skia.org/c/@Path_addRRect 1167 */ 1168 SkPath& addRRect(const SkRRect& rrect, SkPathDirection dir = SkPathDirection::kCW); 1169 1170 /** Adds rrect to SkPath, creating a new closed contour. If dir is kCW_Direction, rrect 1171 winds clockwise; if dir is kCCW_Direction, rrect winds counterclockwise. 1172 start determines the first point of rrect to add. 1173 1174 @param rrect bounds and radii of rounded rectangle 1175 @param dir SkPath::Direction to wind SkRRect 1176 @param start index of initial point of SkRRect 1177 @return reference to SkPath 1178 1179 example: https://fiddle.skia.org/c/@Path_addRRect_2 1180 */ 1181 SkPath& addRRect(const SkRRect& rrect, SkPathDirection dir, unsigned start); 1182 1183 /** Adds contour created from line array, adding (count - 1) line segments. 1184 Contour added starts at pts[0], then adds a line for every additional SkPoint 1185 in pts array. If close is true, appends kClose_Verb to SkPath, connecting 1186 pts[count - 1] and pts[0]. 1187 1188 If count is zero, append kMove_Verb to path. 1189 Has no effect if count is less than one. 1190 1191 @param pts array of line sharing end and start SkPoint 1192 @param count length of SkPoint array 1193 @param close true to add line connecting contour end and start 1194 @return reference to SkPath 1195 1196 example: https://fiddle.skia.org/c/@Path_addPoly 1197 */ 1198 SkPath& addPoly(const SkPoint pts[], int count, bool close); 1199 1200 /** Adds contour created from list. Contour added starts at list[0], then adds a line 1201 for every additional SkPoint in list. If close is true, appends kClose_Verb to SkPath, 1202 connecting last and first SkPoint in list. 1203 1204 If list is empty, append kMove_Verb to path. 1205 1206 @param list array of SkPoint 1207 @param close true to add line connecting contour end and start 1208 @return reference to SkPath 1209 */ addPoly(const std::initializer_list<SkPoint> & list,bool close)1210 SkPath& addPoly(const std::initializer_list<SkPoint>& list, bool close) { 1211 return this->addPoly(list.begin(), SkToInt(list.size()), close); 1212 } 1213 1214 /** \enum SkPath::AddPathMode 1215 AddPathMode chooses how addPath() appends. Adding one SkPath to another can extend 1216 the last contour or start a new contour. 1217 */ 1218 enum AddPathMode { 1219 kAppend_AddPathMode, //!< appended to destination unaltered 1220 kExtend_AddPathMode, //!< add line if prior contour is not closed 1221 }; 1222 1223 /** Appends src to SkPath, offset by (dx, dy). 1224 1225 If mode is kAppend_AddPathMode, src verb array, SkPoint array, and conic weights are 1226 added unaltered. If mode is kExtend_AddPathMode, add line before appending 1227 verbs, SkPoint, and conic weights. 1228 1229 @param src SkPath verbs, SkPoint, and conic weights to add 1230 @param dx offset added to src SkPoint array x-axis coordinates 1231 @param dy offset added to src SkPoint array y-axis coordinates 1232 @param mode kAppend_AddPathMode or kExtend_AddPathMode 1233 @return reference to SkPath 1234 */ 1235 SkPath& addPath(const SkPath& src, SkScalar dx, SkScalar dy, 1236 AddPathMode mode = kAppend_AddPathMode); 1237 1238 /** Appends src to SkPath. 1239 1240 If mode is kAppend_AddPathMode, src verb array, SkPoint array, and conic weights are 1241 added unaltered. If mode is kExtend_AddPathMode, add line before appending 1242 verbs, SkPoint, and conic weights. 1243 1244 @param src SkPath verbs, SkPoint, and conic weights to add 1245 @param mode kAppend_AddPathMode or kExtend_AddPathMode 1246 @return reference to SkPath 1247 */ 1248 SkPath& addPath(const SkPath& src, AddPathMode mode = kAppend_AddPathMode) { 1249 SkMatrix m; 1250 m.reset(); 1251 return this->addPath(src, m, mode); 1252 } 1253 1254 /** Appends src to SkPath, transformed by matrix. Transformed curves may have different 1255 verbs, SkPoint, and conic weights. 1256 1257 If mode is kAppend_AddPathMode, src verb array, SkPoint array, and conic weights are 1258 added unaltered. If mode is kExtend_AddPathMode, add line before appending 1259 verbs, SkPoint, and conic weights. 1260 1261 @param src SkPath verbs, SkPoint, and conic weights to add 1262 @param matrix transform applied to src 1263 @param mode kAppend_AddPathMode or kExtend_AddPathMode 1264 @return reference to SkPath 1265 */ 1266 SkPath& addPath(const SkPath& src, const SkMatrix& matrix, 1267 AddPathMode mode = kAppend_AddPathMode); 1268 1269 /** Appends src to SkPath, from back to front. 1270 Reversed src always appends a new contour to SkPath. 1271 1272 @param src SkPath verbs, SkPoint, and conic weights to add 1273 @return reference to SkPath 1274 1275 example: https://fiddle.skia.org/c/@Path_reverseAddPath 1276 */ 1277 SkPath& reverseAddPath(const SkPath& src); 1278 1279 /** Offsets SkPoint array by (dx, dy). Offset SkPath replaces dst. 1280 If dst is nullptr, SkPath is replaced by offset data. 1281 1282 @param dx offset added to SkPoint array x-axis coordinates 1283 @param dy offset added to SkPoint array y-axis coordinates 1284 @param dst overwritten, translated copy of SkPath; may be nullptr 1285 1286 example: https://fiddle.skia.org/c/@Path_offset 1287 */ 1288 void offset(SkScalar dx, SkScalar dy, SkPath* dst) const; 1289 1290 /** Offsets SkPoint array by (dx, dy). SkPath is replaced by offset data. 1291 1292 @param dx offset added to SkPoint array x-axis coordinates 1293 @param dy offset added to SkPoint array y-axis coordinates 1294 */ offset(SkScalar dx,SkScalar dy)1295 void offset(SkScalar dx, SkScalar dy) { 1296 this->offset(dx, dy, this); 1297 } 1298 1299 /** Transforms verb array, SkPoint array, and weight by matrix. 1300 transform may change verbs and increase their number. 1301 Transformed SkPath replaces dst; if dst is nullptr, original data 1302 is replaced. 1303 1304 @param matrix SkMatrix to apply to SkPath 1305 @param dst overwritten, transformed copy of SkPath; may be nullptr 1306 @param pc whether to apply perspective clipping 1307 1308 example: https://fiddle.skia.org/c/@Path_transform 1309 */ 1310 void transform(const SkMatrix& matrix, SkPath* dst, 1311 SkApplyPerspectiveClip pc = SkApplyPerspectiveClip::kYes) const; 1312 1313 /** Transforms verb array, SkPoint array, and weight by matrix. 1314 transform may change verbs and increase their number. 1315 SkPath is replaced by transformed data. 1316 1317 @param matrix SkMatrix to apply to SkPath 1318 @param pc whether to apply perspective clipping 1319 */ 1320 void transform(const SkMatrix& matrix, 1321 SkApplyPerspectiveClip pc = SkApplyPerspectiveClip::kYes) { 1322 this->transform(matrix, this, pc); 1323 } 1324 1325 /** Returns last point on SkPath in lastPt. Returns false if SkPoint array is empty, 1326 storing (0, 0) if lastPt is not nullptr. 1327 1328 @param lastPt storage for final SkPoint in SkPoint array; may be nullptr 1329 @return true if SkPoint array contains one or more SkPoint 1330 1331 example: https://fiddle.skia.org/c/@Path_getLastPt 1332 */ 1333 bool getLastPt(SkPoint* lastPt) const; 1334 1335 /** Sets last point to (x, y). If SkPoint array is empty, append kMove_Verb to 1336 verb array and append (x, y) to SkPoint array. 1337 1338 @param x set x-axis value of last point 1339 @param y set y-axis value of last point 1340 1341 example: https://fiddle.skia.org/c/@Path_setLastPt 1342 */ 1343 void setLastPt(SkScalar x, SkScalar y); 1344 1345 /** Sets the last point on the path. If SkPoint array is empty, append kMove_Verb to 1346 verb array and append p to SkPoint array. 1347 1348 @param p set value of last point 1349 */ setLastPt(const SkPoint & p)1350 void setLastPt(const SkPoint& p) { 1351 this->setLastPt(p.fX, p.fY); 1352 } 1353 1354 /** \enum SkPath::SegmentMask 1355 SegmentMask constants correspond to each drawing Verb type in SkPath; for 1356 instance, if SkPath only contains lines, only the kLine_SegmentMask bit is set. 1357 */ 1358 enum SegmentMask { 1359 kLine_SegmentMask = kLine_SkPathSegmentMask, 1360 kQuad_SegmentMask = kQuad_SkPathSegmentMask, 1361 kConic_SegmentMask = kConic_SkPathSegmentMask, 1362 kCubic_SegmentMask = kCubic_SkPathSegmentMask, 1363 }; 1364 1365 /** Returns a mask, where each set bit corresponds to a SegmentMask constant 1366 if SkPath contains one or more verbs of that type. 1367 Returns zero if SkPath contains no lines, or curves: quads, conics, or cubics. 1368 1369 getSegmentMasks() returns a cached result; it is very fast. 1370 1371 @return SegmentMask bits or zero 1372 */ getSegmentMasks()1373 uint32_t getSegmentMasks() const { return fPathRef->getSegmentMasks(); } 1374 1375 /** \enum SkPath::Verb 1376 Verb instructs SkPath how to interpret one or more SkPoint and optional conic weight; 1377 manage contour, and terminate SkPath. 1378 */ 1379 enum Verb { 1380 kMove_Verb = static_cast<int>(SkPathVerb::kMove), 1381 kLine_Verb = static_cast<int>(SkPathVerb::kLine), 1382 kQuad_Verb = static_cast<int>(SkPathVerb::kQuad), 1383 kConic_Verb = static_cast<int>(SkPathVerb::kConic), 1384 kCubic_Verb = static_cast<int>(SkPathVerb::kCubic), 1385 kClose_Verb = static_cast<int>(SkPathVerb::kClose), 1386 kDone_Verb = static_cast<int>(SkPathVerb::kDone), 1387 }; 1388 1389 /** \class SkPath::Iter 1390 Iterates through verb array, and associated SkPoint array and conic weight. 1391 Provides options to treat open contours as closed, and to ignore 1392 degenerate data. 1393 */ 1394 class SK_API Iter { 1395 public: 1396 1397 /** Initializes SkPath::Iter with an empty SkPath. next() on SkPath::Iter returns 1398 kDone_Verb. 1399 Call setPath to initialize SkPath::Iter at a later time. 1400 1401 @return SkPath::Iter of empty SkPath 1402 1403 example: https://fiddle.skia.org/c/@Path_Iter_Iter 1404 */ 1405 Iter(); 1406 1407 /** Sets SkPath::Iter to return elements of verb array, SkPoint array, and conic weight in 1408 path. If forceClose is true, SkPath::Iter will add kLine_Verb and kClose_Verb after each 1409 open contour. path is not altered. 1410 1411 @param path SkPath to iterate 1412 @param forceClose true if open contours generate kClose_Verb 1413 @return SkPath::Iter of path 1414 1415 example: https://fiddle.skia.org/c/@Path_Iter_const_SkPath 1416 */ 1417 Iter(const SkPath& path, bool forceClose); 1418 1419 /** Sets SkPath::Iter to return elements of verb array, SkPoint array, and conic weight in 1420 path. If forceClose is true, SkPath::Iter will add kLine_Verb and kClose_Verb after each 1421 open contour. path is not altered. 1422 1423 @param path SkPath to iterate 1424 @param forceClose true if open contours generate kClose_Verb 1425 1426 example: https://fiddle.skia.org/c/@Path_Iter_setPath 1427 */ 1428 void setPath(const SkPath& path, bool forceClose); 1429 1430 /** Returns next SkPath::Verb in verb array, and advances SkPath::Iter. 1431 When verb array is exhausted, returns kDone_Verb. 1432 1433 Zero to four SkPoint are stored in pts, depending on the returned SkPath::Verb. 1434 1435 @param pts storage for SkPoint data describing returned SkPath::Verb 1436 @return next SkPath::Verb from verb array 1437 1438 example: https://fiddle.skia.org/c/@Path_RawIter_next 1439 */ 1440 Verb next(SkPoint pts[4]); 1441 1442 /** Returns conic weight if next() returned kConic_Verb. 1443 1444 If next() has not been called, or next() did not return kConic_Verb, 1445 result is undefined. 1446 1447 @return conic weight for conic SkPoint returned by next() 1448 */ conicWeight()1449 SkScalar conicWeight() const { return *fConicWeights; } 1450 1451 /** Returns true if last kLine_Verb returned by next() was generated 1452 by kClose_Verb. When true, the end point returned by next() is 1453 also the start point of contour. 1454 1455 If next() has not been called, or next() did not return kLine_Verb, 1456 result is undefined. 1457 1458 @return true if last kLine_Verb was generated by kClose_Verb 1459 */ isCloseLine()1460 bool isCloseLine() const { return SkToBool(fCloseLine); } 1461 1462 /** Returns true if subsequent calls to next() return kClose_Verb before returning 1463 kMove_Verb. if true, contour SkPath::Iter is processing may end with kClose_Verb, or 1464 SkPath::Iter may have been initialized with force close set to true. 1465 1466 @return true if contour is closed 1467 1468 example: https://fiddle.skia.org/c/@Path_Iter_isClosedContour 1469 */ 1470 bool isClosedContour() const; 1471 1472 private: 1473 const SkPoint* fPts; 1474 const uint8_t* fVerbs; 1475 const uint8_t* fVerbStop; 1476 const SkScalar* fConicWeights; 1477 SkPoint fMoveTo; 1478 SkPoint fLastPt; 1479 bool fForceClose; 1480 bool fNeedClose; 1481 bool fCloseLine; 1482 enum SegmentState : uint8_t { 1483 /** The current contour is empty. Starting processing or have just closed a contour. */ 1484 kEmptyContour_SegmentState, 1485 /** Have seen a move, but nothing else. */ 1486 kAfterMove_SegmentState, 1487 /** Have seen a primitive but not yet closed the path. Also the initial state. */ 1488 kAfterPrimitive_SegmentState 1489 }; 1490 SegmentState fSegmentState; 1491 1492 inline const SkPoint& cons_moveTo(); 1493 Verb autoClose(SkPoint pts[2]); 1494 }; 1495 1496 /** \class SkPath::RawIter 1497 Iterates through verb array, and associated SkPoint array and conic weight. 1498 verb array, SkPoint array, and conic weight are returned unaltered. 1499 */ 1500 class SK_API RawIter { 1501 public: 1502 1503 /** Initializes RawIter with an empty SkPath. next() on RawIter returns kDone_Verb. 1504 Call setPath to initialize SkPath::Iter at a later time. 1505 1506 @return RawIter of empty SkPath 1507 */ RawIter()1508 RawIter() {} 1509 1510 /** Sets RawIter to return elements of verb array, SkPoint array, and conic weight in path. 1511 1512 @param path SkPath to iterate 1513 @return RawIter of path 1514 */ RawIter(const SkPath & path)1515 RawIter(const SkPath& path) { 1516 setPath(path); 1517 } 1518 1519 /** Sets SkPath::Iter to return elements of verb array, SkPoint array, and conic weight in 1520 path. 1521 1522 @param path SkPath to iterate 1523 */ setPath(const SkPath & path)1524 void setPath(const SkPath& path) { 1525 fRawIter.setPathRef(*path.fPathRef.get()); 1526 } 1527 1528 /** Returns next SkPath::Verb in verb array, and advances RawIter. 1529 When verb array is exhausted, returns kDone_Verb. 1530 Zero to four SkPoint are stored in pts, depending on the returned SkPath::Verb. 1531 1532 @param pts storage for SkPoint data describing returned SkPath::Verb 1533 @return next SkPath::Verb from verb array 1534 */ next(SkPoint pts[4])1535 Verb next(SkPoint pts[4]) { 1536 return (Verb) fRawIter.next(pts); 1537 } 1538 1539 /** Returns next SkPath::Verb, but does not advance RawIter. 1540 1541 @return next SkPath::Verb from verb array 1542 */ peek()1543 Verb peek() const { 1544 return (Verb) fRawIter.peek(); 1545 } 1546 1547 /** Returns conic weight if next() returned kConic_Verb. 1548 1549 If next() has not been called, or next() did not return kConic_Verb, 1550 result is undefined. 1551 1552 @return conic weight for conic SkPoint returned by next() 1553 */ conicWeight()1554 SkScalar conicWeight() const { 1555 return fRawIter.conicWeight(); 1556 } 1557 1558 private: 1559 SkPathRef::Iter fRawIter; 1560 friend class SkPath; 1561 1562 }; 1563 1564 /** Returns true if the point (x, y) is contained by SkPath, taking into 1565 account FillType. 1566 1567 @param x x-axis value of containment test 1568 @param y y-axis value of containment test 1569 @return true if SkPoint is in SkPath 1570 1571 example: https://fiddle.skia.org/c/@Path_contains 1572 */ 1573 bool contains(SkScalar x, SkScalar y) const; 1574 1575 /** Writes text representation of SkPath to stream. If stream is nullptr, writes to 1576 standard output. Set forceClose to true to get edges used to fill SkPath. 1577 Set dumpAsHex true to generate exact binary representations 1578 of floating point numbers used in SkPoint array and conic weights. 1579 1580 @param stream writable SkWStream receiving SkPath text representation; may be nullptr 1581 @param forceClose true if missing kClose_Verb is output 1582 @param dumpAsHex true if SkScalar values are written as hexadecimal 1583 1584 example: https://fiddle.skia.org/c/@Path_dump 1585 */ 1586 void dump(SkWStream* stream, bool forceClose, bool dumpAsHex) const; 1587 1588 /** Writes text representation of SkPath to standard output. The representation may be 1589 directly compiled as C++ code. Floating point values are written 1590 with limited precision; it may not be possible to reconstruct original SkPath 1591 from output. 1592 1593 example: https://fiddle.skia.org/c/@Path_dump_2 1594 */ 1595 void dump() const; 1596 1597 /** Writes text representation of SkPath to standard output. The representation may be 1598 directly compiled as C++ code. Floating point values are written 1599 in hexadecimal to preserve their exact bit pattern. The output reconstructs the 1600 original SkPath. 1601 1602 Use instead of dump() when submitting 1603 1604 example: https://fiddle.skia.org/c/@Path_dumpHex 1605 */ 1606 void dumpHex() const; 1607 1608 /** Writes SkPath to buffer, returning the number of bytes written. 1609 Pass nullptr to obtain the storage size. 1610 1611 Writes SkPath::FillType, verb array, SkPoint array, conic weight, and 1612 additionally writes computed information like SkPath::Convexity and bounds. 1613 1614 Use only be used in concert with readFromMemory(); 1615 the format used for SkPath in memory is not guaranteed. 1616 1617 @param buffer storage for SkPath; may be nullptr 1618 @return size of storage required for SkPath; always a multiple of 4 1619 1620 example: https://fiddle.skia.org/c/@Path_writeToMemory 1621 */ 1622 size_t writeToMemory(void* buffer) const; 1623 1624 /** Writes SkPath to buffer, returning the buffer written to, wrapped in SkData. 1625 1626 serialize() writes SkPath::FillType, verb array, SkPoint array, conic weight, and 1627 additionally writes computed information like SkPath::Convexity and bounds. 1628 1629 serialize() should only be used in concert with readFromMemory(). 1630 The format used for SkPath in memory is not guaranteed. 1631 1632 @return SkPath data wrapped in SkData buffer 1633 1634 example: https://fiddle.skia.org/c/@Path_serialize 1635 */ 1636 sk_sp<SkData> serialize() const; 1637 1638 /** Initializes SkPath from buffer of size length. Returns zero if the buffer is 1639 data is inconsistent, or the length is too small. 1640 1641 Reads SkPath::FillType, verb array, SkPoint array, conic weight, and 1642 additionally reads computed information like SkPath::Convexity and bounds. 1643 1644 Used only in concert with writeToMemory(); 1645 the format used for SkPath in memory is not guaranteed. 1646 1647 @param buffer storage for SkPath 1648 @param length buffer size in bytes; must be multiple of 4 1649 @return number of bytes read, or zero on failure 1650 1651 example: https://fiddle.skia.org/c/@Path_readFromMemory 1652 */ 1653 size_t readFromMemory(const void* buffer, size_t length); 1654 1655 /** (See Skia bug 1762.) 1656 Returns a non-zero, globally unique value. A different value is returned 1657 if verb array, SkPoint array, or conic weight changes. 1658 1659 Setting SkPath::FillType does not change generation identifier. 1660 1661 Each time the path is modified, a different generation identifier will be returned. 1662 SkPath::FillType does affect generation identifier on Android framework. 1663 1664 @return non-zero, globally unique value 1665 1666 example: https://fiddle.skia.org/c/@Path_getGenerationID 1667 */ 1668 uint32_t getGenerationID() const; 1669 1670 /** Returns if SkPath data is consistent. Corrupt SkPath data is detected if 1671 internal values are out of range or internal storage does not match 1672 array dimensions. 1673 1674 @return true if SkPath data is consistent 1675 */ isValid()1676 bool isValid() const { return this->isValidImpl() && fPathRef->isValid(); } 1677 1678 private: 1679 sk_sp<SkPathRef> fPathRef; 1680 int fLastMoveToIndex; 1681 mutable std::atomic<uint8_t> fConvexity; // SkPathConvexityType 1682 mutable std::atomic<uint8_t> fFirstDirection; // really an SkPathPriv::FirstDirection 1683 uint8_t fFillType : 2; 1684 uint8_t fIsVolatile : 1; 1685 1686 /** Resets all fields other than fPathRef to their initial 'empty' values. 1687 * Assumes the caller has already emptied fPathRef. 1688 * On Android increments fGenerationID without reseting it. 1689 */ 1690 void resetFields(); 1691 1692 /** Sets all fields other than fPathRef to the values in 'that'. 1693 * Assumes the caller has already set fPathRef. 1694 * Doesn't change fGenerationID or fSourcePath on Android. 1695 */ 1696 void copyFields(const SkPath& that); 1697 1698 size_t writeToMemoryAsRRect(void* buffer) const; 1699 size_t readAsRRect(const void*, size_t); 1700 size_t readFromMemory_EQ4Or5(const void*, size_t); 1701 1702 friend class Iter; 1703 friend class SkPathPriv; 1704 friend class SkPathStroker; 1705 1706 /* Append, in reverse order, the first contour of path, ignoring path's 1707 last point. If no moveTo() call has been made for this contour, the 1708 first point is automatically set to (0,0). 1709 */ 1710 SkPath& reversePathTo(const SkPath&); 1711 1712 // called before we add points for lineTo, quadTo, cubicTo, checking to see 1713 // if we need to inject a leading moveTo first 1714 // 1715 // SkPath path; path.lineTo(...); <--- need a leading moveTo(0, 0) 1716 // SkPath path; ... path.close(); path.lineTo(...) <-- need a moveTo(previous moveTo) 1717 // 1718 inline void injectMoveToIfNeeded(); 1719 1720 inline bool hasOnlyMoveTos() const; 1721 1722 SkPathConvexityType internalGetConvexity() const; 1723 1724 /** Asserts if SkPath data is inconsistent. 1725 Debugging check intended for internal use only. 1726 */ 1727 SkDEBUGCODE(void validate() const { SkASSERT(this->isValidImpl()); } ) 1728 bool isValidImpl() const; 1729 SkDEBUGCODE(void validateRef() const { fPathRef->validate(); } ) 1730 1731 // called by stroker to see if all points (in the last contour) are equal and worthy of a cap 1732 bool isZeroLengthSincePoint(int startPtIndex) const; 1733 1734 /** Returns if the path can return a bound at no cost (true) or will have to 1735 perform some computation (false). 1736 */ hasComputedBounds()1737 bool hasComputedBounds() const { 1738 SkDEBUGCODE(this->validate();) 1739 return fPathRef->hasComputedBounds(); 1740 } 1741 1742 1743 // 'rect' needs to be sorted setBounds(const SkRect & rect)1744 void setBounds(const SkRect& rect) { 1745 SkPathRef::Editor ed(&fPathRef); 1746 1747 ed.setBounds(rect); 1748 } 1749 1750 void setPt(int index, SkScalar x, SkScalar y); 1751 1752 SkPath& dirtyAfterEdit(); 1753 1754 // Bottlenecks for working with fConvexity and fFirstDirection. 1755 // Notice the setters are const... these are mutable atomic fields. 1756 void setConvexityType(SkPathConvexityType) const; 1757 void setFirstDirection(uint8_t) const; 1758 uint8_t getFirstDirection() const; 1759 1760 friend class SkAutoPathBoundsUpdate; 1761 friend class SkAutoDisableOvalCheck; 1762 friend class SkAutoDisableDirectionCheck; 1763 friend class SkPathEdgeIter; 1764 friend class SkPathWriter; 1765 friend class SkOpBuilder; 1766 friend class SkBench_AddPathTest; // perf test reversePathTo 1767 friend class PathTest_Private; // unit test reversePathTo 1768 friend class ForceIsRRect_Private; // unit test isRRect 1769 friend class FuzzPath; // for legacy access to validateRef 1770 }; 1771 1772 #endif 1773