OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2012 Google Inc. | 3 * Copyright 2012 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 #ifndef SkPathRef_DEFINED | 9 #ifndef SkPathRef_DEFINED |
10 #define SkPathRef_DEFINED | 10 #define SkPathRef_DEFINED |
11 | 11 |
12 #include "SkMatrix.h" | 12 #include "SkMatrix.h" |
13 #include "SkPoint.h" | 13 #include "SkPoint.h" |
| 14 #include "SkRRect.h" |
14 #include "SkRect.h" | 15 #include "SkRect.h" |
15 #include "SkRefCnt.h" | 16 #include "SkRefCnt.h" |
16 #include "SkTDArray.h" | 17 #include "SkTDArray.h" |
17 #include <stddef.h> // ptrdiff_t | 18 #include <stddef.h> // ptrdiff_t |
18 | 19 |
19 class SkRBuffer; | 20 class SkRBuffer; |
20 class SkWBuffer; | 21 class SkWBuffer; |
21 | 22 |
22 /** | 23 /** |
23 * Holds the path verbs and points. It is versioned by a generation ID. None of
its public methods | 24 * Holds the path verbs and points. It is versioned by a generation ID. None of
its public methods |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 fPathRef->resetToSize(newVerbCnt, newPointCnt, newConicCount); | 94 fPathRef->resetToSize(newVerbCnt, newPointCnt, newConicCount); |
94 } | 95 } |
95 | 96 |
96 /** | 97 /** |
97 * Gets the path ref that is wrapped in the Editor. | 98 * Gets the path ref that is wrapped in the Editor. |
98 */ | 99 */ |
99 SkPathRef* pathRef() { return fPathRef; } | 100 SkPathRef* pathRef() { return fPathRef; } |
100 | 101 |
101 void setIsOval(bool isOval) { fPathRef->setIsOval(isOval); } | 102 void setIsOval(bool isOval) { fPathRef->setIsOval(isOval); } |
102 | 103 |
| 104 void setIsRRect(bool isRRect) { fPathRef->setIsRRect(isRRect); } |
| 105 |
103 void setBounds(const SkRect& rect) { fPathRef->setBounds(rect); } | 106 void setBounds(const SkRect& rect) { fPathRef->setBounds(rect); } |
104 | 107 |
105 private: | 108 private: |
106 SkPathRef* fPathRef; | 109 SkPathRef* fPathRef; |
107 }; | 110 }; |
108 | 111 |
| 112 class SK_API Iter { |
| 113 public: |
| 114 Iter(); |
| 115 Iter(const SkPathRef&); |
| 116 |
| 117 void setPathRef(const SkPathRef&); |
| 118 |
| 119 /** Return the next verb in this iteration of the path. When all |
| 120 segments have been visited, return kDone_Verb. |
| 121 |
| 122 @param pts The points representing the current verb and/or segment |
| 123 This must not be NULL. |
| 124 @return The verb for the current segment |
| 125 */ |
| 126 uint8_t next(SkPoint pts[4]); |
| 127 |
| 128 SkScalar conicWeight() const { return *fConicWeights; } |
| 129 |
| 130 private: |
| 131 const SkPoint* fPts; |
| 132 const uint8_t* fVerbs; |
| 133 const uint8_t* fVerbStop; |
| 134 const SkScalar* fConicWeights; |
| 135 }; |
| 136 |
109 public: | 137 public: |
110 /** | 138 /** |
111 * Gets a path ref with no verbs or points. | 139 * Gets a path ref with no verbs or points. |
112 */ | 140 */ |
113 static SkPathRef* CreateEmpty(); | 141 static SkPathRef* CreateEmpty(); |
114 | 142 |
115 /** | 143 /** |
116 * Returns true if all of the points in this path are finite, meaning there | 144 * Returns true if all of the points in this path are finite, meaning there |
117 * are no infinities and no NaNs. | 145 * are no infinities and no NaNs. |
118 */ | 146 */ |
(...skipping 16 matching lines...) Expand all Loading... |
135 * @param rect returns the bounding rect of this oval. It's a circle | 163 * @param rect returns the bounding rect of this oval. It's a circle |
136 * if the height and width are the same. | 164 * if the height and width are the same. |
137 * | 165 * |
138 * @return true if this path is an oval. | 166 * @return true if this path is an oval. |
139 * Tracking whether a path is an oval is considered an | 167 * Tracking whether a path is an oval is considered an |
140 * optimization for performance and so some paths that are in | 168 * optimization for performance and so some paths that are in |
141 * fact ovals can report false. | 169 * fact ovals can report false. |
142 */ | 170 */ |
143 bool isOval(SkRect* rect) const { | 171 bool isOval(SkRect* rect) const { |
144 if (fIsOval && rect) { | 172 if (fIsOval && rect) { |
145 *rect = getBounds(); | 173 *rect = this->getBounds(); |
146 } | 174 } |
147 | 175 |
148 return SkToBool(fIsOval); | 176 return SkToBool(fIsOval); |
149 } | 177 } |
150 | 178 |
| 179 bool isRRect(SkRRect* rrect) const { |
| 180 if (fIsRRect && rrect) { |
| 181 *rrect = this->getRRect(); |
| 182 } |
| 183 return SkToBool(fIsRRect); |
| 184 } |
| 185 |
| 186 |
151 bool hasComputedBounds() const { | 187 bool hasComputedBounds() const { |
152 return !fBoundsIsDirty; | 188 return !fBoundsIsDirty; |
153 } | 189 } |
154 | 190 |
155 /** Returns the bounds of the path's points. If the path contains 0 or 1 | 191 /** Returns the bounds of the path's points. If the path contains 0 or 1 |
156 points, the bounds is set to (0,0,0,0), and isEmpty() will return true. | 192 points, the bounds is set to (0,0,0,0), and isEmpty() will return true. |
157 Note: this bounds may be larger than the actual shape, since curves | 193 Note: this bounds may be larger than the actual shape, since curves |
158 do not extend as far as their control points. | 194 do not extend as far as their control points. |
159 */ | 195 */ |
160 const SkRect& getBounds() const { | 196 const SkRect& getBounds() const { |
161 if (fBoundsIsDirty) { | 197 if (fBoundsIsDirty) { |
162 this->computeBounds(); | 198 this->computeBounds(); |
163 } | 199 } |
164 return fBounds; | 200 return fBounds; |
165 } | 201 } |
166 | 202 |
| 203 SkRRect getRRect() const; |
| 204 |
167 /** | 205 /** |
168 * Transforms a path ref by a matrix, allocating a new one only if necessary
. | 206 * Transforms a path ref by a matrix, allocating a new one only if necessary
. |
169 */ | 207 */ |
170 static void CreateTransformedCopy(SkAutoTUnref<SkPathRef>* dst, | 208 static void CreateTransformedCopy(SkAutoTUnref<SkPathRef>* dst, |
171 const SkPathRef& src, | 209 const SkPathRef& src, |
172 const SkMatrix& matrix); | 210 const SkMatrix& matrix); |
173 | 211 |
174 static SkPathRef* CreateFromBuffer(SkRBuffer* buffer); | 212 static SkPathRef* CreateFromBuffer(SkRBuffer* buffer); |
175 | 213 |
176 /** | 214 /** |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 virtual ~GenIDChangeListener() {} | 281 virtual ~GenIDChangeListener() {} |
244 virtual void onChange() = 0; | 282 virtual void onChange() = 0; |
245 }; | 283 }; |
246 | 284 |
247 void addGenIDChangeListener(GenIDChangeListener* listener); | 285 void addGenIDChangeListener(GenIDChangeListener* listener); |
248 | 286 |
249 SkDEBUGCODE(void validate() const;) | 287 SkDEBUGCODE(void validate() const;) |
250 | 288 |
251 private: | 289 private: |
252 enum SerializationOffsets { | 290 enum SerializationOffsets { |
| 291 kIsRRect_SerializationShift = 26, // requires 1 bit |
253 kIsFinite_SerializationShift = 25, // requires 1 bit | 292 kIsFinite_SerializationShift = 25, // requires 1 bit |
254 kIsOval_SerializationShift = 24, // requires 1 bit | 293 kIsOval_SerializationShift = 24, // requires 1 bit |
255 kSegmentMask_SerializationShift = 0 // requires 4 bits | 294 kSegmentMask_SerializationShift = 0 // requires 4 bits |
256 }; | 295 }; |
257 | 296 |
258 SkPathRef() { | 297 SkPathRef() { |
259 fBoundsIsDirty = true; // this also invalidates fIsFinite | 298 fBoundsIsDirty = true; // this also invalidates fIsFinite |
260 fPointCnt = 0; | 299 fPointCnt = 0; |
261 fVerbCnt = 0; | 300 fVerbCnt = 0; |
262 fVerbs = NULL; | 301 fVerbs = NULL; |
263 fPoints = NULL; | 302 fPoints = NULL; |
264 fFreeSpace = 0; | 303 fFreeSpace = 0; |
265 fGenerationID = kEmptyGenID; | 304 fGenerationID = kEmptyGenID; |
266 fSegmentMask = 0; | 305 fSegmentMask = 0; |
267 fIsOval = false; | 306 fIsOval = false; |
| 307 fIsRRect = false; |
268 SkDEBUGCODE(fEditorsAttached = 0;) | 308 SkDEBUGCODE(fEditorsAttached = 0;) |
269 SkDEBUGCODE(this->validate();) | 309 SkDEBUGCODE(this->validate();) |
270 } | 310 } |
271 | 311 |
272 void copy(const SkPathRef& ref, int additionalReserveVerbs, int additionalRe
servePoints); | 312 void copy(const SkPathRef& ref, int additionalReserveVerbs, int additionalRe
servePoints); |
273 | 313 |
274 // Return true if the computed bounds are finite. | 314 // Return true if the computed bounds are finite. |
275 static bool ComputePtBounds(SkRect* bounds, const SkPathRef& ref) { | 315 static bool ComputePtBounds(SkRect* bounds, const SkPathRef& ref) { |
276 return bounds->setBoundsCheck(ref.points(), ref.countPoints()); | 316 return bounds->setBoundsCheck(ref.points(), ref.countPoints()); |
277 } | 317 } |
(...skipping 27 matching lines...) Expand all Loading... |
305 /** Resets the path ref with verbCount verbs and pointCount points, all unin
itialized. Also | 345 /** Resets the path ref with verbCount verbs and pointCount points, all unin
itialized. Also |
306 * allocates space for reserveVerb additional verbs and reservePoints addit
ional points.*/ | 346 * allocates space for reserveVerb additional verbs and reservePoints addit
ional points.*/ |
307 void resetToSize(int verbCount, int pointCount, int conicCount, | 347 void resetToSize(int verbCount, int pointCount, int conicCount, |
308 int reserveVerbs = 0, int reservePoints = 0) { | 348 int reserveVerbs = 0, int reservePoints = 0) { |
309 SkDEBUGCODE(this->validate();) | 349 SkDEBUGCODE(this->validate();) |
310 fBoundsIsDirty = true; // this also invalidates fIsFinite | 350 fBoundsIsDirty = true; // this also invalidates fIsFinite |
311 fGenerationID = 0; | 351 fGenerationID = 0; |
312 | 352 |
313 fSegmentMask = 0; | 353 fSegmentMask = 0; |
314 fIsOval = false; | 354 fIsOval = false; |
| 355 fIsRRect = false; |
315 | 356 |
316 size_t newSize = sizeof(uint8_t) * verbCount + sizeof(SkPoint) * pointCo
unt; | 357 size_t newSize = sizeof(uint8_t) * verbCount + sizeof(SkPoint) * pointCo
unt; |
317 size_t newReserve = sizeof(uint8_t) * reserveVerbs + sizeof(SkPoint) * r
eservePoints; | 358 size_t newReserve = sizeof(uint8_t) * reserveVerbs + sizeof(SkPoint) * r
eservePoints; |
318 size_t minSize = newSize + newReserve; | 359 size_t minSize = newSize + newReserve; |
319 | 360 |
320 ptrdiff_t sizeDelta = this->currSize() - minSize; | 361 ptrdiff_t sizeDelta = this->currSize() - minSize; |
321 | 362 |
322 if (sizeDelta < 0 || static_cast<size_t>(sizeDelta) >= 3 * minSize) { | 363 if (sizeDelta < 0 || static_cast<size_t>(sizeDelta) >= 3 * minSize) { |
323 sk_free(fPoints); | 364 sk_free(fPoints); |
324 fPoints = NULL; | 365 fPoints = NULL; |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
404 return reinterpret_cast<intptr_t>(fVerbs) - reinterpret_cast<intptr_t>(f
Points); | 445 return reinterpret_cast<intptr_t>(fVerbs) - reinterpret_cast<intptr_t>(f
Points); |
405 } | 446 } |
406 | 447 |
407 /** | 448 /** |
408 * Called the first time someone calls CreateEmpty to actually create the si
ngleton. | 449 * Called the first time someone calls CreateEmpty to actually create the si
ngleton. |
409 */ | 450 */ |
410 friend SkPathRef* sk_create_empty_pathref(); | 451 friend SkPathRef* sk_create_empty_pathref(); |
411 | 452 |
412 void setIsOval(bool isOval) { fIsOval = isOval; } | 453 void setIsOval(bool isOval) { fIsOval = isOval; } |
413 | 454 |
| 455 void setIsRRect(bool isRRect) { fIsRRect = isRRect; } |
| 456 |
| 457 // called only by the editor. Note that this is not a const function. |
414 SkPoint* getPoints() { | 458 SkPoint* getPoints() { |
415 SkDEBUGCODE(this->validate();) | 459 SkDEBUGCODE(this->validate();) |
416 fIsOval = false; | 460 fIsOval = false; |
| 461 fIsRRect = false; |
417 return fPoints; | 462 return fPoints; |
418 } | 463 } |
419 | 464 |
| 465 const SkPoint* getPoints() const { |
| 466 SkDEBUGCODE(this->validate();) |
| 467 return fPoints; |
| 468 } |
| 469 |
420 void callGenIDChangeListeners(); | 470 void callGenIDChangeListeners(); |
421 | 471 |
422 enum { | 472 enum { |
423 kMinSize = 256, | 473 kMinSize = 256, |
424 }; | 474 }; |
425 | 475 |
426 mutable SkRect fBounds; | 476 mutable SkRect fBounds; |
427 mutable uint8_t fBoundsIsDirty; | |
428 mutable SkBool8 fIsFinite; // only meaningful if bounds are valid | |
429 | |
430 SkBool8 fIsOval; | |
431 uint8_t fSegmentMask; | |
432 | 477 |
433 SkPoint* fPoints; // points to begining of the allocation | 478 SkPoint* fPoints; // points to begining of the allocation |
434 uint8_t* fVerbs; // points just past the end of the allocation (v
erbs grow backwards) | 479 uint8_t* fVerbs; // points just past the end of the allocation (v
erbs grow backwards) |
435 int fVerbCnt; | 480 int fVerbCnt; |
436 int fPointCnt; | 481 int fPointCnt; |
437 size_t fFreeSpace; // redundant but saves computation | 482 size_t fFreeSpace; // redundant but saves computation |
438 SkTDArray<SkScalar> fConicWeights; | 483 SkTDArray<SkScalar> fConicWeights; |
439 | 484 |
440 enum { | 485 enum { |
441 kEmptyGenID = 1, // GenID reserved for path ref with zero points and zer
o verbs. | 486 kEmptyGenID = 1, // GenID reserved for path ref with zero points and zer
o verbs. |
442 }; | 487 }; |
443 mutable uint32_t fGenerationID; | 488 mutable uint32_t fGenerationID; |
444 SkDEBUGCODE(int32_t fEditorsAttached;) // assert that only one editor in use
at any time. | 489 SkDEBUGCODE(int32_t fEditorsAttached;) // assert that only one editor in use
at any time. |
445 | 490 |
446 SkTDArray<GenIDChangeListener*> fGenIDChangeListeners; // pointers are owne
d | 491 SkTDArray<GenIDChangeListener*> fGenIDChangeListeners; // pointers are owne
d |
447 | 492 |
| 493 mutable uint8_t fBoundsIsDirty; |
| 494 mutable SkBool8 fIsFinite; // only meaningful if bounds are valid |
| 495 |
| 496 SkBool8 fIsOval; |
| 497 SkBool8 fIsRRect; |
| 498 uint8_t fSegmentMask; |
| 499 |
448 friend class PathRefTest_Private; | 500 friend class PathRefTest_Private; |
| 501 friend class ForceIsRRect_Private; // unit test isRRect |
449 typedef SkRefCnt INHERITED; | 502 typedef SkRefCnt INHERITED; |
450 }; | 503 }; |
451 | 504 |
452 #endif | 505 #endif |
OLD | NEW |