diff options
-rw-r--r-- | include/core/SkShader.h | 13 | ||||
-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 | ||||
-rw-r--r-- | src/effects/gradients/SkLinearGradient.cpp | 9 | ||||
-rw-r--r-- | src/effects/gradients/SkLinearGradient.h | 2 | ||||
-rw-r--r-- | src/effects/gradients/SkRadialGradient.cpp | 9 | ||||
-rw-r--r-- | src/effects/gradients/SkRadialGradient.h | 1 | ||||
-rw-r--r-- | src/effects/gradients/SkSweepGradient.cpp | 8 | ||||
-rw-r--r-- | src/effects/gradients/SkSweepGradient.h | 1 | ||||
-rw-r--r-- | src/effects/gradients/SkTwoPointConicalGradient.cpp | 27 | ||||
-rw-r--r-- | src/effects/gradients/SkTwoPointConicalGradient.h | 2 | ||||
-rw-r--r-- | src/image/SkImageShader.h | 8 |
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; |