SkPath.h 76 KB

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