aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkShader.h13
-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
-rw-r--r--src/effects/gradients/SkLinearGradient.cpp9
-rw-r--r--src/effects/gradients/SkLinearGradient.h2
-rw-r--r--src/effects/gradients/SkRadialGradient.cpp9
-rw-r--r--src/effects/gradients/SkRadialGradient.h1
-rw-r--r--src/effects/gradients/SkSweepGradient.cpp8
-rw-r--r--src/effects/gradients/SkSweepGradient.h1
-rw-r--r--src/effects/gradients/SkTwoPointConicalGradient.cpp27
-rw-r--r--src/effects/gradients/SkTwoPointConicalGradient.h2
-rw-r--r--src/image/SkImageShader.h8
16 files changed, 112 insertions, 92 deletions
diff --git a/include/core/SkShader.h b/include/core/SkShader.h
index e49ad5f6a6..b3b5faaa1f 100644
--- a/include/core/SkShader.h
+++ b/include/core/SkShader.h
@@ -20,6 +20,7 @@
class SkArenaAlloc;
class SkColorFilter;
class SkColorSpace;
+class SkColorSpaceXformer;
class SkImage;
class SkPath;
class SkPicture;
@@ -497,6 +498,16 @@ protected:
const SkMatrix&, const SkPaint&,
const SkMatrix* /*local matrix*/) const;
+ /**
+ * Returns a shader transformed into a new color space via the |xformer|.
+ */
+ sk_sp<SkShader> makeColorSpace(SkColorSpaceXformer* xformer) const {
+ return this->onMakeColorSpace(xformer);
+ }
+ virtual sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer*) const {
+ return sk_ref_sp(const_cast<SkShader*>(this));
+ }
+
private:
// This is essentially const, but not officially so it can be modified in
// constructors.
@@ -505,6 +516,8 @@ private:
// So the SkLocalMatrixShader can whack fLocalMatrix in its SkReadBuffer constructor.
friend class SkLocalMatrixShader;
friend class SkBitmapProcLegacyShader; // for computeTotalInverse()
+ friend class SkComposeShader;
+ friend class SkColorSpaceXformer;
typedef SkFlattenable INHERITED;
};
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);
diff --git a/src/effects/gradients/SkLinearGradient.cpp b/src/effects/gradients/SkLinearGradient.cpp
index de6341e8a4..24cb1b592d 100644
--- a/src/effects/gradients/SkLinearGradient.cpp
+++ b/src/effects/gradients/SkLinearGradient.cpp
@@ -6,6 +6,7 @@
*/
#include "Sk4fLinearGradient.h"
+#include "SkColorSpaceXformer.h"
#include "SkLinearGradient.h"
#include "SkRefCnt.h"
@@ -257,6 +258,14 @@ bool SkLinearGradient::onAppendStages(SkRasterPipeline* p,
return true;
}
+sk_sp<SkShader> SkLinearGradient::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
+ SkPoint pts[2] = { fStart, fEnd };
+ SkSTArray<8, SkColor> xformedColors(fColorCount);
+ xformer->apply(xformedColors.begin(), fOrigColors, fColorCount);
+ return SkGradientShader::MakeLinear(pts, xformedColors.begin(), fOrigPos, fColorCount,
+ fTileMode, fGradFlags, &this->getLocalMatrix());
+}
+
// This swizzles SkColor into the same component order as SkPMColor, but does not actually
// "pre" multiply the color components.
//
diff --git a/src/effects/gradients/SkLinearGradient.h b/src/effects/gradients/SkLinearGradient.h
index 4118deeae5..f860568147 100644
--- a/src/effects/gradients/SkLinearGradient.h
+++ b/src/effects/gradients/SkLinearGradient.h
@@ -71,6 +71,8 @@ protected:
bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*,
const SkMatrix&, const SkPaint&, const SkMatrix*) const override;
+ sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override;
+
private:
class LinearGradient4fContext;
diff --git a/src/effects/gradients/SkRadialGradient.cpp b/src/effects/gradients/SkRadialGradient.cpp
index 2caf905a51..71cdb9fe17 100644
--- a/src/effects/gradients/SkRadialGradient.cpp
+++ b/src/effects/gradients/SkRadialGradient.cpp
@@ -5,6 +5,7 @@
* found in the LICENSE file.
*/
+#include "SkColorSpaceXformer.h"
#include "SkRadialGradient.h"
#include "SkNx.h"
@@ -367,6 +368,14 @@ sk_sp<GrFragmentProcessor> SkRadialGradient::asFragmentProcessor(const AsFPArgs&
#endif
+sk_sp<SkShader> SkRadialGradient::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
+ SkSTArray<8, SkColor> xformedColors(fColorCount);
+ xformer->apply(xformedColors.begin(), fOrigColors, fColorCount);
+ return SkGradientShader::MakeRadial(fCenter, fRadius, xformedColors.begin(), fOrigPos,
+ fColorCount, fTileMode, fGradFlags,
+ &this->getLocalMatrix());
+}
+
#ifndef SK_IGNORE_TO_STRING
void SkRadialGradient::toString(SkString* str) const {
str->append("SkRadialGradient: (");
diff --git a/src/effects/gradients/SkRadialGradient.h b/src/effects/gradients/SkRadialGradient.h
index f92fbb3b72..c43df09146 100644
--- a/src/effects/gradients/SkRadialGradient.h
+++ b/src/effects/gradients/SkRadialGradient.h
@@ -36,6 +36,7 @@ protected:
SkRadialGradient(SkReadBuffer& buffer);
void flatten(SkWriteBuffer& buffer) const override;
Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override;
+ sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override;
private:
const SkPoint fCenter;
diff --git a/src/effects/gradients/SkSweepGradient.cpp b/src/effects/gradients/SkSweepGradient.cpp
index 06b9f210da..27517bb080 100644
--- a/src/effects/gradients/SkSweepGradient.cpp
+++ b/src/effects/gradients/SkSweepGradient.cpp
@@ -5,6 +5,7 @@
* found in the LICENSE file.
*/
+#include "SkColorSpaceXformer.h"
#include "SkSweepGradient.h"
#include <algorithm>
@@ -280,6 +281,13 @@ sk_sp<GrFragmentProcessor> SkSweepGradient::asFragmentProcessor(const AsFPArgs&
#endif
+sk_sp<SkShader> SkSweepGradient::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
+ SkSTArray<8, SkColor> xformedColors(fColorCount);
+ xformer->apply(xformedColors.begin(), fOrigColors, fColorCount);
+ return SkGradientShader::MakeSweep(fCenter.fX, fCenter.fY, xformedColors.begin(), fOrigPos,
+ fColorCount, fGradFlags, &this->getLocalMatrix());
+}
+
#ifndef SK_IGNORE_TO_STRING
void SkSweepGradient::toString(SkString* str) const {
str->append("SkSweepGradient: (");
diff --git a/src/effects/gradients/SkSweepGradient.h b/src/effects/gradients/SkSweepGradient.h
index 30ebb1ad4e..331e22d7b3 100644
--- a/src/effects/gradients/SkSweepGradient.h
+++ b/src/effects/gradients/SkSweepGradient.h
@@ -36,6 +36,7 @@ public:
protected:
void flatten(SkWriteBuffer& buffer) const override;
Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override;
+ sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override;
private:
const SkPoint fCenter;
diff --git a/src/effects/gradients/SkTwoPointConicalGradient.cpp b/src/effects/gradients/SkTwoPointConicalGradient.cpp
index a9740aa455..ced299ee23 100644
--- a/src/effects/gradients/SkTwoPointConicalGradient.cpp
+++ b/src/effects/gradients/SkTwoPointConicalGradient.cpp
@@ -367,6 +367,33 @@ sk_sp<GrFragmentProcessor> SkTwoPointConicalGradient::asFragmentProcessor(
#endif
+sk_sp<SkShader> SkTwoPointConicalGradient::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
+ SkSTArray<8, SkColor> origColorsStorage(fColorCount);
+ SkSTArray<8, SkScalar> origPosStorage(fColorCount);
+ SkSTArray<8, SkColor> xformedColorsStorage(fColorCount);
+ SkColor* origColors = origColorsStorage.begin();
+ SkScalar* origPos = fOrigPos ? origPosStorage.begin() : nullptr;
+ SkColor* xformedColors = xformedColorsStorage.begin();
+
+ // Flip if necessary
+ SkPoint center1 = fFlippedGrad ? fCenter2 : fCenter1;
+ SkPoint center2 = fFlippedGrad ? fCenter1 : fCenter2;
+ SkScalar radius1 = fFlippedGrad ? fRadius2 : fRadius1;
+ SkScalar radius2 = fFlippedGrad ? fRadius1 : fRadius2;
+ for (int i = 0; i < fColorCount; i++) {
+ origColors[i] = fFlippedGrad ? fOrigColors[fColorCount - i - 1] : fOrigColors[i];
+ if (origPos) {
+ origPos[i] = fFlippedGrad ? 1.0f - fOrigPos[fColorCount - i - 1] : fOrigPos[i];
+ }
+ }
+
+ xformer->apply(xformedColors, origColors, fColorCount);
+ return SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2, xformedColors,
+ origPos, fColorCount, fTileMode, fGradFlags,
+ &this->getLocalMatrix());
+}
+
+
#ifndef SK_IGNORE_TO_STRING
void SkTwoPointConicalGradient::toString(SkString* str) const {
str->append("SkTwoPointConicalGradient: (");
diff --git a/src/effects/gradients/SkTwoPointConicalGradient.h b/src/effects/gradients/SkTwoPointConicalGradient.h
index d73ba11512..b32f52c1e0 100644
--- a/src/effects/gradients/SkTwoPointConicalGradient.h
+++ b/src/effects/gradients/SkTwoPointConicalGradient.h
@@ -8,6 +8,7 @@
#ifndef SkTwoPointConicalGradient_DEFINED
#define SkTwoPointConicalGradient_DEFINED
+#include "SkColorSpaceXformer.h"
#include "SkGradientShaderPriv.h"
// TODO(dominikg): Worth making it truly immutable (i.e. set values in constructor)?
@@ -76,6 +77,7 @@ protected:
SkTwoPointConicalGradient(SkReadBuffer& buffer);
void flatten(SkWriteBuffer& buffer) const override;
Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override;
+ sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override;
private:
SkPoint fCenter1;
diff --git a/src/image/SkImageShader.h b/src/image/SkImageShader.h
index 8960812a06..5274826e88 100644
--- a/src/image/SkImageShader.h
+++ b/src/image/SkImageShader.h
@@ -8,9 +8,10 @@
#ifndef SkImageShader_DEFINED
#define SkImageShader_DEFINED
+#include "SkBitmapProcShader.h"
+#include "SkColorSpaceXformer.h"
#include "SkImage.h"
#include "SkShader.h"
-#include "SkBitmapProcShader.h"
class SkImageShader : public SkShader {
public:
@@ -39,6 +40,11 @@ protected:
bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*,
const SkMatrix& ctm, const SkPaint&, const SkMatrix*) const override;
+ sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override {
+ return xformer->apply(fImage.get())->makeShader(fTileModeX, fTileModeY,
+ &this->getLocalMatrix());
+ }
+
sk_sp<SkImage> fImage;
const TileMode fTileModeX;
const TileMode fTileModeY;