diff options
author | Matt Sarett <msarett@google.com> | 2017-04-18 18:29:12 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-04-19 16:28:44 +0000 |
commit | 6cc6ae7573fdfd0af1f9488349b1d2bb88c1b01d (patch) | |
tree | 82902aa9d97585692885c62f144d883ecc035c74 /src/core | |
parent | 4dbc9cead90eb31756a1c1bf61ea01f223c5fe96 (diff) |
SkColorSpaceXformer: Add SkShader::makeColorSpace()
Just a refactor - reimplements the shader xforms with makeColorSpace().
11 gms have diffs. Some are down to floating precision. The old
implementation would go float->fixed->float in some cases. Others
are due to improvements with gradient shaders inside local matrix
shaders.
Bug: skia:6516
Change-Id: I424406990c5c58a47833cf4c9ef146cd3ea6c37e
Reviewed-on: https://skia-review.googlesource.com/13769
Reviewed-by: Mike Klein <mtklein@chromium.org>
Commit-Queue: Matt Sarett <msarett@google.com>
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/SkColorShader.cpp | 4 | ||||
-rw-r--r-- | src/core/SkColorShader.h | 7 | ||||
-rw-r--r-- | src/core/SkColorSpaceXformer.cpp | 98 | ||||
-rw-r--r-- | src/core/SkColorSpaceXformer.h | 4 | ||||
-rw-r--r-- | src/core/SkComposeShader.h | 6 | ||||
-rw-r--r-- | src/core/SkLocalMatrixShader.h | 5 |
6 files changed, 33 insertions, 91 deletions
diff --git a/src/core/SkColorShader.cpp b/src/core/SkColorShader.cpp index 5c8bde6ee1..66fc65426a 100644 --- a/src/core/SkColorShader.cpp +++ b/src/core/SkColorShader.cpp @@ -236,6 +236,10 @@ void SkColor4Shader::toString(SkString* str) const { } #endif +sk_sp<SkShader> SkColor4Shader::onMakeColorSpace(SkColorSpaceXformer* xformer) const { + return SkShader::MakeColorShader(xformer->apply(fCachedByteColor)); +} + sk_sp<SkShader> SkShader::MakeColorShader(const SkColor4f& color, sk_sp<SkColorSpace> space) { if (!SkScalarsAreFinite(color.vec(), 4)) { return nullptr; diff --git a/src/core/SkColorShader.h b/src/core/SkColorShader.h index b9db657b2b..0a6a935afd 100644 --- a/src/core/SkColorShader.h +++ b/src/core/SkColorShader.h @@ -8,6 +8,7 @@ #ifndef SkColorShader_DEFINED #define SkColorShader_DEFINED +#include "SkColorSpaceXformer.h" #include "SkShader.h" #include "SkPM4f.h" @@ -69,6 +70,10 @@ protected: bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*, const SkMatrix& ctm, const SkPaint&, const SkMatrix*) const override; + sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override { + return SkShader::MakeColorShader(xformer->apply(fColor)); + } + private: SkColor fColor; @@ -124,6 +129,8 @@ protected: bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*, const SkMatrix& ctm, const SkPaint&, const SkMatrix*) const override; + sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override; + private: sk_sp<SkColorSpace> fColorSpace; const SkColor4f fColor4; diff --git a/src/core/SkColorSpaceXformer.cpp b/src/core/SkColorSpaceXformer.cpp index 7a9f24b631..779fe81cad 100644 --- a/src/core/SkColorSpaceXformer.cpp +++ b/src/core/SkColorSpaceXformer.cpp @@ -75,91 +75,6 @@ SkColor SkColorSpaceXformer::apply(SkColor srgb) { return xformed; } -// TODO: Is this introspection going to be enough, or do we need a new SkShader method? -sk_sp<SkShader> SkColorSpaceXformer::apply(const SkShader* shader) { - SkColor color; - if (shader->isConstant() && shader->asLuminanceColor(&color)) { - return SkShader::MakeColorShader(this->apply(color)) - ->makeWithLocalMatrix(shader->getLocalMatrix()); - } - - SkShader::TileMode xy[2]; - SkMatrix local; - if (auto img = shader->isAImage(&local, xy)) { - return this->apply(img)->makeShader(xy[0], xy[1], &local); - } - - SkShader::ComposeRec compose; - if (shader->asACompose(&compose)) { - auto A = this->apply(compose.fShaderA), - B = this->apply(compose.fShaderB); - if (A && B) { - return SkShader::MakeComposeShader(std::move(A), std::move(B), compose.fBlendMode) - ->makeWithLocalMatrix(shader->getLocalMatrix()); - } - } - - SkShader::GradientInfo gradient; - sk_bzero(&gradient, sizeof(gradient)); - if (auto type = shader->asAGradient(&gradient)) { - SkSTArray<8, SkColor> colors(gradient.fColorCount); - SkSTArray<8, SkScalar> pos(gradient.fColorCount); - - gradient.fColors = colors.begin(); - gradient.fColorOffsets = pos.begin(); - shader->asAGradient(&gradient); - - SkSTArray<8, SkColor> xformed(gradient.fColorCount); - this->apply(xformed.begin(), gradient.fColors, gradient.fColorCount); - - switch (type) { - case SkShader::kNone_GradientType: - case SkShader::kColor_GradientType: - SkASSERT(false); // Should be unreachable. - break; - - case SkShader::kLinear_GradientType: - return SkGradientShader::MakeLinear(gradient.fPoint, - xformed.begin(), - gradient.fColorOffsets, - gradient.fColorCount, - gradient.fTileMode, - gradient.fGradientFlags, - &shader->getLocalMatrix()); - case SkShader::kRadial_GradientType: - return SkGradientShader::MakeRadial(gradient.fPoint[0], - gradient.fRadius[0], - xformed.begin(), - gradient.fColorOffsets, - gradient.fColorCount, - gradient.fTileMode, - gradient.fGradientFlags, - &shader->getLocalMatrix()); - case SkShader::kSweep_GradientType: - return SkGradientShader::MakeSweep(gradient.fPoint[0].fX, - gradient.fPoint[0].fY, - xformed.begin(), - gradient.fColorOffsets, - gradient.fColorCount, - gradient.fGradientFlags, - &shader->getLocalMatrix()); - case SkShader::kConical_GradientType: - return SkGradientShader::MakeTwoPointConical(gradient.fPoint[0], - gradient.fRadius[0], - gradient.fPoint[1], - gradient.fRadius[1], - xformed.begin(), - gradient.fColorOffsets, - gradient.fColorCount, - gradient.fTileMode, - gradient.fGradientFlags, - &shader->getLocalMatrix()); - } - } - - return sk_ref_sp(const_cast<SkShader*>(shader)); -} - const SkPaint& SkColorSpaceXformer::apply(const SkPaint& src) { const SkPaint* result = &src; auto get_dst = [&] { @@ -176,7 +91,8 @@ const SkPaint& SkColorSpaceXformer::apply(const SkPaint& src) { } if (auto shader = src.getShader()) { - if (auto replacement = this->apply(shader)) { + auto replacement = shader->makeColorSpace(this); + if (replacement.get() != shader) { get_dst()->setShader(std::move(replacement)); } } @@ -189,11 +105,17 @@ const SkPaint& SkColorSpaceXformer::apply(const SkPaint& src) { } if (auto looper = src.getDrawLooper()) { - get_dst()->setDrawLooper(looper->makeColorSpace(this)); + auto replacement = looper->makeColorSpace(this); + if (replacement.get() != looper) { + get_dst()->setDrawLooper(std::move(replacement)); + } } if (auto imageFilter = src.getImageFilter()) { - get_dst()->setImageFilter(imageFilter->makeColorSpace(this)); + auto replacement = imageFilter->makeColorSpace(this); + if (replacement.get() != imageFilter) { + get_dst()->setImageFilter(std::move(replacement)); + } } return *result; diff --git a/src/core/SkColorSpaceXformer.h b/src/core/SkColorSpaceXformer.h index 5fc62e09f7..61a0c027c8 100644 --- a/src/core/SkColorSpaceXformer.h +++ b/src/core/SkColorSpaceXformer.h @@ -18,7 +18,7 @@ public: sk_sp<SkImage> apply(const SkImage* src); sk_sp<SkImage> apply(const SkBitmap& bitmap); - sk_sp<SkColorFilter> apply(const SkColorFilter* shader); + sk_sp<SkColorFilter> apply(const SkColorFilter* filter); const SkPaint* apply(const SkPaint* src); const SkPaint& apply(const SkPaint& src); void apply(SkColor dst[], const SkColor src[], int n); @@ -27,8 +27,6 @@ public: sk_sp<SkColorSpace> dst() const { return fDst; } private: - sk_sp<SkShader> apply(const SkShader* shader); - SkColorSpaceXformer() {} sk_sp<SkColorSpace> fDst; diff --git a/src/core/SkComposeShader.h b/src/core/SkComposeShader.h index be788af2af..d5905b7846 100644 --- a/src/core/SkComposeShader.h +++ b/src/core/SkComposeShader.h @@ -11,6 +11,8 @@ #include "SkShader.h" #include "SkBlendMode.h" +class SkColorSpacXformer; + /////////////////////////////////////////////////////////////////////////////////////////// /** \class SkComposeShader @@ -68,6 +70,10 @@ protected: SkComposeShader(SkReadBuffer&); void flatten(SkWriteBuffer&) const override; Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override; + sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override { + return SkShader::MakeComposeShader(fShaderA->makeColorSpace(xformer), + fShaderB->makeColorSpace(xformer), fMode); + } private: sk_sp<SkShader> fShaderA; diff --git a/src/core/SkLocalMatrixShader.h b/src/core/SkLocalMatrixShader.h index cba140906b..97986a6332 100644 --- a/src/core/SkLocalMatrixShader.h +++ b/src/core/SkLocalMatrixShader.h @@ -14,6 +14,7 @@ class GrFragmentProcessor; class SkArenaAlloc; +class SkColorSpaceXformer; class SkLocalMatrixShader : public SkShader { public: @@ -50,6 +51,10 @@ protected: bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*, const SkMatrix&, const SkPaint&, const SkMatrix*) const override; + sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override { + return fProxyShader->makeColorSpace(xformer)->makeWithLocalMatrix(this->getLocalMatrix()); + } + #ifdef SK_SUPPORT_LEGACY_SHADER_ISABITMAP bool onIsABitmap(SkBitmap* bitmap, SkMatrix* matrix, TileMode* mode) const override { return fProxyShader->isABitmap(bitmap, matrix, mode); |