| 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 } |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |