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