Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 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 "SkLinearGradient.h" | 8 #include "SkLinearGradient.h" |
| 9 | 9 |
| 10 static const float kInv255Float = 1.0f / 255; | |
|
caryclark
2015/11/16 14:44:29
This is a popular pattern:
src/effects/SkColorMat
| |
| 11 | |
| 10 static inline int repeat_bits(int x, const int bits) { | 12 static inline int repeat_bits(int x, const int bits) { |
| 11 return x & ((1 << bits) - 1); | 13 return x & ((1 << bits) - 1); |
| 12 } | 14 } |
| 13 | 15 |
| 14 static inline int repeat_8bits(int x) { | 16 static inline int repeat_8bits(int x) { |
| 15 return x & 0xFF; | 17 return x & 0xFF; |
| 16 } | 18 } |
| 17 | 19 |
| 18 // Visual Studio 2010 (MSC_VER=1600) optimizes bit-shift code incorrectly. | 20 // Visual Studio 2010 (MSC_VER=1600) optimizes bit-shift code incorrectly. |
| 19 // See http://code.google.com/p/skia/issues/detail?id=472 | 21 // See http://code.google.com/p/skia/issues/detail?id=472 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 79 } | 81 } |
| 80 | 82 |
| 81 size_t SkLinearGradient::contextSize() const { | 83 size_t SkLinearGradient::contextSize() const { |
| 82 return sizeof(LinearGradientContext); | 84 return sizeof(LinearGradientContext); |
| 83 } | 85 } |
| 84 | 86 |
| 85 SkShader::Context* SkLinearGradient::onCreateContext(const ContextRec& rec, void * storage) const { | 87 SkShader::Context* SkLinearGradient::onCreateContext(const ContextRec& rec, void * storage) const { |
| 86 return new (storage) LinearGradientContext(*this, rec); | 88 return new (storage) LinearGradientContext(*this, rec); |
| 87 } | 89 } |
| 88 | 90 |
| 91 static uint32_t SkSwizzle_Color_to_PMColor(SkColor c) { | |
| 92 return SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c), SkColorGetG(c), S kColorGetB(c)); | |
| 93 } | |
| 94 | |
| 89 SkLinearGradient::LinearGradientContext::LinearGradientContext( | 95 SkLinearGradient::LinearGradientContext::LinearGradientContext( |
| 90 const SkLinearGradient& shader, const ContextRec& rec) | 96 const SkLinearGradient& shader, const ContextRec& ctx) |
| 91 : INHERITED(shader, rec) | 97 : INHERITED(shader, ctx) |
| 92 { | 98 { |
| 93 unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; | 99 unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; |
| 94 if ((fDstToIndex.getType() & ~mask) == 0) { | 100 if ((fDstToIndex.getType() & ~mask) == 0) { |
| 95 // when we dither, we are (usually) not const-in-Y | 101 // when we dither, we are (usually) not const-in-Y |
| 96 if ((fFlags & SkShader::kHasSpan16_Flag) && !rec.fPaint->isDither()) { | 102 if ((fFlags & SkShader::kHasSpan16_Flag) && !ctx.fPaint->isDither()) { |
| 97 // only claim this if we do have a 16bit mode (i.e. none of our | 103 // only claim this if we do have a 16bit mode (i.e. none of our |
| 98 // colors have alpha), and if we are not dithering (which obviously | 104 // colors have alpha), and if we are not dithering (which obviously |
| 99 // is not const in Y). | 105 // is not const in Y). |
| 100 fFlags |= SkShader::kConstInY16_Flag; | 106 fFlags |= SkShader::kConstInY16_Flag; |
| 101 } | 107 } |
| 102 } | 108 } |
| 109 | |
| 110 // setup for Sk4f | |
| 111 int count = shader.fColorCount; | |
| 112 fRecs.setCount(count); | |
| 113 Rec* rec = fRecs.begin(); | |
| 114 if (shader.fOrigPos) { | |
| 115 rec[0].fPos = 0; | |
| 116 rec[0].fPosScale = 0; // should never get used | |
|
caryclark
2015/11/16 14:44:29
SkDEBUGCODE() ?
Assign SK_ScalarNaN instead?
reed1
2015/11/16 16:43:33
Done.
| |
| 117 for (int i = 1; i < count; ++i) { | |
| 118 rec[i].fPos = SkTMin(SkTMax(rec[i - 1].fPos, shader.fOrigPos[i]), 1. 0f); | |
|
caryclark
2015/11/16 14:44:29
SkASSERT(rec[i - 1].fPos <= rec[i].fPos);
(see com
| |
| 119 rec[i].fPosScale = 1.0f / (rec[i].fPos - rec[i - 1].fPos); | |
| 120 } | |
| 121 rec[count - 1].fPos = 1; // overwrite the last value just to be sure we end at 1.0 | |
|
caryclark
2015/11/16 14:44:29
This seems odd -- is it OK for the last iteration
caryclark
2015/11/16 14:44:29
SkASSERT(rec[count - 2].fPos <= rec[count - 1].fPo
| |
| 122 } else { | |
| 123 float invScale = 1.0f / (count - 1); | |
| 124 for (int i = 0; i < count; ++i) { | |
| 125 rec[i].fPos = i * invScale; | |
| 126 rec[i].fPosScale = count - 1; | |
| 127 } | |
| 128 } | |
| 129 | |
| 130 fApplyAlphaAfterInterp = true; | |
| 131 if ((shader.getGradFlags() & SkGradientShader::kInterpolateColorsInPremul_Fl ag) || | |
| 132 shader.colorsAreOpaque()) | |
| 133 { | |
| 134 fApplyAlphaAfterInterp = false; | |
| 135 } | |
|
caryclark
2015/11/16 14:44:29
fApplyAlphaAfterInterp = !(shader.getGradFlags() &
| |
| 136 | |
| 137 if (fApplyAlphaAfterInterp) { | |
| 138 const float paintAlpha = ctx.fPaint->getAlpha() * kInv255Float; | |
| 139 const Sk4f scale(1, 1, 1, paintAlpha); | |
| 140 for (int i = 0; i < count; ++i) { | |
| 141 uint32_t c = SkSwizzle_Color_to_PMColor(shader.fOrigColors[i]); | |
| 142 rec[i].fColor = Sk4f::FromBytes((const uint8_t*)&c) * scale; | |
| 143 if (i > 0) { | |
| 144 SkASSERT(rec[i - 1].fPos <= rec[i].fPos); | |
|
caryclark
2015/11/16 14:44:29
this assert looks like it would be more at home ab
| |
| 145 } | |
| 146 } | |
| 147 } else { | |
| 148 unsigned alphaScale = ctx.fPaint->getAlpha() + (ctx.fPaint->getAlpha() > > 7); | |
| 149 for (int i = 0; i < count; ++i) { | |
| 150 SkPMColor pmc = SkPreMultiplyColor(shader.fOrigColors[i]); | |
| 151 pmc = SkAlphaMulQ(pmc, alphaScale); | |
| 152 rec[i].fColor = Sk4f::FromBytes((const uint8_t*)&pmc); | |
| 153 if (i > 0) { | |
| 154 SkASSERT(rec[i - 1].fPos <= rec[i].fPos); | |
|
caryclark
2015/11/16 14:44:29
Ditto
| |
| 155 } | |
| 156 } | |
| 157 } | |
| 103 } | 158 } |
| 104 | 159 |
| 105 #define NO_CHECK_ITER \ | 160 #define NO_CHECK_ITER \ |
| 106 do { \ | 161 do { \ |
| 107 unsigned fi = SkGradFixedToFixed(fx) >> SkGradientShaderBase::kCache32Shift; \ | 162 unsigned fi = SkGradFixedToFixed(fx) >> SkGradientShaderBase::kCache32Shift; \ |
| 108 SkASSERT(fi <= 0xFF); \ | 163 SkASSERT(fi <= 0xFF); \ |
| 109 fx += dx; \ | 164 fx += dx; \ |
| 110 *dstC++ = cache[toggle + fi]; \ | 165 *dstC++ = cache[toggle + fi]; \ |
| 111 toggle = next_dither_toggle(toggle); \ | 166 toggle = next_dither_toggle(toggle); \ |
| 112 } while (0) | 167 } while (0) |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 205 *dstC++ = cache[toggle + fi]; | 260 *dstC++ = cache[toggle + fi]; |
| 206 toggle = next_dither_toggle(toggle); | 261 toggle = next_dither_toggle(toggle); |
| 207 } while (--count != 0); | 262 } while (--count != 0); |
| 208 } | 263 } |
| 209 | 264 |
| 210 } | 265 } |
| 211 | 266 |
| 212 void SkLinearGradient::LinearGradientContext::shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC, | 267 void SkLinearGradient::LinearGradientContext::shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC, |
| 213 int count) { | 268 int count) { |
| 214 SkASSERT(count > 0); | 269 SkASSERT(count > 0); |
| 270 const SkLinearGradient& linearGradient = static_cast<const SkLinearGradient& >(fShader); | |
| 215 | 271 |
| 216 const SkLinearGradient& linearGradient = static_cast<const SkLinearGradient& >(fShader); | 272 #ifndef SK_SUPPORT_LEGACY_LINEAR_GRADIENT_TABLE |
| 273 if (SkShader::kClamp_TileMode == linearGradient.fTileMode && | |
| 274 kLinear_MatrixClass == fDstToIndexClass && | |
| 275 linearGradient.fColorCount > 2) | |
| 276 { | |
| 277 this->shade4_clamp(x, y, dstC, count); | |
| 278 return; | |
| 279 } | |
| 280 #endif | |
| 217 | 281 |
| 218 SkPoint srcPt; | 282 SkPoint srcPt; |
| 219 SkMatrix::MapXYProc dstProc = fDstToIndexProc; | 283 SkMatrix::MapXYProc dstProc = fDstToIndexProc; |
| 220 TileProc proc = linearGradient.fTileProc; | 284 TileProc proc = linearGradient.fTileProc; |
| 221 const SkPMColor* SK_RESTRICT cache = fCache->getCache32(); | 285 const SkPMColor* SK_RESTRICT cache = fCache->getCache32(); |
| 222 int toggle = init_dither_toggle(x, y); | 286 int toggle = init_dither_toggle(x, y); |
| 223 | 287 |
| 224 if (fDstToIndexClass != kPerspective_MatrixClass) { | 288 if (fDstToIndexClass != kPerspective_MatrixClass) { |
| 225 dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf, | 289 dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf, |
| 226 SkIntToScalar(y) + SK_ScalarHalf, &srcPt); | 290 SkIntToScalar(y) + SK_ScalarHalf, &srcPt); |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 569 str->append("SkLinearGradient ("); | 633 str->append("SkLinearGradient ("); |
| 570 | 634 |
| 571 str->appendf("start: (%f, %f)", fStart.fX, fStart.fY); | 635 str->appendf("start: (%f, %f)", fStart.fX, fStart.fY); |
| 572 str->appendf(" end: (%f, %f) ", fEnd.fX, fEnd.fY); | 636 str->appendf(" end: (%f, %f) ", fEnd.fX, fEnd.fY); |
| 573 | 637 |
| 574 this->INHERITED::toString(str); | 638 this->INHERITED::toString(str); |
| 575 | 639 |
| 576 str->append(")"); | 640 str->append(")"); |
| 577 } | 641 } |
| 578 #endif | 642 #endif |
| 643 | |
| 644 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
| 645 | |
| 646 #include "SkNx.h" | |
| 647 | |
| 648 static const SkLinearGradient::LinearGradientContext::Rec* find(float tiledX, | |
| 649 const SkLinearGradient::LinearGradientCo ntext::Rec rec[], | |
| 650 int count) { | |
| 651 SkASSERT(count > 1); | |
| 652 SkASSERT(0 == rec[0].fPos); | |
| 653 SkASSERT(1 == rec[count - 1].fPos); | |
| 654 SkASSERT(tiledX >= 0 && tiledX <= 1); | |
| 655 | |
| 656 int i = 1; | |
| 657 while (rec[i].fPos < tiledX) { | |
| 658 i += 1; | |
| 659 } | |
|
caryclark
2015/11/16 14:44:29
Is this array ever so large that it's worth a non-
reed1
2015/11/16 16:43:33
Could be (though my guess is it is usually between
| |
| 660 return &rec[i - 1]; | |
| 661 } | |
| 662 | |
| 663 template <bool apply_alpha> SkPMColor trunc_from_255(Sk4f x) { | |
| 664 SkPMColor c; | |
| 665 x.toBytes((uint8_t*)&c); | |
| 666 if (apply_alpha) { | |
| 667 c = SkPreMultiplyARGB(SkGetPackedA32(c), SkGetPackedR32(c), | |
| 668 SkGetPackedG32(c), SkGetPackedB32(c)); | |
| 669 } | |
| 670 return c; | |
| 671 } | |
| 672 | |
| 673 template <bool apply_alpha> void fill(SkPMColor dst[], int count, Sk4f c4, Sk4f c4other) { | |
| 674 sk_memset32_dither(dst, trunc_from_255<apply_alpha>(c4), | |
| 675 trunc_from_255<apply_alpha>(c4other), count); | |
| 676 } | |
| 677 | |
| 678 /* | |
| 679 * TODOs | |
| 680 * | |
| 681 * - tilemodes | |
| 682 * - interp before or after premul | |
| 683 * - perspective | |
| 684 * - optimizations | |
|
f(malita)
2015/11/16 15:16:20
How does current perf compare to existing impl?
reed1
2015/11/16 16:43:33
Slower, by 10-20% depending.
| |
| 685 * - use fixed (32bit or 16bit) instead of floats? | |
| 686 */ | |
| 687 | |
| 688 static Sk4f lerp_color(float fx, const SkLinearGradient::LinearGradientContext:: Rec* rec) { | |
| 689 const float p0 = rec[0].fPos; | |
| 690 const Sk4f c0 = rec[0].fColor; | |
| 691 const Sk4f c1 = rec[1].fColor; | |
| 692 const Sk4f diffc = c1 - c0; | |
| 693 const float scale = rec[1].fPosScale; | |
| 694 const float t = (fx - p0) * scale; | |
| 695 return c0 + Sk4f(t) * diffc; | |
| 696 } | |
| 697 | |
| 698 template <bool apply_alpha> void ramp(SkPMColor dstC[], int n, Sk4f c, Sk4f dc, | |
| 699 Sk4f dither0, Sk4f dither1) { | |
| 700 Sk4f dc2 = dc + dc; | |
| 701 Sk4f dc4 = dc2 + dc2; | |
| 702 Sk4f cd0 = c + dither0; | |
| 703 Sk4f cd1 = c + dc + dither1; | |
| 704 Sk4f cd2 = cd0 + dc2; | |
| 705 Sk4f cd3 = cd1 + dc2; | |
| 706 while (n >= 4) { | |
| 707 *dstC++ = trunc_from_255<apply_alpha>(cd0); | |
| 708 *dstC++ = trunc_from_255<apply_alpha>(cd1); | |
| 709 *dstC++ = trunc_from_255<apply_alpha>(cd2); | |
| 710 *dstC++ = trunc_from_255<apply_alpha>(cd3); | |
|
caryclark
2015/11/16 14:44:29
probably not worth it, but
if (n >= 4) {
do {
reed1
2015/11/16 16:43:33
Good observation. But it took me a full minute to
| |
| 711 cd0 = cd0 + dc4; | |
| 712 cd1 = cd1 + dc4; | |
| 713 cd2 = cd2 + dc4; | |
| 714 cd3 = cd3 + dc4; | |
| 715 n -= 4; | |
| 716 } | |
| 717 if (n & 2) { | |
| 718 *dstC++ = trunc_from_255<apply_alpha>(cd0); | |
| 719 *dstC++ = trunc_from_255<apply_alpha>(cd1); | |
| 720 cd0 = cd0 + dc2; | |
|
caryclark
2015/11/16 14:44:29
move this into the condition below?
| |
| 721 } | |
| 722 if (n & 1) { | |
| 723 *dstC++ = trunc_from_255<apply_alpha>(cd0); | |
| 724 } | |
| 725 } | |
| 726 | |
| 727 template <bool apply_alpha> void SkLinearGradient::LinearGradientContext::shade4 _pos_clamp( | |
| 728 SkPMColor dstC[], int count, | |
| 729 float fx, float d x, float invDx, | |
| 730 Sk4f dither0, Sk4 f dither1) { | |
| 731 const Rec* rec = fRecs.begin(); | |
| 732 | |
| 733 const Sk4f dx4 = Sk4f(dx); | |
| 734 SkDEBUGCODE(SkPMColor* endDstC = dstC + count;) | |
| 735 | |
| 736 if (fx < 0) { | |
| 737 int n = SkTMin(SkFloatToIntFloor(-fx * invDx) + 1, count); | |
| 738 fill<apply_alpha>(dstC, n, rec[0].fColor + dither0, rec[0].fColor + dith er1); | |
| 739 count -= n; | |
| 740 SkASSERT(count >= 0); | |
| 741 dstC += n; | |
| 742 fx += n * dx; | |
| 743 SkASSERT(0 == count || fx >= 0); | |
| 744 if (n & 1) { | |
| 745 SkTSwap(dither0, dither1); | |
| 746 } | |
| 747 } | |
| 748 | |
| 749 while (count > 0) { | |
| 750 if (fx >= 1) { | |
| 751 Sk4f color = rec[fRecs.count() - 1].fColor; | |
| 752 fill<apply_alpha>(dstC, count, color + dither0, color + dither1); | |
| 753 return; | |
| 754 } | |
| 755 | |
| 756 const Rec* r = find(fx, rec, fRecs.count()); | |
|
caryclark
2015/11/16 14:44:29
add
const float p0 = r[0].fPos;
to mirr
f(malita)
2015/11/16 15:16:20
Since we're peeking at r[1] below, I would SkASSER
reed1
2015/11/16 17:31:24
Done.
reed1
2015/11/16 17:31:24
Done.
| |
| 757 const Sk4f c0 = r[0].fColor; | |
| 758 const Sk4f diffc = r[1].fColor - c0; | |
| 759 const float scale = r[1].fPosScale; | |
| 760 const float t = (fx - r[0].fPos) * scale; | |
|
caryclark
2015/11/16 14:44:29
const float t = (fx - p0) * scale;
| |
| 761 Sk4f c = c0 + Sk4f(t) * diffc; | |
| 762 | |
| 763 const Sk4f dc = diffc * dx4 * Sk4f(scale); | |
| 764 const float p1 = r[1].fPos; | |
| 765 | |
| 766 int n = SkTMin((int)((p1-fx)*invDx) + 1, count); | |
|
caryclark
2015/11/16 14:44:29
Is this the same as the SkFloatToIntFloor in the <
| |
| 767 | |
| 768 fx += n * dx; | |
| 769 count -= n; | |
| 770 SkASSERT(0 == count || fx >= p1); | |
| 771 SkASSERT(count >= 0); | |
|
caryclark
2015/11/16 14:44:29
may be worth changing either the <0 condition or t
| |
| 772 | |
| 773 ramp<apply_alpha>(dstC, n, c, dc, dither0, dither1); | |
| 774 dstC += n; | |
| 775 SkASSERT(dstC <= endDstC); | |
| 776 | |
| 777 if (n & 1) { | |
| 778 SkTSwap(dither0, dither1); | |
| 779 } | |
| 780 } | |
| 781 } | |
| 782 | |
| 783 template <bool apply_alpha>void SkLinearGradient::LinearGradientContext::shade4_ neg_clamp( | |
|
f(malita)
2015/11/16 15:16:20
shade4_neg_clamp & shade4_pos_clamp look pretty si
| |
| 784 SkPMColor dstC[], int count, | |
| 785 float fx, float d x, float invDx, | |
| 786 Sk4f dither0, Sk4 f dither1) { | |
| 787 const Rec* rec = fRecs.begin(); | |
| 788 | |
| 789 const Sk4f dx4 = Sk4f(dx); | |
| 790 SkDEBUGCODE(SkPMColor* endDstC = dstC + count;) | |
| 791 | |
| 792 if (fx > 1) { | |
| 793 int n = SkTMin(SkFloatToIntFloor((1 - fx) * invDx) + 1, count); | |
| 794 Sk4f c = rec[fRecs.count() - 1].fColor; | |
| 795 fill<apply_alpha>(dstC, n, c + dither0, c + dither1); | |
| 796 count -= n; | |
| 797 SkASSERT(count >= 0); | |
| 798 dstC += n; | |
| 799 fx += n * dx; | |
| 800 SkASSERT(0 == count || fx <= 1); | |
| 801 if (n & 1) { | |
| 802 SkTSwap(dither0, dither1); | |
| 803 } | |
| 804 } | |
| 805 | |
| 806 while (count > 0) { | |
| 807 if (fx <= 0) { | |
| 808 fill<apply_alpha>(dstC, count, rec[0].fColor + dither0, rec[0].fColo r + dither1); | |
|
caryclark
2015/11/16 14:44:29
maybe
Sk4f color = rec[0].fColor;
reed1
2015/11/16 16:43:33
Done.
| |
| 809 return; | |
| 810 } | |
| 811 | |
| 812 const Rec* r = find(fx, rec, fRecs.count()); | |
| 813 const float p0 = r[0].fPos; | |
| 814 const Sk4f c0 = r[0].fColor; | |
| 815 const Sk4f diffc = r[1].fColor - c0; | |
| 816 const float scale = r[1].fPosScale; | |
| 817 const float t = (fx - p0) * scale; | |
| 818 Sk4f c = c0 + Sk4f(t) * diffc; | |
| 819 | |
| 820 const Sk4f dc = diffc * dx4 * Sk4f(scale); | |
| 821 | |
| 822 int n = SkTMin((int)((p0 - fx)*invDx) + 1, count); | |
| 823 | |
| 824 fx += n * dx; | |
| 825 count -= n; | |
| 826 SkASSERT(0 == count || fx <= p0); | |
| 827 SkASSERT(count >= 0); | |
| 828 | |
| 829 ramp<apply_alpha>(dstC, n, c, dc, dither0, dither1); | |
| 830 dstC += n; | |
| 831 SkASSERT(dstC <= endDstC); | |
| 832 | |
| 833 if (n & 1) { | |
| 834 SkTSwap(dither0, dither1); | |
| 835 } | |
| 836 } | |
| 837 } | |
| 838 | |
| 839 void SkLinearGradient::LinearGradientContext::shade4_clamp(int x, int y, SkPMCol or dstC[], | |
| 840 int count) { | |
| 841 SkASSERT(count > 0); | |
| 842 SkASSERT(kLinear_MatrixClass == fDstToIndexClass); | |
| 843 | |
| 844 SkPoint srcPt; | |
| 845 fDstToIndexProc(fDstToIndex, x + SK_ScalarHalf, y + SK_ScalarHalf, &srcPt); | |
| 846 float fx = srcPt.x(); | |
| 847 const float dx = fDstToIndex.getScaleX(); | |
| 848 | |
| 849 Sk4f dither0, dither1; | |
| 850 if (fDither) { | |
| 851 // [ 1/8 5/8 ] | |
| 852 // [ 7/8 3/8 ] | |
| 853 const float ditherCell[] = { | |
| 854 0.125f, 0.625f, | |
| 855 0.875f, 0.375f, | |
| 856 }; | |
|
caryclark
2015/11/16 14:44:29
Out of curiosity, could this be
1.0
reed1
2015/11/16 16:43:33
Very good idea. Done.
| |
| 857 const int rowIndex = (y & 1) << 1; | |
| 858 dither0 = Sk4f(ditherCell[rowIndex]); | |
| 859 dither1 = Sk4f(ditherCell[rowIndex + 1]); | |
| 860 } else { | |
| 861 dither0 = dither1 = Sk4f(0.5f); | |
| 862 } | |
| 863 | |
| 864 const float invDx = 1 / dx; | |
| 865 | |
| 866 if (!SkScalarIsFinite(invDx)) { // dx is effectively zero, gradient is verti cal | |
| 867 fx = SkTMin(SkTMax(fx, 0.0f), 1.0f); | |
|
caryclark
2015/11/16 14:44:28
SkTPin(fx, 0.0f, 1.0f)
reed1
2015/11/16 16:43:33
Done.
| |
| 868 Sk4f c = lerp_color(fx, find(fx, fRecs.begin(), fRecs.count())); | |
| 869 if (fApplyAlphaAfterInterp) { | |
| 870 fill<true>(dstC, count, c + dither0, c + dither1); | |
| 871 } else { | |
| 872 fill<false>(dstC, count, c + dither0, c + dither1); | |
| 873 } | |
| 874 return; | |
| 875 } | |
| 876 | |
| 877 if (dx > 0) { | |
| 878 if (fApplyAlphaAfterInterp) { | |
| 879 this->shade4_pos_clamp<true>(dstC, count, fx, dx, invDx, dither0, di ther1); | |
| 880 } else { | |
| 881 this->shade4_pos_clamp<false>(dstC, count, fx, dx, invDx, dither0, d ither1); | |
| 882 } | |
| 883 } else { | |
| 884 if (fApplyAlphaAfterInterp) { | |
| 885 this->shade4_neg_clamp<true>(dstC, count, fx, dx, invDx, dither0, di ther1); | |
| 886 } else { | |
| 887 this->shade4_neg_clamp<false>(dstC, count, fx, dx, invDx, dither0, d ither1); | |
| 888 } | |
| 889 } | |
| 890 } | |
| 891 | |
| OLD | NEW |