aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Matt Sarett <msarett@google.com>2017-04-18 18:29:12 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-04-19 16:28:44 +0000
commit6cc6ae7573fdfd0af1f9488349b1d2bb88c1b01d (patch)
tree82902aa9d97585692885c62f144d883ecc035c74 /src/core
parent4dbc9cead90eb31756a1c1bf61ea01f223c5fe96 (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.cpp4
-rw-r--r--src/core/SkColorShader.h7
-rw-r--r--src/core/SkColorSpaceXformer.cpp98
-rw-r--r--src/core/SkColorSpaceXformer.h4
-rw-r--r--src/core/SkComposeShader.h6
-rw-r--r--src/core/SkLocalMatrixShader.h5
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);