Chromium Code Reviews| 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 "SkDashPathEffect.h" | 10 #include "SkDashPathEffect.h" |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 27 } | 27 } |
| 28 } | 28 } |
| 29 // If we get here, phase "appears" to be larger than our length. This | 29 // If we get here, phase "appears" to be larger than our length. This |
| 30 // shouldn't happen with perfect precision, but we can accumulate errors | 30 // shouldn't happen with perfect precision, but we can accumulate errors |
| 31 // during the initial length computation (rounding can make our sum be too | 31 // during the initial length computation (rounding can make our sum be too |
| 32 // big or too small. In that event, we just have to eat the error here. | 32 // big or too small. In that event, we just have to eat the error here. |
| 33 *index = 0; | 33 *index = 0; |
| 34 return intervals[0]; | 34 return intervals[0]; |
| 35 } | 35 } |
| 36 | 36 |
| 37 SkDashPathEffect::SkDashPathEffect(const SkScalar intervals[], int count, | 37 void SkDashPathEffect::setInternalMembers(SkScalar phase) { |
| 38 SkScalar phase, bool scaleToFit) | |
| 39 : fScaleToFit(scaleToFit) { | |
| 40 SkASSERT(intervals); | |
| 41 SkASSERT(count > 1 && SkAlign2(count) == count); | |
| 42 | |
| 43 fIntervals = (SkScalar*)sk_malloc_throw(sizeof(SkScalar) * count); | |
| 44 fCount = count; | |
| 45 | |
| 46 SkScalar len = 0; | 38 SkScalar len = 0; |
| 47 for (int i = 0; i < count; i++) { | 39 for (int i = 0; i < fCount; i++) { |
| 48 SkASSERT(intervals[i] >= 0); | 40 len += fIntervals[i]; |
| 49 fIntervals[i] = intervals[i]; | |
| 50 len += intervals[i]; | |
| 51 } | 41 } |
| 52 fIntervalLength = len; | 42 fIntervalLength = len; |
| 53 | 43 |
| 54 // watch out for values that might make us go out of bounds | 44 // watch out for values that might make us go out of bounds |
| 55 if ((len > 0) && SkScalarIsFinite(phase) && SkScalarIsFinite(len)) { | 45 if ((len > 0) && SkScalarIsFinite(phase) && SkScalarIsFinite(len)) { |
| 56 | 46 |
| 57 // Adjust phase to be between 0 and len, "flipping" phase if negative. | 47 // Adjust phase to be between 0 and len, "flipping" phase if negative. |
| 58 // e.g., if len is 100, then phase of -20 (or -120) is equivalent to 80 | 48 // e.g., if len is 100, then phase of -20 (or -120) is equivalent to 80 |
| 59 if (phase < 0) { | 49 if (phase < 0) { |
| 60 phase = -phase; | 50 phase = -phase; |
| 61 if (phase > len) { | 51 if (phase > len) { |
| 62 phase = SkScalarMod(phase, len); | 52 phase = SkScalarMod(phase, len); |
| 63 } | 53 } |
| 64 phase = len - phase; | 54 phase = len - phase; |
| 65 | 55 |
| 66 // Due to finite precision, it's possible that phase == len, | 56 // Due to finite precision, it's possible that phase == len, |
| 67 // even after the subtract (if len >>> phase), so fix that here. | 57 // even after the subtract (if len >>> phase), so fix that here. |
| 68 // This fixes http://crbug.com/124652 . | 58 // This fixes http://crbug.com/124652 . |
| 69 SkASSERT(phase <= len); | 59 SkASSERT(phase <= len); |
| 70 if (phase == len) { | 60 if (phase == len) { |
| 71 phase = 0; | 61 phase = 0; |
| 72 } | 62 } |
| 73 } else if (phase >= len) { | 63 } else if (phase >= len) { |
| 74 phase = SkScalarMod(phase, len); | 64 phase = SkScalarMod(phase, len); |
| 75 } | 65 } |
| 76 SkASSERT(phase >= 0 && phase < len); | 66 SkASSERT(phase >= 0 && phase < len); |
| 77 | 67 |
| 78 fInitialDashLength = FindFirstInterval(intervals, phase, | 68 fPhase = phase; |
| 79 &fInitialDashIndex, count); | 69 |
| 70 fInitialDashLength = FindFirstInterval(fIntervals, fPhase, | |
| 71 &fInitialDashIndex, fCount); | |
| 80 | 72 |
| 81 SkASSERT(fInitialDashLength >= 0); | 73 SkASSERT(fInitialDashLength >= 0); |
| 82 SkASSERT(fInitialDashIndex >= 0 && fInitialDashIndex < fCount); | 74 SkASSERT(fInitialDashIndex >= 0 && fInitialDashIndex < fCount); |
| 83 } else { | 75 } else { |
| 84 fInitialDashLength = -1; // signal bad dash intervals | 76 fInitialDashLength = -1; // signal bad dash intervals |
| 85 } | 77 } |
| 86 } | 78 } |
| 87 | 79 |
| 80 SkDashPathEffect::SkDashPathEffect(const SkScalar intervals[], int count, | |
| 81 SkScalar phase, bool scaleToFit) | |
| 82 : fScaleToFit(scaleToFit) { | |
| 83 SkASSERT(intervals); | |
| 84 SkASSERT(count > 1 && SkAlign2(count) == count); | |
| 85 | |
| 86 fIntervals = (SkScalar*)sk_malloc_throw(sizeof(SkScalar) * count); | |
| 87 fCount = count; | |
| 88 for (int i = 0; i < count; i++) { | |
| 89 SkASSERT(intervals[i] >= 0); | |
| 90 fIntervals[i] = intervals[i]; | |
| 91 } | |
| 92 | |
| 93 this->setInternalMembers(phase); | |
| 94 } | |
| 95 | |
| 88 SkDashPathEffect::~SkDashPathEffect() { | 96 SkDashPathEffect::~SkDashPathEffect() { |
| 89 sk_free(fIntervals); | 97 sk_free(fIntervals); |
| 90 } | 98 } |
| 91 | 99 |
| 92 static void outset_for_stroke(SkRect* rect, const SkStrokeRec& rec) { | 100 static void outset_for_stroke(SkRect* rect, const SkStrokeRec& rec) { |
| 93 SkScalar radius = SkScalarHalf(rec.getWidth()); | 101 SkScalar radius = SkScalarHalf(rec.getWidth()); |
| 94 if (0 == radius) { | 102 if (0 == radius) { |
| 95 radius = SK_Scalar1; // hairlines | 103 radius = SK_Scalar1; // hairlines |
| 96 } | 104 } |
| 97 if (SkPaint::kMiter_Join == rec.getJoin()) { | 105 if (SkPaint::kMiter_Join == rec.getJoin()) { |
| (...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 522 results->fLast.addRect(x - halfWidth, y - halfHeight, | 530 results->fLast.addRect(x - halfWidth, y - halfHeight, |
| 523 x + halfWidth, y + halfHeight); | 531 x + halfWidth, y + halfHeight); |
| 524 } | 532 } |
| 525 | 533 |
| 526 SkASSERT(curPt == results->fNumPoints); | 534 SkASSERT(curPt == results->fNumPoints); |
| 527 } | 535 } |
| 528 | 536 |
| 529 return true; | 537 return true; |
| 530 } | 538 } |
| 531 | 539 |
| 540 SkPathEffect::DashType SkDashPathEffect::asADash(DashInfo* info) const { | |
| 541 if (info) { | |
| 542 if (info->fCount >= fCount) { | |
| 543 if (info->fIntervals) { | |
| 544 memcpy(info->fIntervals, fIntervals, fCount * sizeof(SkScalar)); | |
| 545 } | |
| 546 } | |
| 547 info->fCount = fCount; | |
| 548 info->fPhase = fPhase; | |
| 549 info->fScaleToFit = fScaleToFit; | |
| 550 } | |
| 551 return kDash_DashType; | |
| 552 } | |
| 553 | |
| 554 #define NEW_FLATTEN_VERSION 123 | |
| 555 | |
| 532 SkFlattenable::Factory SkDashPathEffect::getFactory() const { | 556 SkFlattenable::Factory SkDashPathEffect::getFactory() const { |
| 533 return CreateProc; | 557 return CreateProc; |
| 534 } | 558 } |
| 535 | 559 |
| 536 void SkDashPathEffect::flatten(SkWriteBuffer& buffer) const { | 560 void SkDashPathEffect::flatten(SkWriteBuffer& buffer) const { |
| 537 this->INHERITED::flatten(buffer); | 561 this->INHERITED::flatten(buffer); |
| 538 buffer.writeInt(fInitialDashIndex); | 562 if (buffer.pictureVersion() < NEW_FLATTEN_VERSION) { |
|
bsalomon
2014/03/28 14:57:22
Do we need this? Will we ever write an old picture
| |
| 539 buffer.writeScalar(fInitialDashLength); | 563 buffer.writeInt(fInitialDashIndex); |
| 540 buffer.writeScalar(fIntervalLength); | 564 buffer.writeScalar(fInitialDashLength); |
| 565 buffer.writeScalar(fIntervalLength); | |
| 566 } else { | |
| 567 buffer.writeScalar(fPhase); | |
| 568 } | |
| 541 buffer.writeBool(fScaleToFit); | 569 buffer.writeBool(fScaleToFit); |
| 542 buffer.writeScalarArray(fIntervals, fCount); | 570 buffer.writeScalarArray(fIntervals, fCount); |
| 543 } | 571 } |
| 544 | 572 |
| 545 SkFlattenable* SkDashPathEffect::CreateProc(SkReadBuffer& buffer) { | 573 SkFlattenable* SkDashPathEffect::CreateProc(SkReadBuffer& buffer) { |
| 546 return SkNEW_ARGS(SkDashPathEffect, (buffer)); | 574 return SkNEW_ARGS(SkDashPathEffect, (buffer)); |
| 547 } | 575 } |
| 548 | 576 |
| 549 SkDashPathEffect::SkDashPathEffect(SkReadBuffer& buffer) : INHERITED(buffer) { | 577 SkDashPathEffect::SkDashPathEffect(SkReadBuffer& buffer) : INHERITED(buffer) { |
| 550 fInitialDashIndex = buffer.readInt(); | 578 if (buffer.pictureVersion() < NEW_FLATTEN_VERSION) { |
| 551 fInitialDashLength = buffer.readScalar(); | 579 fInitialDashIndex = buffer.readInt(); |
| 552 fIntervalLength = buffer.readScalar(); | 580 fInitialDashLength = buffer.readScalar(); |
| 581 fIntervalLength = buffer.readScalar(); | |
| 582 } else { | |
| 583 fPhase = buffer.readScalar(); | |
| 584 } | |
| 585 | |
| 553 fScaleToFit = buffer.readBool(); | 586 fScaleToFit = buffer.readBool(); |
| 554 | 587 |
| 555 fCount = buffer.getArrayCount(); | 588 fCount = buffer.getArrayCount(); |
| 556 size_t allocSize = sizeof(SkScalar) * fCount; | 589 size_t allocSize = sizeof(SkScalar) * fCount; |
| 557 if (buffer.validateAvailable(allocSize)) { | 590 if (buffer.validateAvailable(allocSize)) { |
| 558 fIntervals = (SkScalar*)sk_malloc_throw(allocSize); | 591 fIntervals = (SkScalar*)sk_malloc_throw(allocSize); |
| 559 buffer.readScalarArray(fIntervals, fCount); | 592 buffer.readScalarArray(fIntervals, fCount); |
| 560 } else { | 593 } else { |
| 561 fIntervals = NULL; | 594 fIntervals = NULL; |
| 562 } | 595 } |
| 596 | |
| 597 if (buffer.pictureVersion() < NEW_FLATTEN_VERSION) { | |
| 598 fPhase = 0.0; | |
| 599 for (int i = 0; i < fInitialDashIndex; ++i) { | |
| 600 fPhase += fIntervals[i]; | |
| 601 } | |
| 602 fPhase += fInitialDashLength; | |
| 603 } else { | |
| 604 this->setInternalMembers(fPhase); | |
| 605 } | |
| 563 } | 606 } |
| OLD | NEW |