Chromium Code Reviews| 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); |
| } |