Index: src/effects/gradients/SkGradientShader.cpp |
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp |
index 78cdb80d559c34f127ce48bdb95191557d50e0bf..58c0d3bd5dcc2aaa8a266a7ef23141255e895b40 100644 |
--- a/src/effects/gradients/SkGradientShader.cpp |
+++ b/src/effects/gradients/SkGradientShader.cpp |
@@ -767,12 +767,61 @@ static void desc_init(SkGradientShaderBase::Descriptor* desc, |
} \ |
} while (0) |
+struct ColorStopOptimizer { |
+ ColorStopOptimizer(const SkColor* colors, const SkScalar* pos, |
+ int count, SkShader::TileMode mode) |
+ : fColors(colors) |
+ , fPos(pos) |
+ , fCount(count) { |
+ |
+ if (!pos || count != 3) { |
+ return; |
+ } |
+ |
+ if (SkScalarNearlyEqual(pos[0], 0.0f) && |
+ SkScalarNearlyEqual(pos[1], 0.0f) && |
+ SkScalarNearlyEqual(pos[2], 1.0f)) { |
+ |
+ if (SkShader::kRepeat_TileMode == mode || |
+ SkShader::kMirror_TileMode == mode || |
+ colors[0] == colors[1]) { |
+ |
+ fColorStorage[0] = colors[1]; |
+ fColorStorage[1] = colors[2]; |
+ fPosStorage[0] = 0.0f; |
+ fPosStorage[1] = 1.0f; |
+ |
+ fColors = fColorStorage; |
+ fPos = fPosStorage; |
+ fCount = 2; |
+ } |
+ } else if (SkScalarNearlyEqual(pos[0], 0.0f) && |
+ SkScalarNearlyEqual(pos[1], 1.0f) && |
+ SkScalarNearlyEqual(pos[2], 1.0f)) { |
+ |
+ if (SkShader::kRepeat_TileMode == mode || |
+ SkShader::kMirror_TileMode == mode || |
+ colors[1] == colors[2]) { |
+ |
+ fCount = 2; |
+ } |
+ } |
+ } |
+ |
+ const SkColor* fColors; |
+ const SkScalar* fPos; |
+ int fCount; |
+ |
+ SkColor fColorStorage[2]; |
+ SkScalar fPosStorage[2]; |
+}; |
+ |
sk_sp<SkShader> SkGradientShader::MakeLinear(const SkPoint pts[2], |
- const SkColor colors[], |
- const SkScalar pos[], int colorCount, |
- SkShader::TileMode mode, |
- uint32_t flags, |
- const SkMatrix* localMatrix) { |
+ const SkColor colors[], |
+ const SkScalar pos[], int colorCount, |
+ SkShader::TileMode mode, |
+ uint32_t flags, |
+ const SkMatrix* localMatrix) { |
if (!pts || !SkScalarIsFinite((pts[1] - pts[0]).length())) { |
return nullptr; |
} |
@@ -783,8 +832,10 @@ sk_sp<SkShader> SkGradientShader::MakeLinear(const SkPoint pts[2], |
return SkShader::MakeColorShader(colors[0]); |
} |
+ ColorStopOptimizer opt(colors, pos, colorCount, mode); |
+ |
SkGradientShaderBase::Descriptor desc; |
- desc_init(&desc, colors, pos, colorCount, mode, flags, localMatrix); |
+ desc_init(&desc, opt.fColors, opt.fPos, opt.fCount, mode, flags, localMatrix); |
return sk_make_sp<SkLinearGradient>(pts, desc); |
} |
@@ -804,8 +855,10 @@ sk_sp<SkShader> SkGradientShader::MakeRadial(const SkPoint& center, SkScalar rad |
return SkShader::MakeColorShader(colors[0]); |
} |
+ ColorStopOptimizer opt(colors, pos, colorCount, mode); |
+ |
SkGradientShaderBase::Descriptor desc; |
- desc_init(&desc, colors, pos, colorCount, mode, flags, localMatrix); |
+ desc_init(&desc, opt.fColors, opt.fPos, opt.fCount, mode, flags, localMatrix); |
return sk_make_sp<SkRadialGradient>(center, radius, desc); |
} |
@@ -832,24 +885,26 @@ sk_sp<SkShader> SkGradientShader::MakeTwoPointConical(const SkPoint& start, |
} |
EXPAND_1_COLOR(colorCount); |
+ ColorStopOptimizer opt(colors, pos, colorCount, mode); |
+ |
bool flipGradient = startRadius > endRadius; |
SkGradientShaderBase::Descriptor desc; |
if (!flipGradient) { |
- desc_init(&desc, colors, pos, colorCount, mode, flags, localMatrix); |
+ desc_init(&desc, opt.fColors, opt.fPos, opt.fCount, mode, flags, localMatrix); |
return sk_make_sp<SkTwoPointConicalGradient>(start, startRadius, end, endRadius, |
flipGradient, desc); |
} else { |
SkAutoSTArray<8, SkColor> colorsNew(colorCount); |
SkAutoSTArray<8, SkScalar> posNew(colorCount); |
for (int i = 0; i < colorCount; ++i) { |
- colorsNew[i] = colors[colorCount - i - 1]; |
+ colorsNew[i] = opt.fColors[colorCount - i - 1]; |
} |
if (pos) { |
for (int i = 0; i < colorCount; ++i) { |
- posNew[i] = 1 - pos[colorCount - i - 1]; |
+ posNew[i] = 1 - opt.fPos[colorCount - i - 1]; |
} |
desc_init(&desc, colorsNew.get(), posNew.get(), colorCount, mode, flags, localMatrix); |
} else { |
@@ -874,8 +929,12 @@ sk_sp<SkShader> SkGradientShader::MakeSweep(SkScalar cx, SkScalar cy, |
return SkShader::MakeColorShader(colors[0]); |
} |
+ auto mode = SkShader::kClamp_TileMode; |
+ |
+ ColorStopOptimizer opt(colors, pos, colorCount, mode); |
+ |
SkGradientShaderBase::Descriptor desc; |
- desc_init(&desc, colors, pos, colorCount, SkShader::kClamp_TileMode, flags, localMatrix); |
+ desc_init(&desc, opt.fColors, opt.fPos, opt.fCount, mode, flags, localMatrix); |
return sk_make_sp<SkSweepGradient>(cx, cy, desc); |
} |