| 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 |