Index: src/effects/gradients/SkGradientShader.cpp |
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp |
index 3b761a51cadabba2175375df9b5292f66470c344..460b10111f84699efee298be7766a74ec9666b8a 100644 |
--- a/src/effects/gradients/SkGradientShader.cpp |
+++ b/src/effects/gradients/SkGradientShader.cpp |
@@ -755,12 +755,57 @@ static void desc_init(SkGradientShaderBase::Descriptor* desc, |
desc->fLocalMatrix = localMatrix; |
} |
+static int simplify(SkScalar* pos, SkColor* colors, int colorCount, SkShader::TileMode mode) { |
+ if (pos) { |
+ if (3 == colorCount) { |
+ // Left-edged hard stop gradients (0, 0, 1) can be simplified |
+ // to a 2-color gradient if first two colors are the same |
+ if (SkScalarNearlyEqual(pos[0], 0.0f) && |
+ SkScalarNearlyEqual(pos[1], 0.0f) && |
+ SkScalarNearlyEqual(pos[2], 1.0f)) { |
+ |
+ // If the tile mode is repeat or mirror, first color |
+ // doesn't matter |
+ if (SkShader::kRepeat_TileMode == mode || |
+ SkShader::kMirror_TileMode == mode || |
+ colors[0] == colors[1]) { |
+ |
+ pos[0] = 0.0f; |
+ pos[1] = 1.0f; |
+ |
+ colors[0] = colors[1]; |
+ colors[1] = colors[2]; |
+ |
+ colorCount = 2; |
f(malita)
2016/08/18 22:54:17
If we fall through here, I think we'll also take t
|
+ } |
+ } |
+ |
+ // Right-edged hard stop gradients (0, 1, 1) can be simplified |
+ // to a 2-color gradient if last two colors are the same |
+ if (SkScalarNearlyEqual(pos[0], 0.0f) && |
+ SkScalarNearlyEqual(pos[1], 1.0f) && |
+ SkScalarNearlyEqual(pos[2], 1.0f)) { |
+ |
+ // If the tile mode is repeat or mirror, last color |
+ // doesn't matter |
+ if (SkShader::kRepeat_TileMode == mode || |
+ SkShader::kMirror_TileMode == mode || |
+ colors[1] == colors[2]) { |
+ |
+ colorCount = 2; |
+ } |
+ } |
+ } |
+ } |
+ return colorCount; |
+} |
+ |
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; |
} |
@@ -771,8 +816,22 @@ sk_sp<SkShader> SkGradientShader::MakeLinear(const SkPoint pts[2], |
return SkShader::MakeColorShader(colors[0]); |
} |
+ SkAutoTArray<SkScalar> simplifiedPos(colorCount); |
+ SkAutoTArray<SkColor> simplifiedCol(colorCount); |
+ for (int i = 0; i < colorCount; i++) { |
+ simplifiedCol[i] = colors[i]; |
+ } |
+ if (pos) { |
+ for (int i = 0; i < colorCount; i++) { |
+ simplifiedPos[i] = pos[i]; |
+ } |
+ colorCount = simplify(simplifiedPos.get(), simplifiedCol.get(), colorCount, mode); |
+ } else { |
+ simplifiedPos.reset(0); |
+ } |
f(malita)
2016/08/18 22:54:17
It would be nice to
a) avoid these allocations an
|
+ |
SkGradientShaderBase::Descriptor desc; |
- desc_init(&desc, colors, pos, colorCount, mode, flags, localMatrix); |
+ desc_init(&desc, simplifiedCol.get(), simplifiedPos.get(), colorCount, mode, flags, localMatrix); |
return sk_make_sp<SkLinearGradient>(pts, desc); |
} |
@@ -792,8 +851,22 @@ sk_sp<SkShader> SkGradientShader::MakeRadial(const SkPoint& center, SkScalar rad |
return SkShader::MakeColorShader(colors[0]); |
} |
+ SkAutoTArray<SkScalar> simplifiedPos(colorCount); |
+ SkAutoTArray<SkColor> simplifiedCol(colorCount); |
+ for (int i = 0; i < colorCount; i++) { |
+ simplifiedCol[i] = colors[i]; |
+ } |
+ if (pos) { |
+ for (int i = 0; i < colorCount; i++) { |
+ simplifiedPos[i] = pos[i]; |
+ } |
+ colorCount = simplify(simplifiedPos.get(), simplifiedCol.get(), colorCount, mode); |
+ } else { |
+ simplifiedPos.reset(0); |
+ } |
+ |
SkGradientShaderBase::Descriptor desc; |
- desc_init(&desc, colors, pos, colorCount, mode, flags, localMatrix); |
+ desc_init(&desc, simplifiedCol.get(), simplifiedPos.get(), colorCount, mode, flags, localMatrix); |
return sk_make_sp<SkRadialGradient>(center, radius, desc); |
} |
@@ -822,24 +895,38 @@ sk_sp<SkShader> SkGradientShader::MakeTwoPointConical(const SkPoint& start, |
return SkShader::MakeColorShader(colors[0]); |
} |
+ SkAutoTArray<SkScalar> simplifiedPos(colorCount); |
+ SkAutoTArray<SkColor> simplifiedCol(colorCount); |
+ for (int i = 0; i < colorCount; i++) { |
+ simplifiedCol[i] = colors[i]; |
+ } |
+ if (pos) { |
+ for (int i = 0; i < colorCount; i++) { |
+ simplifiedPos[i] = pos[i]; |
+ } |
+ colorCount = simplify(simplifiedPos.get(), simplifiedCol.get(), colorCount, mode); |
+ } else { |
+ simplifiedPos.reset(0); |
+ } |
+ |
bool flipGradient = startRadius > endRadius; |
SkGradientShaderBase::Descriptor desc; |
if (!flipGradient) { |
- desc_init(&desc, colors, pos, colorCount, mode, flags, localMatrix); |
+ desc_init(&desc, simplifiedCol.get(), simplifiedPos.get(), colorCount, 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] = simplifiedCol[colorCount - i - 1]; |
} |
if (pos) { |
for (int i = 0; i < colorCount; ++i) { |
- posNew[i] = 1 - pos[colorCount - i - 1]; |
+ posNew[i] = 1 - simplifiedPos[colorCount - i - 1]; |
} |
desc_init(&desc, colorsNew.get(), posNew.get(), colorCount, mode, flags, localMatrix); |
} else { |
@@ -864,8 +951,23 @@ sk_sp<SkShader> SkGradientShader::MakeSweep(SkScalar cx, SkScalar cy, |
return SkShader::MakeColorShader(colors[0]); |
} |
+ SkAutoTArray<SkScalar> simplifiedPos(colorCount); |
+ SkAutoTArray<SkColor> simplifiedCol(colorCount); |
+ for (int i = 0; i < colorCount; i++) { |
+ simplifiedCol[i] = colors[i]; |
+ } |
+ auto mode = SkShader::kClamp_TileMode; // Bogus tilemode |
+ if (pos) { |
+ for (int i = 0; i < colorCount; i++) { |
+ simplifiedPos[i] = pos[i]; |
+ } |
+ colorCount = simplify(simplifiedPos.get(), simplifiedCol.get(), colorCount, mode); |
+ } else { |
+ simplifiedPos.reset(0); |
+ } |
+ |
SkGradientShaderBase::Descriptor desc; |
- desc_init(&desc, colors, pos, colorCount, SkShader::kClamp_TileMode, flags, localMatrix); |
+ desc_init(&desc, simplifiedCol.get(), simplifiedPos.get(), colorCount, mode, flags, localMatrix); |
return sk_make_sp<SkSweepGradient>(cx, cy, desc); |
} |