| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  * Copyright 2013 Google Inc. | 2  * Copyright 2013 Google Inc. | 
| 3  * | 3  * | 
| 4  * Use of this source code is governed by a BSD-style license that can be | 4  * Use of this source code is governed by a BSD-style license that can be | 
| 5  * found in the LICENSE file. | 5  * found in the LICENSE file. | 
| 6  */ | 6  */ | 
| 7 | 7 | 
| 8 #include "SkBuffer.h" | 8 #include "SkBuffer.h" | 
| 9 #include "SkOnce.h" | 9 #include "SkOnce.h" | 
| 10 #include "SkPath.h" | 10 #include "SkPath.h" | 
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 83     SkASSERT((*dst)->countPoints() == src.countPoints()); | 83     SkASSERT((*dst)->countPoints() == src.countPoints()); | 
| 84     SkASSERT((*dst)->countVerbs() == src.countVerbs()); | 84     SkASSERT((*dst)->countVerbs() == src.countVerbs()); | 
| 85     SkASSERT((*dst)->fConicWeights.count() == src.fConicWeights.count()); | 85     SkASSERT((*dst)->fConicWeights.count() == src.fConicWeights.count()); | 
| 86 | 86 | 
| 87     // Need to check this here in case (&src == dst) | 87     // Need to check this here in case (&src == dst) | 
| 88     bool canXformBounds = !src.fBoundsIsDirty && matrix.rectStaysRect() && src.c
     ountPoints() > 1; | 88     bool canXformBounds = !src.fBoundsIsDirty && matrix.rectStaysRect() && src.c
     ountPoints() > 1; | 
