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