Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Side by Side Diff: src/core/SkPath.cpp

Issue 24350006: Move bound and isFinite into pathref (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: yet more cleanup Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2006 The Android Open Source Project 3 * Copyright 2006 The Android Open Source Project
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 9
10 #include "SkBuffer.h" 10 #include "SkBuffer.h"
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 private: 70 private:
71 SkPath* fPath; 71 SkPath* fPath;
72 SkPath::Direction fSaved; 72 SkPath::Direction fSaved;
73 }; 73 };
74 74
75 /* This guy's constructor/destructor bracket a path editing operation. It is 75 /* This guy's constructor/destructor bracket a path editing operation. It is
76 used when we know the bounds of the amount we are going to add to the path 76 used when we know the bounds of the amount we are going to add to the path
77 (usually a new contour, but not required). 77 (usually a new contour, but not required).
78 78
79 It captures some state about the path up front (i.e. if it already has a 79 It captures some state about the path up front (i.e. if it already has a
80 cached bounds), and the if it can, it updates the cache bounds explicitly, 80 cached bounds), and then if it can, it updates the cache bounds explicitly,
81 avoiding the need to revisit all of the points in getBounds(). 81 avoiding the need to revisit all of the points in getBounds().
82 82
83 It also notes if the path was originally degenerate, and if so, sets 83 It also notes if the path was originally degenerate, and if so, sets
84 isConvex to true. Thus it can only be used if the contour being added is 84 isConvex to true. Thus it can only be used if the contour being added is
85 convex. 85 convex (which is always true since we only allow the addition of rects).
86 */ 86 */
87 class SkAutoPathBoundsUpdate { 87 class SkAutoPathBoundsUpdate {
88 public: 88 public:
89 SkAutoPathBoundsUpdate(SkPath* path, const SkRect& r) : fRect(r) { 89 SkAutoPathBoundsUpdate(SkPath* path, const SkRect& r) : fRect(r) {
90 this->init(path); 90 this->init(path);
91 } 91 }
92 92
93 SkAutoPathBoundsUpdate(SkPath* path, SkScalar left, SkScalar top, 93 SkAutoPathBoundsUpdate(SkPath* path, SkScalar left, SkScalar top,
94 SkScalar right, SkScalar bottom) { 94 SkScalar right, SkScalar bottom) {
95 fRect.set(left, top, right, bottom); 95 fRect.set(left, top, right, bottom);
96 this->init(path); 96 this->init(path);
97 } 97 }
98 98
99 ~SkAutoPathBoundsUpdate() { 99 ~SkAutoPathBoundsUpdate() {
100 fPath->setIsConvex(fDegenerate); 100 fPath->setIsConvex(fDegenerate);
101 if (fEmpty) { 101 if (fEmpty || fHasValidBounds) {
102 fPath->fBounds = fRect; 102 fPath->setBounds(fRect);
103 fPath->fBoundsIsDirty = false;
104 fPath->fIsFinite = fPath->fBounds.isFinite();
105 } else if (!fDirty) {
106 joinNoEmptyChecks(&fPath->fBounds, fRect);
107 fPath->fBoundsIsDirty = false;
108 fPath->fIsFinite = fPath->fBounds.isFinite();
109 } 103 }
110 } 104 }
111 105
112 private: 106 private:
113 SkPath* fPath; 107 SkPath* fPath;
114 SkRect fRect; 108 SkRect fRect;
115 bool fDirty; 109 bool fHasValidBounds;
116 bool fDegenerate; 110 bool fDegenerate;
117 bool fEmpty; 111 bool fEmpty;
118 112
119 // returns true if we should proceed
120 void init(SkPath* path) { 113 void init(SkPath* path) {
114 // Cannot use fRect for our bounds unless we know it is sorted
115 fRect.sort();
121 fPath = path; 116 fPath = path;
122 // Mark the path's bounds as dirty if (1) they are, or (2) the path 117 // Mark the path's bounds as dirty if (1) they are, or (2) the path
123 // is non-finite, and therefore its bounds are not meaningful 118 // is non-finite, and therefore its bounds are not meaningful
124 fDirty = SkToBool(path->fBoundsIsDirty) || !path->fIsFinite; 119 fHasValidBounds = path->hasComputedBounds() && path->isFinite();
120 fEmpty = path->isEmpty();
121 if (fHasValidBounds && !fEmpty) {
122 joinNoEmptyChecks(&fRect, fPath->getBounds());
123 }
125 fDegenerate = is_degenerate(*path); 124 fDegenerate = is_degenerate(*path);
126 fEmpty = path->isEmpty();
127 // Cannot use fRect for our bounds unless we know it is sorted
128 fRect.sort();
129 } 125 }
130 }; 126 };
131 127
132 // Return true if the computed bounds are finite.
133 static bool compute_pt_bounds(SkRect* bounds, const SkPathRef& ref) {
134 int count = ref.countPoints();
135 if (count <= 1) { // we ignore just 1 point (moveto)
136 bounds->setEmpty();
137 return count ? ref.points()->isFinite() : true;
138 } else {
139 return bounds->setBoundsCheck(ref.points(), count);
140 }
141 }
142
143 //////////////////////////////////////////////////////////////////////////// 128 ////////////////////////////////////////////////////////////////////////////
144 129
145 /* 130 /*
146 Stores the verbs and points as they are given to us, with exceptions: 131 Stores the verbs and points as they are given to us, with exceptions:
147 - we only record "Close" if it was immediately preceeded by Move | Line | Qu ad | Cubic 132 - we only record "Close" if it was immediately preceeded by Move | Line | Qu ad | Cubic
148 - we insert a Move(0,0) if Line | Quad | Cubic is our first command 133 - we insert a Move(0,0) if Line | Quad | Cubic is our first command
149 134
150 The iterator does more cleanup, especially if forceClose == true 135 The iterator does more cleanup, especially if forceClose == true
151 1. If we encounter degenerate segments, remove them 136 1. If we encounter degenerate segments, remove them
152 2. if we encounter Close, return a cons'd up Line() first (if the curr-pt != start-pt) 137 2. if we encounter Close, return a cons'd up Line() first (if the curr-pt != start-pt)
(...skipping 13 matching lines...) Expand all
166 #endif 151 #endif
167 { 152 {
168 this->resetFields(); 153 this->resetFields();
169 } 154 }
170 155
171 void SkPath::resetFields() { 156 void SkPath::resetFields() {
172 //fPathRef is assumed to have been emptied by the caller. 157 //fPathRef is assumed to have been emptied by the caller.
173 fLastMoveToIndex = INITIAL_LASTMOVETOINDEX_VALUE; 158 fLastMoveToIndex = INITIAL_LASTMOVETOINDEX_VALUE;
174 fFillType = kWinding_FillType; 159 fFillType = kWinding_FillType;
175 fSegmentMask = 0; 160 fSegmentMask = 0;
176 fBoundsIsDirty = true;
177 fConvexity = kUnknown_Convexity; 161 fConvexity = kUnknown_Convexity;
178 fDirection = kUnknown_Direction; 162 fDirection = kUnknown_Direction;
179 fIsFinite = false;
180 fIsOval = false; 163 fIsOval = false;
181 #ifdef SK_BUILD_FOR_ANDROID 164 #ifdef SK_BUILD_FOR_ANDROID
182 GEN_ID_INC; 165 GEN_ID_INC;
183 // We don't touch fSourcePath. It's used to track texture garbage collectio n, so we don't 166 // We don't touch fSourcePath. It's used to track texture garbage collectio n, so we don't
184 // want to muck with it if it's been set to something non-NULL. 167 // want to muck with it if it's been set to something non-NULL.
185 #endif 168 #endif
186 } 169 }
187 170
188 SkPath::SkPath(const SkPath& that) 171 SkPath::SkPath(const SkPath& that)
189 : fPathRef(SkRef(that.fPathRef.get())) { 172 : fPathRef(SkRef(that.fPathRef.get())) {
(...skipping 19 matching lines...) Expand all
209 GEN_ID_INC; // Similar to swap, we can't just copy this or it could go back in time. 192 GEN_ID_INC; // Similar to swap, we can't just copy this or it could go back in time.
210 fSourcePath = that.fSourcePath; 193 fSourcePath = that.fSourcePath;
211 #endif 194 #endif
212 } 195 }
213 SkDEBUGCODE(this->validate();) 196 SkDEBUGCODE(this->validate();)
214 return *this; 197 return *this;
215 } 198 }
216 199
217 void SkPath::copyFields(const SkPath& that) { 200 void SkPath::copyFields(const SkPath& that) {
218 //fPathRef is assumed to have been set by the caller. 201 //fPathRef is assumed to have been set by the caller.
219 fBounds = that.fBounds;
220 fLastMoveToIndex = that.fLastMoveToIndex; 202 fLastMoveToIndex = that.fLastMoveToIndex;
221 fFillType = that.fFillType; 203 fFillType = that.fFillType;
222 fSegmentMask = that.fSegmentMask; 204 fSegmentMask = that.fSegmentMask;
223 fBoundsIsDirty = that.fBoundsIsDirty;
224 fConvexity = that.fConvexity; 205 fConvexity = that.fConvexity;
225 fDirection = that.fDirection; 206 fDirection = that.fDirection;
226 fIsFinite = that.fIsFinite;
227 fIsOval = that.fIsOval; 207 fIsOval = that.fIsOval;
228 } 208 }
229 209
230 bool operator==(const SkPath& a, const SkPath& b) { 210 bool operator==(const SkPath& a, const SkPath& b) {
231 // note: don't need to look at isConvex or bounds, since just comparing the 211 // note: don't need to look at isConvex or bounds, since just comparing the
232 // raw data is sufficient. 212 // raw data is sufficient.
233 213
234 // We explicitly check fSegmentMask as a quick-reject. We could skip it, 214 // We explicitly check fSegmentMask as a quick-reject. We could skip it,
235 // since it is only a cache of info in the fVerbs, but its a fast way to 215 // since it is only a cache of info in the fVerbs, but its a fast way to
236 // notice a difference 216 // notice a difference
237 217
238 return &a == &b || 218 return &a == &b ||
239 (a.fFillType == b.fFillType && a.fSegmentMask == b.fSegmentMask && 219 (a.fFillType == b.fFillType && a.fSegmentMask == b.fSegmentMask &&
240 *a.fPathRef.get() == *b.fPathRef.get()); 220 *a.fPathRef.get() == *b.fPathRef.get());
241 } 221 }
242 222
243 void SkPath::swap(SkPath& that) { 223 void SkPath::swap(SkPath& that) {
244 SkASSERT(&that != NULL); 224 SkASSERT(&that != NULL);
245 225
246 if (this != &that) { 226 if (this != &that) {
247 fPathRef.swap(&that.fPathRef); 227 fPathRef.swap(&that.fPathRef);
248 SkTSwap<SkRect>(fBounds, that.fBounds);
249 SkTSwap<int>(fLastMoveToIndex, that.fLastMoveToIndex); 228 SkTSwap<int>(fLastMoveToIndex, that.fLastMoveToIndex);
250 SkTSwap<uint8_t>(fFillType, that.fFillType); 229 SkTSwap<uint8_t>(fFillType, that.fFillType);
251 SkTSwap<uint8_t>(fSegmentMask, that.fSegmentMask); 230 SkTSwap<uint8_t>(fSegmentMask, that.fSegmentMask);
252 SkTSwap<uint8_t>(fBoundsIsDirty, that.fBoundsIsDirty);
253 SkTSwap<uint8_t>(fConvexity, that.fConvexity); 231 SkTSwap<uint8_t>(fConvexity, that.fConvexity);
254 SkTSwap<uint8_t>(fDirection, that.fDirection); 232 SkTSwap<uint8_t>(fDirection, that.fDirection);
255 SkTSwap<SkBool8>(fIsFinite, that.fIsFinite);
256 SkTSwap<SkBool8>(fIsOval, that.fIsOval); 233 SkTSwap<SkBool8>(fIsOval, that.fIsOval);
257 #ifdef SK_BUILD_FOR_ANDROID 234 #ifdef SK_BUILD_FOR_ANDROID
258 // It doesn't really make sense to swap the generation IDs here, because they might go 235 // It doesn't really make sense to swap the generation IDs here, because they might go
259 // backwards. To be safe we increment both to mark them both as changed . 236 // backwards. To be safe we increment both to mark them both as changed .
260 GEN_ID_INC; 237 GEN_ID_INC;
261 GEN_ID_PTR_INC(&that); 238 GEN_ID_PTR_INC(&that);
262 SkTSwap<const SkPath*>(fSourcePath, that.fSourcePath); 239 SkTSwap<const SkPath*>(fSourcePath, that.fSourcePath);
263 #endif 240 #endif
264 } 241 }
265 } 242 }
266 243
244 const SkRect& SkPath::getBounds() const {
245 return fPathRef->getBounds();
246 }
247
248 void SkPath::setBounds(const SkRect& rect) {
249 fPathRef->setBounds(rect);
250 }
251
267 static inline bool check_edge_against_rect(const SkPoint& p0, 252 static inline bool check_edge_against_rect(const SkPoint& p0,
268 const SkPoint& p1, 253 const SkPoint& p1,
269 const SkRect& rect, 254 const SkRect& rect,
270 SkPath::Direction dir) { 255 SkPath::Direction dir) {
271 const SkPoint* edgeBegin; 256 const SkPoint* edgeBegin;
272 SkVector v; 257 SkVector v;
273 if (SkPath::kCW_Direction == dir) { 258 if (SkPath::kCW_Direction == dir) {
274 v = p1 - p0; 259 v = p1 - p0;
275 edgeBegin = &p0; 260 edgeBegin = &p0;
276 } else { 261 } else {
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 362
378 SkPathRef::Rewind(&fPathRef); 363 SkPathRef::Rewind(&fPathRef);
379 this->resetFields(); 364 this->resetFields();
380 } 365 }
381 366
382 bool SkPath::isEmpty() const { 367 bool SkPath::isEmpty() const {
383 SkDEBUGCODE(this->validate();) 368 SkDEBUGCODE(this->validate();)
384 return 0 == fPathRef->countVerbs(); 369 return 0 == fPathRef->countVerbs();
385 } 370 }
386 371
372 bool SkPath::isFinite() const {
373 SkDEBUGCODE(this->validate();)
374 return fPathRef->isFinite();
375 }
376
377 bool SkPath::hasComputedBounds() const {
378 SkDEBUGCODE(this->validate();)
379 return fPathRef->hasComputedBounds();
380 }
381
387 bool SkPath::isLine(SkPoint line[2]) const { 382 bool SkPath::isLine(SkPoint line[2]) const {
388 int verbCount = fPathRef->countVerbs(); 383 int verbCount = fPathRef->countVerbs();
389 384
390 if (2 == verbCount) { 385 if (2 == verbCount) {
391 SkASSERT(kMove_Verb == fPathRef->atVerb(0)); 386 SkASSERT(kMove_Verb == fPathRef->atVerb(0));
392 if (kLine_Verb == fPathRef->atVerb(1)) { 387 if (kLine_Verb == fPathRef->atVerb(1)) {
393 SkASSERT(2 == fPathRef->countPoints()); 388 SkASSERT(2 == fPathRef->countPoints());
394 if (line) { 389 if (line) {
395 const SkPoint* pts = fPathRef->points(); 390 const SkPoint* pts = fPathRef->points();
396 line[0] = pts[0]; 391 line[0] = pts[0];
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
658 if (count == 0) { 653 if (count == 0) {
659 this->moveTo(x, y); 654 this->moveTo(x, y);
660 } else { 655 } else {
661 fIsOval = false; 656 fIsOval = false;
662 SkPathRef::Editor ed(&fPathRef); 657 SkPathRef::Editor ed(&fPathRef);
663 ed.atPoint(count-1)->set(x, y); 658 ed.atPoint(count-1)->set(x, y);
664 GEN_ID_INC; 659 GEN_ID_INC;
665 } 660 }
666 } 661 }
667 662
668 void SkPath::computeBounds() const {
669 SkDEBUGCODE(this->validate();)
670 SkASSERT(fBoundsIsDirty);
671
672 fIsFinite = compute_pt_bounds(&fBounds, *fPathRef.get());
673 fBoundsIsDirty = false;
674 }
675
676 void SkPath::setConvexity(Convexity c) { 663 void SkPath::setConvexity(Convexity c) {
677 if (fConvexity != c) { 664 if (fConvexity != c) {
678 fConvexity = c; 665 fConvexity = c;
679 GEN_ID_INC; 666 GEN_ID_INC;
680 } 667 }
681 } 668 }
682 669
683 ////////////////////////////////////////////////////////////////////////////// 670 //////////////////////////////////////////////////////////////////////////////
684 // Construction methods 671 // Construction methods
685 672
686 #define DIRTY_AFTER_EDIT \ 673 #define DIRTY_AFTER_EDIT \
687 do { \ 674 do { \
688 fBoundsIsDirty = true; \
689 fConvexity = kUnknown_Convexity; \ 675 fConvexity = kUnknown_Convexity; \
690 fDirection = kUnknown_Direction; \ 676 fDirection = kUnknown_Direction; \
691 fIsOval = false; \ 677 fIsOval = false; \
692 } while (0) 678 } while (0)
693 679
694 #define DIRTY_AFTER_EDIT_NO_CONVEXITY_OR_DIRECTION_CHANGE \
695 do { \
696 fBoundsIsDirty = true; \
697 } while (0)
698
699 void SkPath::incReserve(U16CPU inc) { 680 void SkPath::incReserve(U16CPU inc) {
700 SkDEBUGCODE(this->validate();) 681 SkDEBUGCODE(this->validate();)
701 SkPathRef::Editor(&fPathRef, inc, inc); 682 SkPathRef::Editor(&fPathRef, inc, inc);
702 SkDEBUGCODE(this->validate();) 683 SkDEBUGCODE(this->validate();)
703 } 684 }
704 685
705 void SkPath::moveTo(SkScalar x, SkScalar y) { 686 void SkPath::moveTo(SkScalar x, SkScalar y) {
706 SkDEBUGCODE(this->validate();) 687 SkDEBUGCODE(this->validate();)
707 688
708 SkPathRef::Editor ed(&fPathRef); 689 SkPathRef::Editor ed(&fPathRef);
709 690
710 // remember our index 691 // remember our index
711 fLastMoveToIndex = ed.pathRef()->countPoints(); 692 fLastMoveToIndex = ed.pathRef()->countPoints();
712 693
713 ed.growForVerb(kMove_Verb)->set(x, y); 694 ed.growForVerb(kMove_Verb)->set(x, y);
714 695
715 GEN_ID_INC; 696 GEN_ID_INC;
716 DIRTY_AFTER_EDIT_NO_CONVEXITY_OR_DIRECTION_CHANGE;
717 } 697 }
718 698
719 void SkPath::rMoveTo(SkScalar x, SkScalar y) { 699 void SkPath::rMoveTo(SkScalar x, SkScalar y) {
720 SkPoint pt; 700 SkPoint pt;
721 this->getLastPt(&pt); 701 this->getLastPt(&pt);
722 this->moveTo(pt.fX + x, pt.fY + y); 702 this->moveTo(pt.fX + x, pt.fY + y);
723 } 703 }
724 704
725 void SkPath::injectMoveToIfNeeded() { 705 void SkPath::injectMoveToIfNeeded() {
726 if (fLastMoveToIndex < 0) { 706 if (fLastMoveToIndex < 0) {
(...skipping 948 matching lines...) Expand 10 before | Expand all | Expand 10 after
1675 SkDEBUGFAIL("unknown verb"); 1655 SkDEBUGFAIL("unknown verb");
1676 break; 1656 break;
1677 } 1657 }
1678 } 1658 }
1679 1659
1680 dst->swap(tmp); 1660 dst->swap(tmp);
1681 SkPathRef::Editor ed(&dst->fPathRef); 1661 SkPathRef::Editor ed(&dst->fPathRef);
1682 matrix.mapPoints(ed.points(), ed.pathRef()->countPoints()); 1662 matrix.mapPoints(ed.points(), ed.pathRef()->countPoints());
1683 dst->fDirection = kUnknown_Direction; 1663 dst->fDirection = kUnknown_Direction;
1684 } else { 1664 } else {
1685 /*
1686 * If we're not in perspective, we can transform all of the points at
1687 * once.
1688 *
1689 * Here we also want to optimize bounds, by noting if the bounds are
1690 * already known, and if so, we just transform those as well and mark
1691 * them as "known", rather than force the transformed path to have to
1692 * recompute them.
1693 *
1694 * Special gotchas if the path is effectively empty (<= 1 point) or
1695 * if it is non-finite. In those cases bounds need to stay empty,
1696 * regardless of the matrix.
1697 */
1698 if (!fBoundsIsDirty && matrix.rectStaysRect() && fPathRef->countPoints() > 1) {
1699 dst->fBoundsIsDirty = false;
1700 if (fIsFinite) {
1701 matrix.mapRect(&dst->fBounds, fBounds);
1702 if (!(dst->fIsFinite = dst->fBounds.isFinite())) {
1703 dst->fBounds.setEmpty();
1704 }
1705 } else {
1706 dst->fIsFinite = false;
1707 dst->fBounds.setEmpty();
1708 }
1709 } else {
1710 GEN_ID_PTR_INC(dst);
1711 dst->fBoundsIsDirty = true;
1712 }
1713
1714 SkPathRef::CreateTransformedCopy(&dst->fPathRef, *fPathRef.get(), matrix ); 1665 SkPathRef::CreateTransformedCopy(&dst->fPathRef, *fPathRef.get(), matrix );
1715 1666
1716 if (this != dst) { 1667 if (this != dst) {
1717 dst->fFillType = fFillType; 1668 dst->fFillType = fFillType;
1718 dst->fSegmentMask = fSegmentMask; 1669 dst->fSegmentMask = fSegmentMask;
1719 dst->fConvexity = fConvexity; 1670 dst->fConvexity = fConvexity;
1720 } 1671 }
1721 1672
1722 #ifdef SK_BUILD_FOR_ANDROID 1673 #ifdef SK_BUILD_FOR_ANDROID
1723 if (!matrix.isIdentity()) { 1674 if (!matrix.isIdentity() && !dst->hasComputedBounds()) {
1724 GEN_ID_PTR_INC(dst); 1675 GEN_ID_PTR_INC(dst);
1725 } 1676 }
1726 #endif 1677 #endif
1727 1678
1728 if (kUnknown_Direction == fDirection) { 1679 if (kUnknown_Direction == fDirection) {
1729 dst->fDirection = kUnknown_Direction; 1680 dst->fDirection = kUnknown_Direction;
1730 } else { 1681 } else {
1731 SkScalar det2x2 = 1682 SkScalar det2x2 =
1732 SkScalarMul(matrix.get(SkMatrix::kMScaleX), matrix.get(SkMatrix: :kMScaleY)) - 1683 SkScalarMul(matrix.get(SkMatrix::kMScaleX), matrix.get(SkMatrix: :kMScaleY)) -
1733 SkScalarMul(matrix.get(SkMatrix::kMSkewX), matrix.get(SkMatrix:: kMSkewY)); 1684 SkScalarMul(matrix.get(SkMatrix::kMSkewX), matrix.get(SkMatrix:: kMSkewY));
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after
2082 /////////////////////////////////////////////////////////////////////////////// 2033 ///////////////////////////////////////////////////////////////////////////////
2083 2034
2084 /* 2035 /*
2085 Format in compressed buffer: [ptCount, verbCount, pts[], verbs[]] 2036 Format in compressed buffer: [ptCount, verbCount, pts[], verbs[]]
2086 */ 2037 */
2087 2038
2088 uint32_t SkPath::writeToMemory(void* storage) const { 2039 uint32_t SkPath::writeToMemory(void* storage) const {
2089 SkDEBUGCODE(this->validate();) 2040 SkDEBUGCODE(this->validate();)
2090 2041
2091 if (NULL == storage) { 2042 if (NULL == storage) {
2092 const int byteCount = sizeof(int32_t) 2043 const int byteCount = sizeof(int32_t) + fPathRef->writeSize();
2093 + fPathRef->writeSize()
2094 + sizeof(SkRect);
2095 return SkAlign4(byteCount); 2044 return SkAlign4(byteCount);
2096 } 2045 }
2097 2046
2098 SkWBuffer buffer(storage); 2047 SkWBuffer buffer(storage);
2099 2048
2100 // Call getBounds() to ensure (as a side-effect) that fBounds 2049 int32_t packed = ((fIsOval & 1) << kIsOval_SerializationShift) |
2101 // and fIsFinite are computed.
2102 const SkRect& bounds = this->getBounds();
2103 SkASSERT(!fBoundsIsDirty);
2104
2105 int32_t packed = ((fIsFinite & 1) << kIsFinite_SerializationShift) |
2106 ((fIsOval & 1) << kIsOval_SerializationShift) |
2107 (fConvexity << kConvexity_SerializationShift) | 2050 (fConvexity << kConvexity_SerializationShift) |
2108 (fFillType << kFillType_SerializationShift) | 2051 (fFillType << kFillType_SerializationShift) |
2109 (fSegmentMask << kSegmentMask_SerializationShift) | 2052 (fSegmentMask << kSegmentMask_SerializationShift) |
2110 (fDirection << kDirection_SerializationShift); 2053 (fDirection << kDirection_SerializationShift)
2054 #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V14_AND_ALL_OTHER_INSTANCES_TO O
2055 | (0x1 << kNewFormat_SerializationShift);
2056 #endif
2111 2057
2112 buffer.write32(packed); 2058 buffer.write32(packed);
2113 2059
2114 fPathRef->writeToBuffer(&buffer); 2060 fPathRef->writeToBuffer(&buffer);
2115 2061
2116 buffer.write(&bounds, sizeof(bounds));
2117
2118 buffer.padToAlign4(); 2062 buffer.padToAlign4();
2119 return SkToU32(buffer.pos()); 2063 return SkToU32(buffer.pos());
2120 } 2064 }
2121 2065
2122 uint32_t SkPath::readFromMemory(const void* storage) { 2066 uint32_t SkPath::readFromMemory(const void* storage) {
2123 SkRBuffer buffer(storage); 2067 SkRBuffer buffer(storage);
2124 2068
2125 uint32_t packed = buffer.readS32(); 2069 uint32_t packed = buffer.readS32();
2126 fIsFinite = (packed >> kIsFinite_SerializationShift) & 1;
2127 fIsOval = (packed >> kIsOval_SerializationShift) & 1; 2070 fIsOval = (packed >> kIsOval_SerializationShift) & 1;
2128 fConvexity = (packed >> kConvexity_SerializationShift) & 0xFF; 2071 fConvexity = (packed >> kConvexity_SerializationShift) & 0xFF;
2129 fFillType = (packed >> kFillType_SerializationShift) & 0xFF; 2072 fFillType = (packed >> kFillType_SerializationShift) & 0xFF;
2130 fSegmentMask = (packed >> kSegmentMask_SerializationShift) & 0xF; 2073 fSegmentMask = (packed >> kSegmentMask_SerializationShift) & 0xF;
2131 fDirection = (packed >> kDirection_SerializationShift) & 0x3; 2074 fDirection = (packed >> kDirection_SerializationShift) & 0x3;
2075 #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V14_AND_ALL_OTHER_INSTANCES_TO O
2076 bool newFormat = (packed >> kNewFormat_SerializationShift) & 1;
2077 #endif
2132 2078
2133 fPathRef.reset(SkPathRef::CreateFromBuffer(&buffer)); 2079 fPathRef.reset(SkPathRef::CreateFromBuffer(&buffer
2134 2080 #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V14_AND_ALL_OTHER_INSTANCES_TO O
2135 buffer.read(&fBounds, sizeof(fBounds)); 2081 , newFormat, packed)
2136 fBoundsIsDirty = false; 2082 #endif
2083 );
2137 2084
2138 buffer.skipToAlign4(); 2085 buffer.skipToAlign4();
2139 2086
2140 GEN_ID_INC; 2087 GEN_ID_INC;
2141 2088
2142 SkDEBUGCODE(this->validate();) 2089 SkDEBUGCODE(this->validate();)
2143 return SkToU32(buffer.pos()); 2090 return SkToU32(buffer.pos());
2144 } 2091 }
2145 2092
2146 /////////////////////////////////////////////////////////////////////////////// 2093 ///////////////////////////////////////////////////////////////////////////////
(...skipping 858 matching lines...) Expand 10 before | Expand all | Expand 10 after
3005 switch (this->getFillType()) { 2952 switch (this->getFillType()) {
3006 case SkPath::kEvenOdd_FillType: 2953 case SkPath::kEvenOdd_FillType:
3007 case SkPath::kInverseEvenOdd_FillType: 2954 case SkPath::kInverseEvenOdd_FillType:
3008 w &= 1; 2955 w &= 1;
3009 break; 2956 break;
3010 default: 2957 default:
3011 break; 2958 break;
3012 } 2959 }
3013 return SkToBool(w); 2960 return SkToBool(w);
3014 } 2961 }
OLDNEW
« include/core/SkPath.h ('K') | « include/core/SkPicture.h ('k') | src/core/SkPathRef.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698