Flutter Engine
The Flutter Engine
SkPathRef.h
Go to the documentation of this file.
1/*
2 * Copyright 2012 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 SkPathRef_DEFINED
9#define SkPathRef_DEFINED
10
11#include "include/core/SkArc.h"
13#include "include/core/SkRect.h"
22
23#include <atomic>
24#include <cstddef>
25#include <cstdint>
26#include <tuple>
27
28class SkMatrix;
29class SkRRect;
30
31// These are computed from a stream of verbs
33 bool valid;
35 unsigned segmentMask;
36};
37SkPathVerbAnalysis sk_path_analyze_verbs(const uint8_t verbs[], int count);
38
39
40/**
41 * Holds the path verbs and points. It is versioned by a generation ID. None of its public methods
42 * modify the contents. To modify or append to the verbs/points wrap the SkPathRef in an
43 * SkPathRef::Editor object. Installing the editor resets the generation ID. It also performs
44 * copy-on-write if the SkPathRef is shared by multiple SkPaths. The caller passes the Editor's
45 * constructor a pointer to a sk_sp<SkPathRef>, which may be updated to point to a new SkPathRef
46 * after the editor's constructor returns.
47 *
48 * The points and verbs are stored in a single allocation. The points are at the begining of the
49 * allocation while the verbs are stored at end of the allocation, in reverse order. Thus the points
50 * and verbs both grow into the middle of the allocation until the meet. To access verb i in the
51 * verb array use ref.verbs()[~i] (because verbs() returns a pointer just beyond the first
52 * logical verb or the last verb in memory).
53 */
54
55class SK_API SkPathRef final : public SkNVRefCnt<SkPathRef> {
56public:
57 // See https://bugs.chromium.org/p/skia/issues/detail?id=13817 for how these sizes were
58 // determined.
62
63 enum class PathType : uint8_t {
65 kOval,
66 kOpenOval, // An unclosed oval, as is generated by canvas2d ellipse or arc
67 kRRect,
68 kArc,
69 };
70
72 SkSpan<const SkScalar> weights, unsigned segmentMask)
73 : fPoints(points)
74 , fVerbs(verbs)
75 , fConicWeights(weights)
76 {
77 fBoundsIsDirty = true; // this also invalidates fIsFinite
78 fGenerationID = 0; // recompute
79 fSegmentMask = segmentMask;
80 fType = PathType::kGeneral;
81 // The next two values don't matter unless fType is kOval or kRRect
82 fRRectOrOvalIsCCW = false;
83 fRRectOrOvalStartIdx = 0xAC;
84 fArcOval.setEmpty();
85 fArcStartAngle = fArcSweepAngle = 0.0f;
86 fArcType = SkArc::Type::kArc;
87 SkDEBUGCODE(fEditorsAttached.store(0);)
88
89 this->computeBounds(); // do this now, before we worry about multiple owners/threads
90 SkDEBUGCODE(this->validate();)
91 }
92
93 class Editor {
94 public:
95 Editor(sk_sp<SkPathRef>* pathRef,
96 int incReserveVerbs = 0,
97 int incReservePoints = 0,
98 int incReserveConics = 0);
99
100 ~Editor() { SkDEBUGCODE(fPathRef->fEditorsAttached--;) }
101
102 /**
103 * Returns the array of points.
104 */
105 SkPoint* writablePoints() { return fPathRef->getWritablePoints(); }
106 const SkPoint* points() const { return fPathRef->points(); }
107
108 /**
109 * Gets the ith point. Shortcut for this->points() + i
110 */
111 SkPoint* atPoint(int i) { return fPathRef->getWritablePoints() + i; }
112 const SkPoint* atPoint(int i) const { return &fPathRef->fPoints[i]; }
113
114 /**
115 * Adds the verb and allocates space for the number of points indicated by the verb. The
116 * return value is a pointer to where the points for the verb should be written.
117 * 'weight' is only used if 'verb' is kConic_Verb
118 */
119 SkPoint* growForVerb(int /*SkPath::Verb*/ verb, SkScalar weight = 0) {
120 SkDEBUGCODE(fPathRef->validate();)
121 return fPathRef->growForVerb(verb, weight);
122 }
123
124 /**
125 * Allocates space for multiple instances of a particular verb and the
126 * requisite points & weights.
127 * The return pointer points at the first new point (indexed normally [<i>]).
128 * If 'verb' is kConic_Verb, 'weights' will return a pointer to the
129 * space for the conic weights (indexed normally).
130 */
131 SkPoint* growForRepeatedVerb(int /*SkPath::Verb*/ verb,
132 int numVbs,
133 SkScalar** weights = nullptr) {
134 return fPathRef->growForRepeatedVerb(verb, numVbs, weights);
135 }
136
137 /**
138 * Concatenates all verbs from 'path' onto the pathRef's verbs array. Increases the point
139 * count by the number of points in 'path', and the conic weight count by the number of
140 * conics in 'path'.
141 *
142 * Returns pointers to the uninitialized points and conic weights data.
143 */
144 std::tuple<SkPoint*, SkScalar*> growForVerbsInPath(const SkPathRef& path) {
145 return fPathRef->growForVerbsInPath(path);
146 }
147
148 /**
149 * Resets the path ref to a new verb and point count. The new verbs and points are
150 * uninitialized.
151 */
152 void resetToSize(int newVerbCnt, int newPointCnt, int newConicCount) {
153 fPathRef->resetToSize(newVerbCnt, newPointCnt, newConicCount);
154 }
155
156 /**
157 * Gets the path ref that is wrapped in the Editor.
158 */
159 SkPathRef* pathRef() { return fPathRef; }
160
161 void setIsOval(bool isCCW, unsigned start, bool isClosed) {
162 fPathRef->setIsOval(isCCW, start, isClosed);
163 }
164
165 void setIsRRect(bool isCCW, unsigned start) {
166 fPathRef->setIsRRect(isCCW, start);
167 }
168
169 void setIsArc(const SkArc& arc) {
170 fPathRef->setIsArc(arc);
171 }
172
173 void setBounds(const SkRect& rect) { fPathRef->setBounds(rect); }
174
175 private:
176 SkPathRef* fPathRef;
177 };
178
179 class SK_API Iter {
180 public:
181 Iter();
182 Iter(const SkPathRef&);
183
184 void setPathRef(const SkPathRef&);
185
186 /** Return the next verb in this iteration of the path. When all
187 segments have been visited, return kDone_Verb.
188
189 If any point in the path is non-finite, return kDone_Verb immediately.
190
191 @param pts The points representing the current verb and/or segment
192 This must not be NULL.
193 @return The verb for the current segment
194 */
195 uint8_t next(SkPoint pts[4]);
196 uint8_t peek() const;
197
198 SkScalar conicWeight() const { return *fConicWeights; }
199
200 private:
201 const SkPoint* fPts;
202 const uint8_t* fVerbs;
203 const uint8_t* fVerbStop;
204 const SkScalar* fConicWeights;
205 };
206
207public:
208 /**
209 * Gets a path ref with no verbs or points.
210 */
211 static SkPathRef* CreateEmpty();
212
213 /**
214 * Returns true if all of the points in this path are finite, meaning there
215 * are no infinities and no NaNs.
216 */
217 bool isFinite() const {
218 if (fBoundsIsDirty) {
219 this->computeBounds();
220 }
221 return SkToBool(fIsFinite);
222 }
223
224 /**
225 * Returns a mask, where each bit corresponding to a SegmentMask is
226 * set if the path contains 1 or more segments of that type.
227 * Returns 0 for an empty path (no segments).
228 */
229 uint32_t getSegmentMasks() const { return fSegmentMask; }
230
231 /** Returns true if the path is an oval.
232 *
233 * @param rect returns the bounding rect of this oval. It's a circle
234 * if the height and width are the same.
235 * @param isCCW is the oval CCW (or CW if false).
236 * @param start indicates where the contour starts on the oval (see
237 * SkPath::addOval for intepretation of the index).
238 *
239 * @return true if this path is an oval.
240 * Tracking whether a path is an oval is considered an
241 * optimization for performance and so some paths that are in
242 * fact ovals can report false.
243 */
244 bool isOval(SkRect* rect, bool* isCCW, unsigned* start) const {
245 if (fType == PathType::kOval) {
246 if (rect) {
247 *rect = this->getBounds();
248 }
249 if (isCCW) {
250 *isCCW = SkToBool(fRRectOrOvalIsCCW);
251 }
252 if (start) {
253 *start = fRRectOrOvalStartIdx;
254 }
255 }
256
257 return fType == PathType::kOval;
258 }
259
260 bool isRRect(SkRRect* rrect, bool* isCCW, unsigned* start) const;
261
262 bool isArc(SkArc* arc) const {
263 if (fType == PathType::kArc) {
264 if (arc) {
265 *arc = SkArc::Make(fArcOval, fArcStartAngle, fArcSweepAngle, fArcType);
266 }
267 }
268
269 return fType == PathType::kArc;
270 }
271
272 bool hasComputedBounds() const {
273 return !fBoundsIsDirty;
274 }
275
276 /** Returns the bounds of the path's points. If the path contains 0 or 1
277 points, the bounds is set to (0,0,0,0), and isEmpty() will return true.
278 Note: this bounds may be larger than the actual shape, since curves
279 do not extend as far as their control points.
280 */
281 const SkRect& getBounds() const {
282 if (fBoundsIsDirty) {
283 this->computeBounds();
284 }
285 return fBounds;
286 }
287
288 SkRRect getRRect() const;
289
290 /**
291 * Transforms a path ref by a matrix, allocating a new one only if necessary.
292 */
293 static void CreateTransformedCopy(sk_sp<SkPathRef>* dst,
294 const SkPathRef& src,
295 const SkMatrix& matrix);
296
297 // static SkPathRef* CreateFromBuffer(SkRBuffer* buffer);
298
299 /**
300 * Rollsback a path ref to zero verbs and points with the assumption that the path ref will be
301 * repopulated with approximately the same number of verbs and points. A new path ref is created
302 * only if necessary.
303 */
304 static void Rewind(sk_sp<SkPathRef>* pathRef);
305
306 ~SkPathRef();
307 int countPoints() const { return fPoints.size(); }
308 int countVerbs() const { return fVerbs.size(); }
309 int countWeights() const { return fConicWeights.size(); }
310
311 size_t approximateBytesUsed() const;
312
313 /**
314 * Returns a pointer one beyond the first logical verb (last verb in memory order).
315 */
316 const uint8_t* verbsBegin() const { return fVerbs.begin(); }
317
318 /**
319 * Returns a const pointer to the first verb in memory (which is the last logical verb).
320 */
321 const uint8_t* verbsEnd() const { return fVerbs.end(); }
322
323 /**
324 * Returns a const pointer to the first point.
325 */
326 const SkPoint* points() const { return fPoints.begin(); }
327
328 /**
329 * Shortcut for this->points() + this->countPoints()
330 */
331 const SkPoint* pointsEnd() const { return this->points() + this->countPoints(); }
332
333 const SkScalar* conicWeights() const { return fConicWeights.begin(); }
334 const SkScalar* conicWeightsEnd() const { return fConicWeights.end(); }
335
336 /**
337 * Convenience methods for getting to a verb or point by index.
338 */
339 uint8_t atVerb(int index) const { return fVerbs[index]; }
340 const SkPoint& atPoint(int index) const { return fPoints[index]; }
341
342 bool operator== (const SkPathRef& ref) const;
343
344 void interpolate(const SkPathRef& ending, SkScalar weight, SkPathRef* out) const;
345
346 /**
347 * Gets an ID that uniquely identifies the contents of the path ref. If two path refs have the
348 * same ID then they have the same verbs and points. However, two path refs may have the same
349 * contents but different genIDs.
350 * skbug.com/1762 for background on why fillType is necessary (for now).
351 */
352 uint32_t genID(uint8_t fillType) const;
353
354 void addGenIDChangeListener(sk_sp<SkIDChangeListener>); // Threadsafe.
355 int genIDChangeListenerCount(); // Threadsafe
356
357 bool dataMatchesVerbs() const;
358 bool isValid() const;
359 SkDEBUGCODE(void validate() const { SkASSERT(this->isValid()); } )
360
361 /**
362 * Resets this SkPathRef to a clean state.
363 */
364 void reset();
365
367 return fGenerationID == kEmptyGenID;
368 }
369
370private:
372 kLegacyRRectOrOvalStartIdx_SerializationShift = 28, // requires 3 bits, ignored.
373 kLegacyRRectOrOvalIsCCW_SerializationShift = 27, // requires 1 bit, ignored.
374 kLegacyIsRRect_SerializationShift = 26, // requires 1 bit, ignored.
375 kIsFinite_SerializationShift = 25, // requires 1 bit
376 kLegacyIsOval_SerializationShift = 24, // requires 1 bit, ignored.
377 kSegmentMask_SerializationShift = 0 // requires 4 bits (deprecated)
378 };
379
380 SkPathRef(int numVerbs = 0, int numPoints = 0, int numConics = 0) {
381 fBoundsIsDirty = true; // this also invalidates fIsFinite
382 fGenerationID = kEmptyGenID;
383 fSegmentMask = 0;
384 fType = PathType::kGeneral;
385 // The next two values don't matter unless fType is kOval or kRRect
386 fRRectOrOvalIsCCW = false;
387 fRRectOrOvalStartIdx = 0xAC;
388 fArcOval.setEmpty();
389 fArcStartAngle = fArcSweepAngle = 0.0f;
390 fArcType = SkArc::Type::kArc;
391 if (numPoints > 0) {
392 fPoints.reserve_exact(numPoints);
393 }
394 if (numVerbs > 0) {
395 fVerbs.reserve_exact(numVerbs);
396 }
397 if (numConics > 0) {
398 fConicWeights.reserve_exact(numConics);
399 }
400 SkDEBUGCODE(fEditorsAttached.store(0);)
401 SkDEBUGCODE(this->validate();)
402 }
403
404 void copy(const SkPathRef& ref, int additionalReserveVerbs, int additionalReservePoints, int additionalReserveConics);
405
406 // Return true if the computed bounds are finite.
407 static bool ComputePtBounds(SkRect* bounds, const SkPathRef& ref) {
408 return bounds->setBoundsCheck(ref.points(), ref.countPoints());
409 }
410
411 // called, if dirty, by getBounds()
412 void computeBounds() const {
413 SkDEBUGCODE(this->validate();)
414 // TODO: remove fBoundsIsDirty and fIsFinite,
415 // using an inverted rect instead of fBoundsIsDirty and always recalculating fIsFinite.
416 SkASSERT(fBoundsIsDirty);
417
418 fIsFinite = ComputePtBounds(&fBounds, *this);
419 fBoundsIsDirty = false;
420 }
421
422 void setBounds(const SkRect& rect) {
423 SkASSERT(rect.fLeft <= rect.fRight && rect.fTop <= rect.fBottom);
424 fBounds = rect;
425 fBoundsIsDirty = false;
426 fIsFinite = fBounds.isFinite();
427 }
428
429 /** Makes additional room but does not change the counts or change the genID */
430 void incReserve(int additionalVerbs, int additionalPoints, int additionalConics) {
431 SkDEBUGCODE(this->validate();)
432 // Use reserve() so that if there is not enough space, the array will grow with some
433 // additional space. This ensures repeated calls to grow won't always allocate.
434 if (additionalPoints > 0) {
435 fPoints.reserve(fPoints.size() + additionalPoints);
436 }
437 if (additionalVerbs > 0) {
438 fVerbs.reserve(fVerbs.size() + additionalVerbs);
439 }
440 if (additionalConics > 0) {
441 fConicWeights.reserve(fConicWeights.size() + additionalConics);
442 }
443 SkDEBUGCODE(this->validate();)
444 }
445
446 /**
447 * Resets all state except that of the verbs, points, and conic-weights.
448 * Intended to be called from other functions that reset state.
449 */
450 void commonReset() {
451 SkDEBUGCODE(this->validate();)
452 this->callGenIDChangeListeners();
453 fBoundsIsDirty = true; // this also invalidates fIsFinite
454 fGenerationID = 0;
455
456 fSegmentMask = 0;
457 fType = PathType::kGeneral;
458 }
459
460 /** Resets the path ref with verbCount verbs and pointCount points, all uninitialized. Also
461 * allocates space for reserveVerb additional verbs and reservePoints additional points.*/
462 void resetToSize(int verbCount, int pointCount, int conicCount,
463 int reserveVerbs = 0, int reservePoints = 0,
464 int reserveConics = 0) {
465 this->commonReset();
466 // Use reserve_exact() so the arrays are sized to exactly fit the data.
467 fPoints.reserve_exact(pointCount + reservePoints);
468 fPoints.resize_back(pointCount);
469
470 fVerbs.reserve_exact(verbCount + reserveVerbs);
471 fVerbs.resize_back(verbCount);
472
473 fConicWeights.reserve_exact(conicCount + reserveConics);
474 fConicWeights.resize_back(conicCount);
475 SkDEBUGCODE(this->validate();)
476 }
477
478 /**
479 * Increases the verb count by numVbs and point count by the required amount.
480 * The new points are uninitialized. All the new verbs are set to the specified
481 * verb. If 'verb' is kConic_Verb, 'weights' will return a pointer to the
482 * uninitialized conic weights.
483 */
484 SkPoint* growForRepeatedVerb(int /*SkPath::Verb*/ verb, int numVbs, SkScalar** weights);
485
486 /**
487 * Increases the verb count 1, records the new verb, and creates room for the requisite number
488 * of additional points. A pointer to the first point is returned. Any new points are
489 * uninitialized.
490 */
491 SkPoint* growForVerb(int /*SkPath::Verb*/ verb, SkScalar weight);
492
493 /**
494 * Concatenates all verbs from 'path' onto our own verbs array. Increases the point count by the
495 * number of points in 'path', and the conic weight count by the number of conics in 'path'.
496 *
497 * Returns pointers to the uninitialized points and conic weights data.
498 */
499 std::tuple<SkPoint*, SkScalar*> growForVerbsInPath(const SkPathRef& path);
500
501 /**
502 * Private, non-const-ptr version of the public function verbsMemBegin().
503 */
504 uint8_t* verbsBeginWritable() { return fVerbs.begin(); }
505
506 /**
507 * Called the first time someone calls CreateEmpty to actually create the singleton.
508 */
510
511 void setIsOval(bool isCCW, unsigned start, bool isClosed) {
512 fType = isClosed ? PathType::kOval : PathType::kOpenOval;
513 fRRectOrOvalIsCCW = isCCW;
514 fRRectOrOvalStartIdx = SkToU8(start);
515 }
516
517 void setIsRRect(bool isCCW, unsigned start) {
518 fType = PathType::kRRect;
519 fRRectOrOvalIsCCW = isCCW;
520 fRRectOrOvalStartIdx = SkToU8(start);
521 }
522
523 void setIsArc(const SkArc& arc) {
524 fType = PathType::kArc;
525 fArcOval = arc.fOval;
526 fArcStartAngle = arc.fStartAngle;
527 fArcSweepAngle = arc.fSweepAngle;
528 fArcType = arc.fType;
529 }
530
531 // called only by the editor. Note that this is not a const function.
532 SkPoint* getWritablePoints() {
533 SkDEBUGCODE(this->validate();)
534 fType = PathType::kGeneral;
535 return fPoints.begin();
536 }
537
538 const SkPoint* getPoints() const {
539 SkDEBUGCODE(this->validate();)
540 return fPoints.begin();
541 }
542
543 void callGenIDChangeListeners();
544
545 mutable SkRect fBounds;
546
547 enum {
548 kEmptyGenID = 1, // GenID reserved for path ref with zero points and zero verbs.
549 };
550 mutable uint32_t fGenerationID;
551 SkIDChangeListener::List fGenIDChangeListeners;
552
553 PointsArray fPoints;
554 VerbsArray fVerbs;
555 ConicWeightsArray fConicWeights;
556
557 SkDEBUGCODE(std::atomic<int> fEditorsAttached;) // assert only one editor in use at any time.
558
559 mutable uint8_t fBoundsIsDirty;
560 mutable bool fIsFinite; // only meaningful if bounds are valid
561
562 PathType fType;
563 // Both the circle and rrect special cases have a notion of direction and starting point
564 // The next two variables store that information for either.
565 bool fRRectOrOvalIsCCW;
566 uint8_t fRRectOrOvalStartIdx;
567 uint8_t fSegmentMask;
568 // If the path is an arc, these four variables store that information.
569 // We should just store an SkArc, but alignment would cost us 8 more bytes.
570 SkArc::Type fArcType;
571 SkRect fArcOval;
572 SkScalar fArcStartAngle;
573 SkScalar fArcSweepAngle;
574
576 friend class ForceIsRRect_Private; // unit test isRRect
577 friend class SkPath;
578 friend class SkPathBuilder;
579 friend class SkPathPriv;
580};
581
582#endif
SkPoint fPts[2]
m reset()
int count
Definition: FontMgrTest.cpp:50
static const int points[]
const SkRect fBounds
static float next(float f)
#define SK_API
Definition: SkAPI.h:35
#define SkASSERT(cond)
Definition: SkAssert.h:116
static double interpolate(double A, double B, double t)
SkPathVerbAnalysis sk_path_analyze_verbs(const uint8_t verbs[], int count)
Definition: SkPath.cpp:3515
@ kGeneral
@ kRRect
SerializationOffsets
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
static constexpr bool SkToBool(const T &x)
Definition: SkTo.h:35
constexpr uint8_t SkToU8(S x)
Definition: SkTo.h:22
void resetToSize(int newVerbCnt, int newPointCnt, int newConicCount)
Definition: SkPathRef.h:152
void setIsOval(bool isCCW, unsigned start, bool isClosed)
Definition: SkPathRef.h:161
std::tuple< SkPoint *, SkScalar * > growForVerbsInPath(const SkPathRef &path)
Definition: SkPathRef.h:144
SkPoint * growForRepeatedVerb(int verb, int numVbs, SkScalar **weights=nullptr)
Definition: SkPathRef.h:131
SkPoint * atPoint(int i)
Definition: SkPathRef.h:111
const SkPoint * points() const
Definition: SkPathRef.h:106
SkPoint * growForVerb(int verb, SkScalar weight=0)
Definition: SkPathRef.h:119
void setIsRRect(bool isCCW, unsigned start)
Definition: SkPathRef.h:165
SkPathRef * pathRef()
Definition: SkPathRef.h:159
const SkPoint * atPoint(int i) const
Definition: SkPathRef.h:112
void setBounds(const SkRect &rect)
Definition: SkPathRef.h:173
SkPoint * writablePoints()
Definition: SkPathRef.h:105
void setIsArc(const SkArc &arc)
Definition: SkPathRef.h:169
SkScalar conicWeight() const
Definition: SkPathRef.h:198
SkDEBUGCODE(void validate() const { SkASSERT(this->isValid());}) void reset()
friend SkPathRef * sk_create_empty_pathref()
const SkPoint & atPoint(int index) const
Definition: SkPathRef.h:340
SkPathRef(SkSpan< const SkPoint > points, SkSpan< const uint8_t > verbs, SkSpan< const SkScalar > weights, unsigned segmentMask)
Definition: SkPathRef.h:71
const SkRect & getBounds() const
Definition: SkPathRef.h:281
bool isFinite() const
Definition: SkPathRef.h:217
bool isInitialEmptyPathRef() const
Definition: SkPathRef.h:366
int countWeights() const
Definition: SkPathRef.h:309
const uint8_t * verbsEnd() const
Definition: SkPathRef.h:321
const SkPoint * pointsEnd() const
Definition: SkPathRef.h:331
const SkScalar * conicWeightsEnd() const
Definition: SkPathRef.h:334
uint8_t atVerb(int index) const
Definition: SkPathRef.h:339
const SkPoint * points() const
Definition: SkPathRef.h:326
bool hasComputedBounds() const
Definition: SkPathRef.h:272
const SkScalar * conicWeights() const
Definition: SkPathRef.h:333
int countPoints() const
Definition: SkPathRef.h:307
const uint8_t * verbsBegin() const
Definition: SkPathRef.h:316
bool isArc(SkArc *arc) const
Definition: SkPathRef.h:262
int countVerbs() const
Definition: SkPathRef.h:308
bool isOval(SkRect *rect, bool *isCCW, unsigned *start) const
Definition: SkPathRef.h:244
uint32_t getSegmentMasks() const
Definition: SkPathRef.h:229
Definition: SkPath.h:59
float SkScalar
Definition: extension.cpp:12
unsigned useCenter Optional< SkMatrix > matrix
Definition: SkRecords.h:258
Optional< SkRect > bounds
Definition: SkRecords.h:189
SkRRect rrect
Definition: SkRecords.h:232
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
Definition: copy.py:1
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
bool operator==(C p1, const scoped_nsprotocol< C > &p2)
dst
Definition: cp.py:12
Definition: SkArc.h:15
Type fType
Definition: SkArc.h:62
SkScalar fSweepAngle
Definition: SkArc.h:60
SkScalar fStartAngle
Definition: SkArc.h:58
Type
Definition: SkArc.h:16
SkRect fOval
Definition: SkArc.h:55
static SkArc Make(const SkRect &oval, SkScalar startAngleDegrees, SkScalar sweepAngleDegrees, Type type)
Definition: SkArc.h:38
unsigned segmentMask
Definition: SkPathRef.h:35
bool isFinite() const
Definition: SkRect.h:711