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