Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkPathPriv.h
Go to the documentation of this file.
1/*
2 * Copyright 2015 Google Inc.
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 SkPathPriv_DEFINED
9#define SkPathPriv_DEFINED
10
11#include "include/core/SkPath.h"
15#include "include/core/SkRect.h"
23
24#include <cstdint>
25#include <iterator>
26#include <utility>
27
28class SkMatrix;
29class SkRRect;
30
31static_assert(0 == static_cast<int>(SkPathFillType::kWinding), "fill_type_mismatch");
32static_assert(1 == static_cast<int>(SkPathFillType::kEvenOdd), "fill_type_mismatch");
33static_assert(2 == static_cast<int>(SkPathFillType::kInverseWinding), "fill_type_mismatch");
34static_assert(3 == static_cast<int>(SkPathFillType::kInverseEvenOdd), "fill_type_mismatch");
35
37public:
38 // skbug.com/9906: Not a perfect solution for W plane clipping, but 1/16384 is a
39 // reasonable limit (roughly 5e-5)
40 inline static constexpr SkScalar kW0PlaneDistance = 1.f / (1 << 14);
41
43 // since we agree numerically for the values in Direction, we can just cast.
44 return (SkPathFirstDirection)dir;
45 }
46
47 /**
48 * Return the opposite of the specified direction. kUnknown is its own
49 * opposite.
50 */
52 static const SkPathFirstDirection gOppositeDir[] = {
54 };
55 return gOppositeDir[(unsigned)dir];
56 }
57
58 /**
59 * Tries to compute the direction of the outer-most non-degenerate
60 * contour. If it can be computed, return that direction. If it cannot be determined,
61 * or the contour is known to be convex, return kUnknown. If the direction was determined,
62 * it is cached to make subsequent calls return quickly.
63 */
65
66 static bool IsClosedSingleContour(const SkPath& path) {
67 int verbCount = path.countVerbs();
68 if (verbCount == 0)
69 return false;
70 int moveCount = 0;
71 auto verbs = path.fPathRef->verbsBegin();
72 for (int i = 0; i < verbCount; i++) {
73 switch (verbs[i]) {
75 moveCount += 1;
76 if (moveCount > 1) {
77 return false;
78 }
79 break;
81 if (i == verbCount - 1) {
82 return true;
83 }
84 return false;
85 default: break;
86 }
87 }
88 return false;
89 }
90
91 // In some scenarios (e.g. fill or convexity checking all but the last leading move to are
92 // irrelevant to behavior). SkPath::injectMoveToIfNeeded should ensure that this is always at
93 // least 1.
94 static int LeadingMoveToCount(const SkPath& path) {
95 int verbCount = path.countVerbs();
96 auto verbs = path.fPathRef->verbsBegin();
97 for (int i = 0; i < verbCount; i++) {
98 if (verbs[i] != SkPath::Verb::kMove_Verb) {
99 return i;
100 }
101 }
102 return verbCount; // path is all move verbs
103 }
104
105 static void AddGenIDChangeListener(const SkPath& path, sk_sp<SkIDChangeListener> listener) {
106 path.fPathRef->addGenIDChangeListener(std::move(listener));
107 }
108
109 /**
110 * This returns true for a rect that has a move followed by 3 or 4 lines and a close. If
111 * 'isSimpleFill' is true, an uncloseed rect will also be accepted as long as it starts and
112 * ends at the same corner. This does not permit degenerate line or point rectangles.
113 */
114 static bool IsSimpleRect(const SkPath& path, bool isSimpleFill, SkRect* rect,
115 SkPathDirection* direction, unsigned* start);
116
117 /**
118 * Creates a path from arc params using the semantics of SkCanvas::drawArc. This function
119 * assumes empty ovals and zero sweeps have already been filtered out.
120 */
121 static void CreateDrawArcPath(SkPath* path, const SkRect& oval, SkScalar startAngle,
122 SkScalar sweepAngle, bool useCenter, bool isFillNoPathEffect);
123
124 /**
125 * Determines whether an arc produced by CreateDrawArcPath will be convex. Assumes a non-empty
126 * oval.
127 */
128 static bool DrawArcIsConvex(SkScalar sweepAngle, bool useCenter, bool isFillNoPathEffect);
129
130 static void ShrinkToFit(SkPath* path) {
131 path->shrinkToFit();
132 }
133
134 /**
135 * Returns a C++11-iterable object that traverses a path's verbs in order. e.g:
136 *
137 * for (SkPath::Verb verb : SkPathPriv::Verbs(path)) {
138 * ...
139 * }
140 */
141 struct Verbs {
142 public:
143 Verbs(const SkPath& path) : fPathRef(path.fPathRef.get()) {}
144 struct Iter {
145 void operator++() { fVerb++; }
146 bool operator!=(const Iter& b) { return fVerb != b.fVerb; }
147 SkPath::Verb operator*() { return static_cast<SkPath::Verb>(*fVerb); }
148 const uint8_t* fVerb;
149 };
150 Iter begin() { return Iter{fPathRef->verbsBegin()}; }
151 Iter end() { return Iter{fPathRef->verbsEnd()}; }
152 private:
153 Verbs(const Verbs&) = delete;
154 Verbs& operator=(const Verbs&) = delete;
155 SkPathRef* fPathRef;
156 };
157
158 /**
159 * Iterates through a raw range of path verbs, points, and conics. All values are returned
160 * unaltered.
161 *
162 * NOTE: This class's definition will be moved into SkPathPriv once RangeIter is removed.
163 */
164 using RangeIter = SkPath::RangeIter;
165
166 /**
167 * Iterable object for traversing verbs, points, and conic weights in a path:
168 *
169 * for (auto [verb, pts, weights] : SkPathPriv::Iterate(skPath)) {
170 * ...
171 * }
172 */
173 struct Iterate {
174 public:
175 Iterate(const SkPath& path)
176 : Iterate(path.fPathRef->verbsBegin(),
177 // Don't allow iteration through non-finite points.
178 (!path.isFinite()) ? path.fPathRef->verbsBegin()
179 : path.fPathRef->verbsEnd(),
180 path.fPathRef->points(), path.fPathRef->conicWeights()) {
181 }
182 Iterate(const uint8_t* verbsBegin, const uint8_t* verbsEnd, const SkPoint* points,
183 const SkScalar* weights)
184 : fVerbsBegin(verbsBegin), fVerbsEnd(verbsEnd), fPoints(points), fWeights(weights) {
185 }
186 SkPath::RangeIter begin() { return {fVerbsBegin, fPoints, fWeights}; }
187 SkPath::RangeIter end() { return {fVerbsEnd, nullptr, nullptr}; }
188 private:
189 const uint8_t* fVerbsBegin;
190 const uint8_t* fVerbsEnd;
191 const SkPoint* fPoints;
192 const SkScalar* fWeights;
193 };
194
195 /**
196 * Returns a pointer to the verb data.
197 */
198 static const uint8_t* VerbData(const SkPath& path) {
199 return path.fPathRef->verbsBegin();
200 }
201
202 /** Returns a raw pointer to the path points */
203 static const SkPoint* PointData(const SkPath& path) {
204 return path.fPathRef->points();
205 }
206
207 /** Returns the number of conic weights in the path */
208 static int ConicWeightCnt(const SkPath& path) {
209 return path.fPathRef->countWeights();
210 }
211
212 /** Returns a raw pointer to the path conic weights. */
213 static const SkScalar* ConicWeightData(const SkPath& path) {
214 return path.fPathRef->conicWeights();
215 }
216
217 /** Returns true if the underlying SkPathRef has one single owner. */
218 static bool TestingOnly_unique(const SkPath& path) {
219 return path.fPathRef->unique();
220 }
221
222 // Won't be needed once we can make path's immutable (with their bounds always computed)
223 static bool HasComputedBounds(const SkPath& path) {
224 return path.hasComputedBounds();
225 }
226
227 /** Returns true if constructed by addCircle(), addOval(); and in some cases,
228 addRoundRect(), addRRect(). SkPath constructed with conicTo() or rConicTo() will not
229 return true though SkPath draws oval.
230
231 rect receives bounds of oval.
232 dir receives SkPathDirection of oval: kCW_Direction if clockwise, kCCW_Direction if
233 counterclockwise.
234 start receives start of oval: 0 for top, 1 for right, 2 for bottom, 3 for left.
235
236 rect, dir, and start are unmodified if oval is not found.
237
238 Triggers performance optimizations on some GPU surface implementations.
239
240 @param rect storage for bounding SkRect of oval; may be nullptr
241 @param dir storage for SkPathDirection; may be nullptr
242 @param start storage for start of oval; may be nullptr
243 @return true if SkPath was constructed by method that reduces to oval
244 */
245 static bool IsOval(const SkPath& path, SkRect* rect, SkPathDirection* dir, unsigned* start) {
246 bool isCCW = false;
247 bool result = path.fPathRef->isOval(rect, &isCCW, start);
248 if (dir && result) {
250 }
251 return result;
252 }
253
254 /** Returns true if constructed by addRoundRect(), addRRect(); and if construction
255 is not empty, not SkRect, and not oval. SkPath constructed with other calls
256 will not return true though SkPath draws SkRRect.
257
258 rrect receives bounds of SkRRect.
259 dir receives SkPathDirection of oval: kCW_Direction if clockwise, kCCW_Direction if
260 counterclockwise.
261 start receives start of SkRRect: 0 for top, 1 for right, 2 for bottom, 3 for left.
262
263 rrect, dir, and start are unmodified if SkRRect is not found.
264
265 Triggers performance optimizations on some GPU surface implementations.
266
267 @param rrect storage for bounding SkRect of SkRRect; may be nullptr
268 @param dir storage for SkPathDirection; may be nullptr
269 @param start storage for start of SkRRect; may be nullptr
270 @return true if SkPath contains only SkRRect
271 */
272 static bool IsRRect(const SkPath& path, SkRRect* rrect, SkPathDirection* dir,
273 unsigned* start) {
274 bool isCCW = false;
275 bool result = path.fPathRef->isRRect(rrect, &isCCW, start);
276 if (dir && result) {
278 }
279 return result;
280 }
281
282 /**
283 * Sometimes in the drawing pipeline, we have to perform math on path coordinates, even after
284 * the path is in device-coordinates. Tessellation and clipping are two examples. Usually this
285 * is pretty modest, but it can involve subtracting/adding coordinates, or multiplying by
286 * small constants (e.g. 2,3,4). To try to preflight issues where these optionations could turn
287 * finite path values into infinities (or NaNs), we allow the upper drawing code to reject
288 * the path if its bounds (in device coordinates) is too close to max float.
289 */
290 static bool TooBigForMath(const SkRect& bounds) {
291 // This value is just a guess. smaller is safer, but we don't want to reject largish paths
292 // that we don't have to.
293 constexpr SkScalar scale_down_to_allow_for_small_multiplies = 0.25f;
294 constexpr SkScalar max = SK_ScalarMax * scale_down_to_allow_for_small_multiplies;
295
296 // use ! expression so we return true if bounds contains NaN
297 return !(bounds.fLeft >= -max && bounds.fTop >= -max &&
298 bounds.fRight <= max && bounds.fBottom <= max);
299 }
300 static bool TooBigForMath(const SkPath& path) {
301 return TooBigForMath(path.getBounds());
302 }
303
304 // Returns number of valid points for each SkPath::Iter verb
305 static int PtsInIter(unsigned verb) {
306 static const uint8_t gPtsInVerb[] = {
307 1, // kMove pts[0]
308 2, // kLine pts[0..1]
309 3, // kQuad pts[0..2]
310 3, // kConic pts[0..2]
311 4, // kCubic pts[0..3]
312 0, // kClose
313 0 // kDone
314 };
315
316 SkASSERT(verb < std::size(gPtsInVerb));
317 return gPtsInVerb[verb];
318 }
319
320 // Returns number of valid points for each verb, not including the "starter"
321 // point that the Iterator adds for line/quad/conic/cubic
322 static int PtsInVerb(unsigned verb) {
323 static const uint8_t gPtsInVerb[] = {
324 1, // kMove pts[0]
325 1, // kLine pts[0..1]
326 2, // kQuad pts[0..2]
327 2, // kConic pts[0..2]
328 3, // kCubic pts[0..3]
329 0, // kClose
330 0 // kDone
331 };
332
333 SkASSERT(verb < std::size(gPtsInVerb));
334 return gPtsInVerb[verb];
335 }
336
337 static bool IsAxisAligned(const SkPath& path);
338
339 static bool AllPointsEq(const SkPoint pts[], int count) {
340 for (int i = 1; i < count; ++i) {
341 if (pts[0] != pts[i]) {
342 return false;
343 }
344 }
345 return true;
346 }
347
348 static int LastMoveToIndex(const SkPath& path) { return path.fLastMoveToIndex; }
349
350 static bool IsRectContour(const SkPath&, bool allowPartial, int* currVerb,
351 const SkPoint** ptsPtr, bool* isClosed, SkPathDirection* direction,
352 SkRect* rect);
353
354 /** Returns true if SkPath is equivalent to nested SkRect pair when filled.
355 If false, rect and dirs are unchanged.
356 If true, rect and dirs are written to if not nullptr:
357 setting rect[0] to outer SkRect, and rect[1] to inner SkRect;
358 setting dirs[0] to SkPathDirection of outer SkRect, and dirs[1] to SkPathDirection of
359 inner SkRect.
360
361 @param rect storage for SkRect pair; may be nullptr
362 @param dirs storage for SkPathDirection pair; may be nullptr
363 @return true if SkPath contains nested SkRect pair
364 */
365 static bool IsNestedFillRects(const SkPath&, SkRect rect[2],
366 SkPathDirection dirs[2] = nullptr);
367
369 return (static_cast<int>(fill) & 2) != 0;
370 }
371
372 /** Returns equivalent SkPath::FillType representing SkPath fill inside its bounds.
373 .
374
375 @param fill one of: kWinding_FillType, kEvenOdd_FillType,
376 kInverseWinding_FillType, kInverseEvenOdd_FillType
377 @return fill, or kWinding_FillType or kEvenOdd_FillType if fill is inverted
378 */
380 return (SkPathFillType)(static_cast<int>(fill) & 1);
381 }
382
383 /**
384 * If needed (to not blow-up under a perspective matrix), clip the path, returning the
385 * answer in "result", and return true.
386 *
387 * Note result might be empty (if the path was completely clipped out).
388 *
389 * If no clipping is needed, returns false and "result" is left unchanged.
390 */
391 static bool PerspectiveClip(const SkPath& src, const SkMatrix&, SkPath* result);
392
393 /**
394 * Gets the number of GenIDChangeListeners. If another thread has access to this path then
395 * this may be stale before return and only indicates that the count was the return value
396 * at some point during the execution of the function.
397 */
398 static int GenIDChangeListenersCount(const SkPath&);
399
400 static void UpdatePathPoint(SkPath* path, int index, const SkPoint& pt) {
401 SkASSERT(index < path->countPoints());
402 SkPathRef::Editor ed(&path->fPathRef);
403 ed.writablePoints()[index] = pt;
404 path->dirtyAfterEdit();
405 }
406
407 static SkPathConvexity GetConvexity(const SkPath& path) {
408 return path.getConvexity();
409 }
411 return path.getConvexityOrUnknown();
412 }
413 static void SetConvexity(const SkPath& path, SkPathConvexity c) {
414 path.setConvexity(c);
415 }
416 static void ForceComputeConvexity(const SkPath& path) {
417 path.setConvexity(SkPathConvexity::kUnknown);
418 (void)path.isConvex();
419 }
420
421 static void ReverseAddPath(SkPathBuilder* builder, const SkPath& reverseMe) {
422 builder->privateReverseAddPath(reverseMe);
423 }
424
425 static SkPath MakePath(const SkPathVerbAnalysis& analysis,
426 const SkPoint points[],
427 const uint8_t verbs[],
428 int verbCount,
429 const SkScalar conics[],
430 SkPathFillType fillType,
431 bool isVolatile) {
432 return SkPath::MakeInternal(analysis, points, verbs, verbCount, conics, fillType,
433 isVolatile);
434 }
435};
436
437// Lightweight variant of SkPath::Iter that only returns segments (e.g. lines/conics).
438// Does not return kMove or kClose.
439// Always "auto-closes" each contour.
440// Roughly the same as SkPath::Iter(path, true), but does not return moves or closes
441//
443 const uint8_t* fVerbs;
444 const uint8_t* fVerbsStop;
445 const SkPoint* fPts;
446 const SkPoint* fMoveToPtr;
447 const SkScalar* fConicWeights;
448 SkPoint fScratch[2]; // for auto-close lines
449 bool fNeedsCloseLine;
450 bool fNextIsNewContour;
451 SkDEBUGCODE(bool fIsConic;)
452
453 enum {
454 kIllegalEdgeValue = 99
455 };
456
457public:
458 SkPathEdgeIter(const SkPath& path);
459
461 SkASSERT(fIsConic);
462 return *fConicWeights;
463 }
464
471
473 return SkPath::Verb(e);
474 }
475
476 struct Result {
477 const SkPoint* fPts; // points for the segment, or null if done
480
481 // Returns true when it holds an Edge, false when the path is done.
482 explicit operator bool() { return fPts != nullptr; }
483 };
484
486 auto closeline = [&]() {
487 fScratch[0] = fPts[-1];
488 fScratch[1] = *fMoveToPtr;
489 fNeedsCloseLine = false;
490 fNextIsNewContour = true;
491 return Result{ fScratch, Edge::kLine, false };
492 };
493
494 for (;;) {
495 SkASSERT(fVerbs <= fVerbsStop);
496 if (fVerbs == fVerbsStop) {
497 return fNeedsCloseLine
498 ? closeline()
499 : Result{ nullptr, Edge(kIllegalEdgeValue), false };
500 }
501
502 SkDEBUGCODE(fIsConic = false;)
503
504 const auto v = *fVerbs++;
505 switch (v) {
506 case SkPath::kMove_Verb: {
507 if (fNeedsCloseLine) {
508 auto res = closeline();
509 fMoveToPtr = fPts++;
510 return res;
511 }
512 fMoveToPtr = fPts++;
513 fNextIsNewContour = true;
514 } break;
516 if (fNeedsCloseLine) return closeline();
517 break;
518 default: {
519 // Actual edge.
520 const int pts_count = (v+2) / 2,
521 cws_count = (v & (v-1)) / 2;
522 SkASSERT(pts_count == SkPathPriv::PtsInIter(v) - 1);
523
524 fNeedsCloseLine = true;
525 fPts += pts_count;
526 fConicWeights += cws_count;
527
528 SkDEBUGCODE(fIsConic = (v == SkPath::kConic_Verb);)
529 SkASSERT(fIsConic == (cws_count > 0));
530
531 bool isNewContour = fNextIsNewContour;
532 fNextIsNewContour = false;
533 return { &fPts[-(pts_count + 1)], Edge(v), isNewContour };
534 }
535 }
536 }
537 }
538};
539
540#endif
SkPoint fPts[2]
int count
static const int points[]
static bool isFinite(const SkRect &r)
#define SkASSERT(cond)
Definition SkAssert.h:116
#define SkDEBUGCODE(...)
Definition SkDebug.h:23
SkPathConvexity
Definition SkPathEnums.h:13
SkPathFirstDirection
Definition SkPathEnums.h:19
SkPathDirection
Definition SkPathTypes.h:34
SkPathFillType
Definition SkPathTypes.h:11
#define SK_ScalarMax
Definition SkScalar.h:24
Result next()
Definition SkPathPriv.h:485
SkScalar conicWeight() const
Definition SkPathPriv.h:460
static SkPath::Verb EdgeToVerb(Edge e)
Definition SkPathPriv.h:472
static bool IsInverseFillType(SkPathFillType fill)
Definition SkPathPriv.h:368
static int PtsInVerb(unsigned verb)
Definition SkPathPriv.h:322
static bool IsClosedSingleContour(const SkPath &path)
Definition SkPathPriv.h:66
static SkPathConvexity GetConvexity(const SkPath &path)
Definition SkPathPriv.h:407
static bool IsRRect(const SkPath &path, SkRRect *rrect, SkPathDirection *dir, unsigned *start)
Definition SkPathPriv.h:272
static bool IsNestedFillRects(const SkPath &, SkRect rect[2], SkPathDirection dirs[2]=nullptr)
Definition SkPath.cpp:3712
static int LastMoveToIndex(const SkPath &path)
Definition SkPathPriv.h:348
static bool TooBigForMath(const SkPath &path)
Definition SkPathPriv.h:300
static bool IsSimpleRect(const SkPath &path, bool isSimpleFill, SkRect *rect, SkPathDirection *direction, unsigned *start)
Definition SkPath.cpp:3180
static int GenIDChangeListenersCount(const SkPath &)
Definition SkPath.cpp:3920
static void SetConvexity(const SkPath &path, SkPathConvexity c)
Definition SkPathPriv.h:413
static bool HasComputedBounds(const SkPath &path)
Definition SkPathPriv.h:223
static bool DrawArcIsConvex(SkScalar sweepAngle, bool useCenter, bool isFillNoPathEffect)
Definition SkPath.cpp:3276
static const uint8_t * VerbData(const SkPath &path)
Definition SkPathPriv.h:198
static SkPath MakePath(const SkPathVerbAnalysis &analysis, const SkPoint points[], const uint8_t verbs[], int verbCount, const SkScalar conics[], SkPathFillType fillType, bool isVolatile)
Definition SkPathPriv.h:425
static void ForceComputeConvexity(const SkPath &path)
Definition SkPathPriv.h:416
static bool IsOval(const SkPath &path, SkRect *rect, SkPathDirection *dir, unsigned *start)
Definition SkPathPriv.h:245
static SkPathFirstDirection AsFirstDirection(SkPathDirection dir)
Definition SkPathPriv.h:42
static bool IsAxisAligned(const SkPath &path)
Definition SkPath.cpp:3924
static int PtsInIter(unsigned verb)
Definition SkPathPriv.h:305
static bool TestingOnly_unique(const SkPath &path)
Definition SkPathPriv.h:218
static void ReverseAddPath(SkPathBuilder *builder, const SkPath &reverseMe)
Definition SkPathPriv.h:421
static SkPathFirstDirection ComputeFirstDirection(const SkPath &)
Definition SkPath.cpp:2563
static int LeadingMoveToCount(const SkPath &path)
Definition SkPathPriv.h:94
static constexpr SkScalar kW0PlaneDistance
Definition SkPathPriv.h:40
static void AddGenIDChangeListener(const SkPath &path, sk_sp< SkIDChangeListener > listener)
Definition SkPathPriv.h:105
static SkPathConvexity GetConvexityOrUnknown(const SkPath &path)
Definition SkPathPriv.h:410
static void ShrinkToFit(SkPath *path)
Definition SkPathPriv.h:130
static bool PerspectiveClip(const SkPath &src, const SkMatrix &, SkPath *result)
Definition SkPath.cpp:3894
static void UpdatePathPoint(SkPath *path, int index, const SkPoint &pt)
Definition SkPathPriv.h:400
static bool IsRectContour(const SkPath &, bool allowPartial, int *currVerb, const SkPoint **ptsPtr, bool *isClosed, SkPathDirection *direction, SkRect *rect)
Definition SkPath.cpp:3571
static const SkScalar * ConicWeightData(const SkPath &path)
Definition SkPathPriv.h:213
static const SkPoint * PointData(const SkPath &path)
Definition SkPathPriv.h:203
static bool TooBigForMath(const SkRect &bounds)
Definition SkPathPriv.h:290
static bool AllPointsEq(const SkPoint pts[], int count)
Definition SkPathPriv.h:339
static int ConicWeightCnt(const SkPath &path)
Definition SkPathPriv.h:208
static void CreateDrawArcPath(SkPath *path, const SkRect &oval, SkScalar startAngle, SkScalar sweepAngle, bool useCenter, bool isFillNoPathEffect)
Definition SkPath.cpp:3290
SkPath::RangeIter RangeIter
Definition SkPathPriv.h:164
static SkPathFirstDirection OppositeFirstDirection(SkPathFirstDirection dir)
Definition SkPathPriv.h:51
static SkPathFillType ConvertToNonInverseFillType(SkPathFillType fill)
Definition SkPathPriv.h:379
SkPoint * writablePoints()
Definition SkPathRef.h:104
const uint8_t * verbsEnd() const
Definition SkPathRef.h:323
const uint8_t * verbsBegin() const
Definition SkPathRef.h:318
@ kClose_Verb
Definition SkPath.h:1463
@ kMove_Verb
Definition SkPath.h:1458
@ kConic_Verb
Definition SkPath.h:1461
@ kCubic_Verb
Definition SkPath.h:1462
@ kQuad_Verb
Definition SkPath.h:1460
@ kLine_Verb
Definition SkPath.h:1459
float SkScalar
Definition extension.cpp:12
static bool b
GAsyncResult * result
static float max(float r, float g, float b)
Definition hsl.cpp:49
const SkPoint * fPts
Definition SkPathPriv.h:477
Iterate(const uint8_t *verbsBegin, const uint8_t *verbsEnd, const SkPoint *points, const SkScalar *weights)
Definition SkPathPriv.h:182
SkPath::RangeIter end()
Definition SkPathPriv.h:187
Iterate(const SkPath &path)
Definition SkPathPriv.h:175
SkPath::RangeIter begin()
Definition SkPathPriv.h:186
bool operator!=(const Iter &b)
Definition SkPathPriv.h:146
SkPath::Verb operator*()
Definition SkPathPriv.h:147
const uint8_t * fVerb
Definition SkPathPriv.h:148
Verbs(const SkPath &path)
Definition SkPathPriv.h:143