diff options
author | Mike Klein <mtklein@chromium.org> | 2017-03-15 09:56:47 -0700 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-03-15 18:41:10 +0000 |
commit | d492db941a0f8110ef4b6bceacfe788a8d33a5b7 (patch) | |
tree | 4cab62862449a18a911eaca5261f4dccb08510b5 /src/core | |
parent | 7d9f9e30204ee8a380443b868e4cc281319a2051 (diff) |
SkColorSpaceXformCanvas: simple support for shaders
So far it looks like we can hit the major shader subclasses without
needing to add new calls to SkShader. Not married to this approach,
but it's a big head start.
I've left out nonlinear gradient types just to keep this CL clear.
Will follow up with them... they won't be interestingly different.
Change-Id: I8711ff464f384d8be1671c139ba10a20502d9c0f
Reviewed-on: https://skia-review.googlesource.com/9742
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Mike Klein <mtklein@chromium.org>
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/SkColorSpaceXformCanvas.cpp | 78 |
1 files changed, 71 insertions, 7 deletions
diff --git a/src/core/SkColorSpaceXformCanvas.cpp b/src/core/SkColorSpaceXformCanvas.cpp index ac93e3a1ee..ede47ef76a 100644 --- a/src/core/SkColorSpaceXformCanvas.cpp +++ b/src/core/SkColorSpaceXformCanvas.cpp @@ -8,6 +8,7 @@ #include "SkColorFilter.h" #include "SkColorSpaceXform.h" #include "SkColorSpaceXformCanvas.h" +#include "SkGradientShader.h" #include "SkImage_Base.h" #include "SkMakeUnique.h" #include "SkNoDrawCanvas.h" @@ -25,6 +26,10 @@ public: fFromSRGB = SkColorSpaceXform::New(SkColorSpace::MakeSRGB().get(), fTargetCS.get()); } + sk_sp<const SkImage> xform(const SkImage* img) const { + return as_IB(img)->makeColorSpace(fTargetCS); + } + void xform(SkColor* xformed, const SkColor* srgb, int n) const { SkAssertResult(fFromSRGB->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, xformed, SkColorSpaceXform::kBGRA_8888_ColorFormat, srgb, @@ -37,6 +42,64 @@ public: return xformed; } + // TODO: Is this introspection going to be enough, or do we need a new SkShader method? + sk_sp<SkShader> xform(const SkShader* shader) const { + SkColor color; + if (shader->isConstant() && shader->asLuminanceColor(&color)) { + return SkShader::MakeColorShader(this->xform(color)); + } + + SkShader::TileMode xy[2]; + SkMatrix local; + if (auto img = shader->isAImage(&local, xy)) { + return this->xform(img)->makeShader(xy[0], xy[1], &local); + } + + SkShader::ComposeRec compose; + if (shader->asACompose(&compose)) { + auto A = this->xform(compose.fShaderA), + B = this->xform(compose.fShaderB); + if (A && B) { + return SkShader::MakeComposeShader(std::move(A), std::move(B), compose.fBlendMode); + } + } + + 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->xform(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: break; // TODO + case SkShader::kSweep_GradientType: break; // TODO + case SkShader::kConical_GradientType: break; // TODO + } + } + + return nullptr; + } + const SkPaint& xform(const SkPaint& paint, SkTLazy<SkPaint>* lazy) const { const SkPaint* result = &paint; auto get_lazy = [&] { @@ -52,6 +115,12 @@ public: get_lazy()->setColor(this->xform(paint.getColor())); } + if (auto shader = paint.getShader()) { + if (auto replacement = this->xform(shader)) { + get_lazy()->setShader(std::move(replacement)); + } + } + // As far as I know, SkModeColorFilter is the only color filter that holds a color. if (auto cf = paint.getColorFilter()) { SkColor color; @@ -62,7 +131,6 @@ public: } // TODO: - // - shaders // - image filters? return *result; @@ -72,10 +140,6 @@ public: return paint ? &this->xform(*paint, lazy) : nullptr; } - sk_sp<const SkImage> xform(const SkImage* img) const { - return as_IB(img)->makeColorSpace(fTargetCS); - } - void onDrawPaint(const SkPaint& paint) override { SkTLazy<SkPaint> lazy; fTarget->drawPaint(this->xform(paint, &lazy)); @@ -130,7 +194,7 @@ public: const SkPoint* verts, const SkPoint* texs, const SkColor* colors, SkBlendMode mode, const uint16_t* indices, int indexCount, const SkPaint& paint) override { - SkTArray<SkColor> xformed; + SkSTArray<8, SkColor> xformed; if (colors) { xformed.reset(count); this->xform(xformed.begin(), colors, count); @@ -214,7 +278,7 @@ public: void onDrawAtlas(const SkImage* atlas, const SkRSXform* xforms, const SkRect* tex, const SkColor* colors, int count, SkBlendMode mode, const SkRect* cull, const SkPaint* paint) override { - SkTArray<SkColor> xformed; + SkSTArray<8, SkColor> xformed; if (colors) { xformed.reset(count); this->xform(xformed.begin(), colors, count); |