OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 this->resetFields(); | 349 this->resetFields(); |
373 } | 350 } |
374 | 351 |
375 void SkPath::rewind() { | 352 void SkPath::rewind() { |
376 SkDEBUGCODE(this->validate();) | 353 SkDEBUGCODE(this->validate();) |
377 | 354 |
378 SkPathRef::Rewind(&fPathRef); | 355 SkPathRef::Rewind(&fPathRef); |
379 this->resetFields(); | 356 this->resetFields(); |
380 } | 357 } |
381 | 358 |
382 bool SkPath::isEmpty() const { | |
383 SkDEBUGCODE(this->validate();) | |
384 return 0 == fPathRef->countVerbs(); | |
385 } | |
386 | |
387 bool SkPath::isLine(SkPoint line[2]) const { | 359 bool SkPath::isLine(SkPoint line[2]) const { |
388 int verbCount = fPathRef->countVerbs(); | 360 int verbCount = fPathRef->countVerbs(); |
389 | 361 |
390 if (2 == verbCount) { | 362 if (2 == verbCount) { |
391 SkASSERT(kMove_Verb == fPathRef->atVerb(0)); | 363 SkASSERT(kMove_Verb == fPathRef->atVerb(0)); |
392 if (kLine_Verb == fPathRef->atVerb(1)) { | 364 if (kLine_Verb == fPathRef->atVerb(1)) { |
393 SkASSERT(2 == fPathRef->countPoints()); | 365 SkASSERT(2 == fPathRef->countPoints()); |
394 if (line) { | 366 if (line) { |
395 const SkPoint* pts = fPathRef->points(); | 367 const SkPoint* pts = fPathRef->points(); |
396 line[0] = pts[0]; | 368 line[0] = pts[0]; |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
658 if (count == 0) { | 630 if (count == 0) { |
659 this->moveTo(x, y); | 631 this->moveTo(x, y); |
660 } else { | 632 } else { |
661 fIsOval = false; | 633 fIsOval = false; |
662 SkPathRef::Editor ed(&fPathRef); | 634 SkPathRef::Editor ed(&fPathRef); |
663 ed.atPoint(count-1)->set(x, y); | 635 ed.atPoint(count-1)->set(x, y); |
664 GEN_ID_INC; | 636 GEN_ID_INC; |
665 } | 637 } |
666 } | 638 } |
667 | 639 |
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) { | 640 void SkPath::setConvexity(Convexity c) { |
677 if (fConvexity != c) { | 641 if (fConvexity != c) { |
678 fConvexity = c; | 642 fConvexity = c; |
679 GEN_ID_INC; | 643 GEN_ID_INC; |
680 } | 644 } |
681 } | 645 } |
682 | 646 |
683 ////////////////////////////////////////////////////////////////////////////// | 647 ////////////////////////////////////////////////////////////////////////////// |
684 // Construction methods | 648 // Construction methods |
685 | 649 |
686 #define DIRTY_AFTER_EDIT \ | 650 #define DIRTY_AFTER_EDIT \ |
687 do { \ | 651 do { \ |
688 fBoundsIsDirty = true; \ | |
689 fConvexity = kUnknown_Convexity; \ | 652 fConvexity = kUnknown_Convexity; \ |
690 fDirection = kUnknown_Direction; \ | 653 fDirection = kUnknown_Direction; \ |
691 fIsOval = false; \ | 654 fIsOval = false; \ |
692 } while (0) | 655 } while (0) |
693 | 656 |
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) { | 657 void SkPath::incReserve(U16CPU inc) { |
700 SkDEBUGCODE(this->validate();) | 658 SkDEBUGCODE(this->validate();) |
701 SkPathRef::Editor(&fPathRef, inc, inc); | 659 SkPathRef::Editor(&fPathRef, inc, inc); |
702 SkDEBUGCODE(this->validate();) | 660 SkDEBUGCODE(this->validate();) |
703 } | 661 } |
704 | 662 |
705 void SkPath::moveTo(SkScalar x, SkScalar y) { | 663 void SkPath::moveTo(SkScalar x, SkScalar y) { |
706 SkDEBUGCODE(this->validate();) | 664 SkDEBUGCODE(this->validate();) |
707 | 665 |
708 SkPathRef::Editor ed(&fPathRef); | 666 SkPathRef::Editor ed(&fPathRef); |
709 | 667 |
710 // remember our index | 668 // remember our index |
711 fLastMoveToIndex = ed.pathRef()->countPoints(); | 669 fLastMoveToIndex = ed.pathRef()->countPoints(); |
712 | 670 |
713 ed.growForVerb(kMove_Verb)->set(x, y); | 671 ed.growForVerb(kMove_Verb)->set(x, y); |
714 | 672 |
715 GEN_ID_INC; | 673 GEN_ID_INC; |
716 DIRTY_AFTER_EDIT_NO_CONVEXITY_OR_DIRECTION_CHANGE; | |
717 } | 674 } |
718 | 675 |
719 void SkPath::rMoveTo(SkScalar x, SkScalar y) { | 676 void SkPath::rMoveTo(SkScalar x, SkScalar y) { |
720 SkPoint pt; | 677 SkPoint pt; |
721 this->getLastPt(&pt); | 678 this->getLastPt(&pt); |
722 this->moveTo(pt.fX + x, pt.fY + y); | 679 this->moveTo(pt.fX + x, pt.fY + y); |
723 } | 680 } |
724 | 681 |
725 void SkPath::injectMoveToIfNeeded() { | 682 void SkPath::injectMoveToIfNeeded() { |
726 if (fLastMoveToIndex < 0) { | 683 if (fLastMoveToIndex < 0) { |
(...skipping 948 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1675 SkDEBUGFAIL("unknown verb"); | 1632 SkDEBUGFAIL("unknown verb"); |
1676 break; | 1633 break; |
1677 } | 1634 } |
1678 } | 1635 } |
1679 | 1636 |
1680 dst->swap(tmp); | 1637 dst->swap(tmp); |
1681 SkPathRef::Editor ed(&dst->fPathRef); | 1638 SkPathRef::Editor ed(&dst->fPathRef); |
1682 matrix.mapPoints(ed.points(), ed.pathRef()->countPoints()); | 1639 matrix.mapPoints(ed.points(), ed.pathRef()->countPoints()); |
1683 dst->fDirection = kUnknown_Direction; | 1640 dst->fDirection = kUnknown_Direction; |
1684 } else { | 1641 } 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
); | 1642 SkPathRef::CreateTransformedCopy(&dst->fPathRef, *fPathRef.get(), matrix
); |
1715 | 1643 |
1716 if (this != dst) { | 1644 if (this != dst) { |
1717 dst->fFillType = fFillType; | 1645 dst->fFillType = fFillType; |
1718 dst->fSegmentMask = fSegmentMask; | 1646 dst->fSegmentMask = fSegmentMask; |
1719 dst->fConvexity = fConvexity; | 1647 dst->fConvexity = fConvexity; |
1720 } | 1648 } |
1721 | 1649 |
1722 #ifdef SK_BUILD_FOR_ANDROID | 1650 #ifdef SK_BUILD_FOR_ANDROID |
1723 if (!matrix.isIdentity()) { | 1651 if (!matrix.isIdentity() && !dst->hasComputedBounds()) { |
1724 GEN_ID_PTR_INC(dst); | 1652 GEN_ID_PTR_INC(dst); |
1725 } | 1653 } |
1726 #endif | 1654 #endif |
1727 | 1655 |
1728 if (kUnknown_Direction == fDirection) { | 1656 if (kUnknown_Direction == fDirection) { |
1729 dst->fDirection = kUnknown_Direction; | 1657 dst->fDirection = kUnknown_Direction; |
1730 } else { | 1658 } else { |
1731 SkScalar det2x2 = | 1659 SkScalar det2x2 = |
1732 SkScalarMul(matrix.get(SkMatrix::kMScaleX), matrix.get(SkMatrix:
:kMScaleY)) - | 1660 SkScalarMul(matrix.get(SkMatrix::kMScaleX), matrix.get(SkMatrix:
:kMScaleY)) - |
1733 SkScalarMul(matrix.get(SkMatrix::kMSkewX), matrix.get(SkMatrix::
kMSkewY)); | 1661 SkScalarMul(matrix.get(SkMatrix::kMSkewX), matrix.get(SkMatrix::
kMSkewY)); |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2082 /////////////////////////////////////////////////////////////////////////////// | 2010 /////////////////////////////////////////////////////////////////////////////// |
2083 | 2011 |
2084 /* | 2012 /* |
2085 Format in compressed buffer: [ptCount, verbCount, pts[], verbs[]] | 2013 Format in compressed buffer: [ptCount, verbCount, pts[], verbs[]] |
2086 */ | 2014 */ |
2087 | 2015 |
2088 uint32_t SkPath::writeToMemory(void* storage) const { | 2016 uint32_t SkPath::writeToMemory(void* storage) const { |
2089 SkDEBUGCODE(this->validate();) | 2017 SkDEBUGCODE(this->validate();) |
2090 | 2018 |
2091 if (NULL == storage) { | 2019 if (NULL == storage) { |
2092 const int byteCount = sizeof(int32_t) | 2020 const int byteCount = sizeof(int32_t) + fPathRef->writeSize(); |
2093 + fPathRef->writeSize() | |
2094 + sizeof(SkRect); | |
2095 return SkAlign4(byteCount); | 2021 return SkAlign4(byteCount); |
2096 } | 2022 } |
2097 | 2023 |
2098 SkWBuffer buffer(storage); | 2024 SkWBuffer buffer(storage); |
2099 | 2025 |
2100 // Call getBounds() to ensure (as a side-effect) that fBounds | 2026 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) | | 2027 (fConvexity << kConvexity_SerializationShift) | |
2108 (fFillType << kFillType_SerializationShift) | | 2028 (fFillType << kFillType_SerializationShift) | |
2109 (fSegmentMask << kSegmentMask_SerializationShift) | | 2029 (fSegmentMask << kSegmentMask_SerializationShift) | |
2110 (fDirection << kDirection_SerializationShift); | 2030 (fDirection << kDirection_SerializationShift) |
| 2031 #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V14_AND_ALL_OTHER_INSTANCES_TO
O |
| 2032 | (0x1 << kNewFormat_SerializationShift); |
| 2033 #endif |
2111 | 2034 |
2112 buffer.write32(packed); | 2035 buffer.write32(packed); |
2113 | 2036 |
2114 fPathRef->writeToBuffer(&buffer); | 2037 fPathRef->writeToBuffer(&buffer); |
2115 | 2038 |
2116 buffer.write(&bounds, sizeof(bounds)); | |
2117 | |
2118 buffer.padToAlign4(); | 2039 buffer.padToAlign4(); |
2119 return SkToU32(buffer.pos()); | 2040 return SkToU32(buffer.pos()); |
2120 } | 2041 } |
2121 | 2042 |
2122 uint32_t SkPath::readFromMemory(const void* storage) { | 2043 uint32_t SkPath::readFromMemory(const void* storage) { |
2123 SkRBuffer buffer(storage); | 2044 SkRBuffer buffer(storage); |
2124 | 2045 |
2125 uint32_t packed = buffer.readS32(); | 2046 uint32_t packed = buffer.readS32(); |
2126 fIsFinite = (packed >> kIsFinite_SerializationShift) & 1; | |
2127 fIsOval = (packed >> kIsOval_SerializationShift) & 1; | 2047 fIsOval = (packed >> kIsOval_SerializationShift) & 1; |
2128 fConvexity = (packed >> kConvexity_SerializationShift) & 0xFF; | 2048 fConvexity = (packed >> kConvexity_SerializationShift) & 0xFF; |
2129 fFillType = (packed >> kFillType_SerializationShift) & 0xFF; | 2049 fFillType = (packed >> kFillType_SerializationShift) & 0xFF; |
2130 fSegmentMask = (packed >> kSegmentMask_SerializationShift) & 0xF; | 2050 fSegmentMask = (packed >> kSegmentMask_SerializationShift) & 0xF; |
2131 fDirection = (packed >> kDirection_SerializationShift) & 0x3; | 2051 fDirection = (packed >> kDirection_SerializationShift) & 0x3; |
| 2052 #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V14_AND_ALL_OTHER_INSTANCES_TO
O |
| 2053 bool newFormat = (packed >> kNewFormat_SerializationShift) & 1; |
| 2054 #endif |
2132 | 2055 |
2133 fPathRef.reset(SkPathRef::CreateFromBuffer(&buffer)); | 2056 fPathRef.reset(SkPathRef::CreateFromBuffer(&buffer |
2134 | 2057 #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V14_AND_ALL_OTHER_INSTANCES_TO
O |
2135 buffer.read(&fBounds, sizeof(fBounds)); | 2058 , newFormat, packed) |
2136 fBoundsIsDirty = false; | 2059 #endif |
| 2060 ); |
2137 | 2061 |
2138 buffer.skipToAlign4(); | 2062 buffer.skipToAlign4(); |
2139 | 2063 |
2140 GEN_ID_INC; | 2064 GEN_ID_INC; |
2141 | 2065 |
2142 SkDEBUGCODE(this->validate();) | 2066 SkDEBUGCODE(this->validate();) |
2143 return SkToU32(buffer.pos()); | 2067 return SkToU32(buffer.pos()); |
2144 } | 2068 } |
2145 | 2069 |
2146 /////////////////////////////////////////////////////////////////////////////// | 2070 /////////////////////////////////////////////////////////////////////////////// |
(...skipping 858 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3005 switch (this->getFillType()) { | 2929 switch (this->getFillType()) { |
3006 case SkPath::kEvenOdd_FillType: | 2930 case SkPath::kEvenOdd_FillType: |
3007 case SkPath::kInverseEvenOdd_FillType: | 2931 case SkPath::kInverseEvenOdd_FillType: |
3008 w &= 1; | 2932 w &= 1; |
3009 break; | 2933 break; |
3010 default: | 2934 default: |
3011 break; | 2935 break; |
3012 } | 2936 } |
3013 return SkToBool(w); | 2937 return SkToBool(w); |
3014 } | 2938 } |
OLD | NEW |