| 89 | 89 | 
| 90     matrix.mapPoints((*dst)->fPoints, src.points(), src.fPointCnt); | 90     matrix.mapPoints((*dst)->fPoints, src.points(), src.fPointCnt); | 
| 91 | 91 | 
| 92     /* | 92     /* | 
| 93         *  Here we optimize the bounds computation, by noting if the bounds are | 93      *  Here we optimize the bounds computation, by noting if the bounds are | 
| 94         *  already known, and if so, we just transform those as well and mark | 94      *  already known, and if so, we just transform those as well and mark | 
| 95         *  them as "known", rather than force the transformed path to have to | 95      *  them as "known", rather than force the transformed path to have to | 
| 96         *  recompute them. | 96      *  recompute them. | 
| 97         * | 97      * | 
| 98         *  Special gotchas if the path is effectively empty (<= 1 point) or | 98      *  Special gotchas if the path is effectively empty (<= 1 point) or | 
| 99         *  if it is non-finite. In those cases bounds need to stay empty, | 99      *  if it is non-finite. In those cases bounds need to stay empty, | 
| 100         *  regardless of the matrix. | 100      *  regardless of the matrix. | 
| 101         */ | 101      */ | 
| 102     if (canXformBounds) { | 102     if (canXformBounds) { | 
| 103         (*dst)->fBoundsIsDirty = false; | 103         (*dst)->fBoundsIsDirty = false; | 
| 104         if (src.fIsFinite) { | 104         if (src.fIsFinite) { | 
| 105             matrix.mapRect(&(*dst)->fBounds, src.fBounds); | 105             matrix.mapRect(&(*dst)->fBounds, src.fBounds); | 
| 106             if (!((*dst)->fIsFinite = (*dst)->fBounds.isFinite())) { | 106             if (!((*dst)->fIsFinite = (*dst)->fBounds.isFinite())) { | 
| 107                 (*dst)->fBounds.setEmpty(); | 107                 (*dst)->fBounds.setEmpty(); | 
| 108             } | 108             } | 
| 109         } else { | 109         } else { | 
| 110             (*dst)->fIsFinite = false; | 110             (*dst)->fIsFinite = false; | 
| 111             (*dst)->fBounds.setEmpty(); | 111             (*dst)->fBounds.setEmpty(); | 
| 112         } | 112         } | 
| 113     } else { | 113     } else { | 
| 114         (*dst)->fBoundsIsDirty = true; | 114         (*dst)->fBoundsIsDirty = true; | 
| 115     } | 115     } | 
| 116 | 116 | 
| 117     (*dst)->fSegmentMask = src.fSegmentMask; | 117     (*dst)->fSegmentMask = src.fSegmentMask; | 
| 118 | 118 | 
| 119     // It's an oval only if it stays a rect. | 119     // It's an oval only if it stays a rect. | 
| 120     bool rectStaysRect = matrix.rectStaysRect(); | 120     bool rectStaysRect = matrix.rectStaysRect(); | 
| 121     (*dst)->fIsOval = src.fIsOval && rectStaysRect; | 121     (*dst)->fIsOval = src.fIsOval && rectStaysRect; | 
| 122     (*dst)->fIsRRect = src.fIsRRect && rectStaysRect; | 122     (*dst)->fIsRRect = src.fIsRRect && rectStaysRect; | 
|  | 123     if ((*dst)->fIsOval || (*dst)->fIsRRect) { | 
|  | 124         int start = src.fRRectOrOvalStartIdx; | 
|  | 125         int rm = 0; | 
|  | 126         if ((*dst)->fIsRRect) { | 
|  | 127             rm = src.fRRectOrOvalStartIdx & 0b1; | 
|  | 128             start /= 2; | 
|  | 129         } | 
|  | 130         // Is the antidiagonal non-zero (otherwise the diagonal is zero) | 
|  | 131         int antiDiag; | 
|  | 132         // Is the non-zero value in the top row (either kMScaleX or kMSkewX) neg
     ative | 
|  | 133         int topNeg; | 
|  | 134         // Are the two non-zero diagonal or antidiagonal values the same sign. | 
|  | 135         int sameSign; | 
|  | 136         if (matrix.get(SkMatrix::kMScaleX) != 0) { | 
|  | 137             antiDiag = 0b00; | 
|  | 138             if (matrix.get(SkMatrix::kMScaleX) > 0) { | 
|  | 139                 topNeg = 0b00; | 
|  | 140                 sameSign = matrix.get(SkMatrix::kMScaleY) > 0 ? 0b01 : 0b00; | 
|  | 141             } else { | 
|  | 142                 topNeg = 0b10; | 
|  | 143                 sameSign = matrix.get(SkMatrix::kMScaleY) > 0 ? 0b00 : 0b01; | 
|  | 144             } | 
|  | 145         } else { | 
|  | 146             antiDiag = 0b01; | 
|  | 147             if (matrix.get(SkMatrix::kMSkewX) > 0) { | 
|  | 148                 topNeg = 0b00; | 
|  | 149                 sameSign = matrix.get(SkMatrix::kMSkewY) > 0 ? 0b01 : 0b00; | 
|  | 150             } else { | 
|  | 151                 topNeg = 0b10; | 
|  | 152                 sameSign = matrix.get(SkMatrix::kMSkewY) > 0 ? 0b00 : 0b01; | 
|  | 153             } | 
|  | 154         } | 
|  | 155         if (sameSign != antiDiag) { | 
|  | 156             // This is a rotation plus scale | 
|  | 157             (*dst)->fRRectOrOvalIsCCW = src.fRRectOrOvalIsCCW; | 
|  | 158             // Trust me (or create yourself a table) | 
|  | 159             (*dst)->fRRectOrOvalStartIdx = (start + 4 - (topNeg | antiDiag)) % 4
     ; | 
|  | 160             SkASSERT((*dst)->fRRectOrOvalStartIdx < 4); | 
|  | 161             if ((*dst)->fIsRRect) { | 
|  | 162                 (*dst)->fRRectOrOvalStartIdx = 2 * (*dst)->fRRectOrOvalStartIdx 
     + rm; | 
|  | 163             } | 
|  | 164         } else { | 
|  | 165             // This is a mirror plus scale | 
|  | 166             (*dst)->fRRectOrOvalIsCCW = !src.fRRectOrOvalIsCCW; | 
|  | 167             // Trust me (or create yourself a table) | 
|  | 168             (*dst)->fRRectOrOvalStartIdx = (6 + (topNeg | antiDiag) - start) % 4
     ; | 
|  | 169             SkASSERT((*dst)->fRRectOrOvalStartIdx < 4); | 
|  | 170             if ((*dst)->fIsRRect) { | 
|  | 171                 (*dst)->fRRectOrOvalStartIdx = 2 * (*dst)->fRRectOrOvalStartIdx 
     + (rm ? 0b0 : 0b1); | 
|  | 172             } | 
|  | 173         } | 
|  | 174     } | 
| 123 | 175 | 
| 124     SkDEBUGCODE((*dst)->validate();) | 176     SkDEBUGCODE((*dst)->validate();) | 
| 125 } | 177 } | 
| 126 | 178 | 
| 127 SkPathRef* SkPathRef::CreateFromBuffer(SkRBuffer* buffer) { | 179 SkPathRef* SkPathRef::CreateFromBuffer(SkRBuffer* buffer) { | 
| 128     SkPathRef* ref = new SkPathRef; | 180     SkPathRef* ref = new SkPathRef; | 
| 129 | 181 | 
| 130     int32_t packed; | 182     int32_t packed; | 
| 131     if (!buffer->readS32(&packed)) { | 183     if (!buffer->readS32(&packed)) { | 
| 132         delete ref; | 184         delete ref; | 
| 133         return nullptr; | 185         return nullptr; | 
| 134     } | 186     } | 
| 135 | 187 | 
| 136     ref->fIsFinite = (packed >> kIsFinite_SerializationShift) & 1; | 188     ref->fIsFinite = (packed >> kIsFinite_SerializationShift) & 1; | 
| 137     uint8_t segmentMask = (packed >> kSegmentMask_SerializationShift) & 0xF; | 189     uint8_t segmentMask = (packed >> kSegmentMask_SerializationShift) & 0xF; | 
| 138     bool isOval  = (packed >> kIsOval_SerializationShift) & 1; | 190     bool isOval  = (packed >> kIsOval_SerializationShift) & 1; | 
| 139     bool isRRect  = (packed >> kIsRRect_SerializationShift) & 1; | 191     bool isRRect  = (packed >> kIsRRect_SerializationShift) & 1; | 
|  | 192     bool rrectOrOvalIsCCW = (packed >> kRRectOrOvalIsCCW_SerializationShift) & 1
     ; | 
|  | 193     unsigned rrectOrOvalStartIdx = (packed >> kRRectOrOvalStartIdx_Serialization
     Shift) & 0x7; | 
| 140 | 194 | 
| 141     int32_t verbCount, pointCount, conicCount; | 195     int32_t verbCount, pointCount, conicCount; | 
| 142     ptrdiff_t maxPtrDiff = std::numeric_limits<ptrdiff_t>::max(); | 196     ptrdiff_t maxPtrDiff = std::numeric_limits<ptrdiff_t>::max(); | 
| 143     if (!buffer->readU32(&(ref->fGenerationID)) || | 197     if (!buffer->readU32(&(ref->fGenerationID)) || | 
| 144         !buffer->readS32(&verbCount) || | 198         !buffer->readS32(&verbCount) || | 
| 145         verbCount < 0 || | 199         verbCount < 0 || | 
| 146         static_cast<uint32_t>(verbCount) > maxPtrDiff/sizeof(uint8_t) || | 200         static_cast<uint32_t>(verbCount) > maxPtrDiff/sizeof(uint8_t) || | 
| 147         !buffer->readS32(&pointCount) || | 201         !buffer->readS32(&pointCount) || | 
| 148         pointCount < 0 || | 202         pointCount < 0 || | 
| 149         static_cast<uint32_t>(pointCount) > maxPtrDiff/sizeof(SkPoint) || | 203         static_cast<uint32_t>(pointCount) > maxPtrDiff/sizeof(SkPoint) || | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
| 166         !buffer->read(&ref->fBounds, sizeof(SkRect))) { | 220         !buffer->read(&ref->fBounds, sizeof(SkRect))) { | 
| 167         delete ref; | 221         delete ref; | 
| 168         return nullptr; | 222         return nullptr; | 
| 169     } | 223     } | 
| 170     ref->fBoundsIsDirty = false; | 224     ref->fBoundsIsDirty = false; | 
| 171 | 225 | 
| 172     // resetToSize clears fSegmentMask and fIsOval | 226     // resetToSize clears fSegmentMask and fIsOval | 
| 173     ref->fSegmentMask = segmentMask; | 227     ref->fSegmentMask = segmentMask; | 
| 174     ref->fIsOval = isOval; | 228     ref->fIsOval = isOval; | 
| 175     ref->fIsRRect = isRRect; | 229     ref->fIsRRect = isRRect; | 
|  | 230     ref->fRRectOrOvalIsCCW = rrectOrOvalIsCCW; | 
|  | 231     ref->fRRectOrOvalStartIdx = rrectOrOvalStartIdx; | 
| 176     return ref; | 232     return ref; | 
| 177 } | 233 } | 
| 178 | 234 | 
| 179 void SkPathRef::Rewind(SkAutoTUnref<SkPathRef>* pathRef) { | 235 void SkPathRef::Rewind(SkAutoTUnref<SkPathRef>* pathRef) { | 
| 180     if ((*pathRef)->unique()) { | 236     if ((*pathRef)->unique()) { | 
| 181         SkDEBUGCODE((*pathRef)->validate();) | 237         SkDEBUGCODE((*pathRef)->validate();) | 
| 182         (*pathRef)->callGenIDChangeListeners(); | 238         (*pathRef)->callGenIDChangeListeners(); | 
| 183         (*pathRef)->fBoundsIsDirty = true;  // this also invalidates fIsFinite | 239         (*pathRef)->fBoundsIsDirty = true;  // this also invalidates fIsFinite | 
| 184         (*pathRef)->fVerbCnt = 0; | 240         (*pathRef)->fVerbCnt = 0; | 
| 185         (*pathRef)->fPointCnt = 0; | 241         (*pathRef)->fPointCnt = 0; | 
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 246 } | 302 } | 
| 247 | 303 | 
| 248 void SkPathRef::writeToBuffer(SkWBuffer* buffer) const { | 304 void SkPathRef::writeToBuffer(SkWBuffer* buffer) const { | 
| 249     SkDEBUGCODE(this->validate();) | 305     SkDEBUGCODE(this->validate();) | 
| 250     SkDEBUGCODE(size_t beforePos = buffer->pos();) | 306     SkDEBUGCODE(size_t beforePos = buffer->pos();) | 
| 251 | 307 | 
| 252     // Call getBounds() to ensure (as a side-effect) that fBounds | 308     // Call getBounds() to ensure (as a side-effect) that fBounds | 
| 253     // and fIsFinite are computed. | 309     // and fIsFinite are computed. | 
| 254     const SkRect& bounds = this->getBounds(); | 310     const SkRect& bounds = this->getBounds(); | 
| 255 | 311 | 
| 256     int32_t packed = ((fIsFinite & 1) << kIsFinite_SerializationShift) | | 312     int32_t packed = ((fRRectOrOvalStartIdx & 7) << kRRectOrOvalStartIdx_Seriali
     zationShift) | | 
|  | 313                      ((fRRectOrOvalIsCCW & 1) << kRRectOrOvalIsCCW_Serialization
     Shift) | | 
|  | 314                      ((fIsFinite & 1) << kIsFinite_SerializationShift) | | 
| 257                      ((fIsOval & 1) << kIsOval_SerializationShift) | | 315                      ((fIsOval & 1) << kIsOval_SerializationShift) | | 
| 258                      ((fIsRRect & 1) << kIsRRect_SerializationShift) | | 316                      ((fIsRRect & 1) << kIsRRect_SerializationShift) | | 
| 259                      (fSegmentMask << kSegmentMask_SerializationShift); | 317                      (fSegmentMask << kSegmentMask_SerializationShift); | 
| 260     buffer->write32(packed); | 318     buffer->write32(packed); | 
| 261 | 319 | 
| 262     // TODO: write gen ID here. Problem: We don't know if we're cross process or
      not from | 320     // TODO: write gen ID here. Problem: We don't know if we're cross process or
      not from | 
| 263     // SkWBuffer. Until this is fixed we write 0. | 321     // SkWBuffer. Until this is fixed we write 0. | 
| 264     buffer->write32(0); | 322     buffer->write32(0); | 
| 265     buffer->write32(fVerbCnt); | 323     buffer->write32(fVerbCnt); | 
| 266     buffer->write32(fPointCnt); | 324     buffer->write32(fPointCnt); | 
| (...skipping 24 matching lines...) Expand all  Loading... | 
| 291     sk_careful_memcpy(this->fPoints, ref.fPoints, ref.fPointCnt * sizeof(SkPoint
     )); | 349     sk_careful_memcpy(this->fPoints, ref.fPoints, ref.fPointCnt * sizeof(SkPoint
     )); | 
| 292     fConicWeights = ref.fConicWeights; | 350     fConicWeights = ref.fConicWeights; | 
| 293     fBoundsIsDirty = ref.fBoundsIsDirty; | 351     fBoundsIsDirty = ref.fBoundsIsDirty; | 
| 294     if (!fBoundsIsDirty) { | 352     if (!fBoundsIsDirty) { | 
| 295         fBounds = ref.fBounds; | 353         fBounds = ref.fBounds; | 
| 296         fIsFinite = ref.fIsFinite; | 354         fIsFinite = ref.fIsFinite; | 
| 297     } | 355     } | 
| 298     fSegmentMask = ref.fSegmentMask; | 356     fSegmentMask = ref.fSegmentMask; | 
| 299     fIsOval = ref.fIsOval; | 357     fIsOval = ref.fIsOval; | 
| 300     fIsRRect = ref.fIsRRect; | 358     fIsRRect = ref.fIsRRect; | 
|  | 359     fRRectOrOvalIsCCW = ref.fRRectOrOvalIsCCW; | 
|  | 360     fRRectOrOvalStartIdx = ref.fRRectOrOvalStartIdx; | 
| 301     SkDEBUGCODE(this->validate();) | 361     SkDEBUGCODE(this->validate();) | 
| 302 } | 362 } | 
| 303 | 363 | 
| 304 | 364 | 
| 305 void SkPathRef::interpolate(const SkPathRef& ending, SkScalar weight, SkPathRef*
      out) const { | 365 void SkPathRef::interpolate(const SkPathRef& ending, SkScalar weight, SkPathRef*
      out) const { | 
| 306     const SkScalar* inValues = &ending.getPoints()->fX; | 366     const SkScalar* inValues = &ending.getPoints()->fX; | 
| 307     SkScalar* outValues = &out->getPoints()->fX; | 367     SkScalar* outValues = &out->getPoints()->fX; | 
| 308     int count = out->countPoints() * 2; | 368     int count = out->countPoints() * 2; | 
| 309     for (int index = 0; index < count; ++index) { | 369     for (int index = 0; index < count; ++index) { | 
| 310         outValues[index] = outValues[index] * weight + inValues[index] * (1 - we
     ight); | 370         outValues[index] = outValues[index] * weight + inValues[index] * (1 - we
     ight); | 
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 669                 break; | 729                 break; | 
| 670             default: | 730             default: | 
| 671                 SkDEBUGFAIL("Unknown Verb"); | 731                 SkDEBUGFAIL("Unknown Verb"); | 
| 672                 break; | 732                 break; | 
| 673         } | 733         } | 
| 674     } | 734     } | 
| 675     SkASSERT(mask == fSegmentMask); | 735     SkASSERT(mask == fSegmentMask); | 
| 676 #endif // SK_DEBUG_PATH | 736 #endif // SK_DEBUG_PATH | 
| 677 } | 737 } | 
| 678 #endif | 738 #endif | 
| OLD | NEW | 
|---|