diff options
Diffstat (limited to 'src/shaders')
-rw-r--r-- | src/shaders/SkImageShader.cpp | 46 | ||||
-rw-r--r-- | src/shaders/SkImageShader.h | 30 |
2 files changed, 48 insertions, 28 deletions
diff --git a/src/shaders/SkImageShader.cpp b/src/shaders/SkImageShader.cpp index 1f77158206..3e58782aee 100644 --- a/src/shaders/SkImageShader.cpp +++ b/src/shaders/SkImageShader.cpp @@ -31,23 +31,30 @@ static SkShader::TileMode optimize(SkShader::TileMode tm, int dimension) { #endif } -SkImageShader::SkImageShader(sk_sp<SkImage> img, TileMode tmx, TileMode tmy, const SkMatrix* matrix) - : INHERITED(matrix) +SkImageShader::SkImageShader(sk_sp<SkImage> img, + TileMode tmx, TileMode tmy, + const SkMatrix* localMatrix, + SkAlphaType outputAlphaType) + : INHERITED(localMatrix) , fImage(std::move(img)) , fTileModeX(optimize(tmx, fImage->width())) , fTileModeY(optimize(tmy, fImage->height())) + , fOutputAlphaType(outputAlphaType) {} +// fOutputAlphaType is always kPremul_SkAlphaType when an SkImageShader is constructed +// through public APIs that might lead to serialization, so we don't read or write it. + sk_sp<SkFlattenable> SkImageShader::CreateProc(SkReadBuffer& buffer) { const TileMode tx = (TileMode)buffer.readUInt(); const TileMode ty = (TileMode)buffer.readUInt(); - SkMatrix matrix; - buffer.readMatrix(&matrix); + SkMatrix localMatrix; + buffer.readMatrix(&localMatrix); sk_sp<SkImage> img = buffer.readImage(); if (!img) { return nullptr; } - return SkImageShader::Make(std::move(img), tx, ty, &matrix); + return SkImageShader::Make(std::move(img), tx, ty, &localMatrix); } void SkImageShader::flatten(SkWriteBuffer& buffer) const { @@ -55,6 +62,7 @@ void SkImageShader::flatten(SkWriteBuffer& buffer) const { buffer.writeUInt(fTileModeY); buffer.writeMatrix(this->getLocalMatrix()); buffer.writeImage(fImage.get()); + SkASSERT(fOutputAlphaType == kPremul_SkAlphaType); } bool SkImageShader::isOpaque() const { @@ -164,13 +172,14 @@ static bool bitmap_is_too_big(int w, int h) { return w > kMaxSize || h > kMaxSize; } -sk_sp<SkShader> SkImageShader::Make(sk_sp<SkImage> image, TileMode tx, TileMode ty, - const SkMatrix* localMatrix) { +sk_sp<SkShader> SkImageShader::Make(sk_sp<SkImage> image, + TileMode tx, TileMode ty, + const SkMatrix* localMatrix, + SkAlphaType outputAlphaType) { if (!image || bitmap_is_too_big(image->width(), image->height())) { return sk_make_sp<SkEmptyShader>(); - } else { - return sk_make_sp<SkImageShader>(image, tx, ty, localMatrix); } + return sk_sp<SkShader>{ new SkImageShader(image, tx,ty, localMatrix, outputAlphaType) }; } #ifndef SK_IGNORE_TO_STRING @@ -385,19 +394,24 @@ bool SkImageShader::onAppendStages(const StageRec& rec) const { auto append_misc = [&] { if (info.colorType() == kAlpha_8_SkColorType) { p->append(SkRasterPipeline::set_rgb, &misc->paint_color); - } - if (info.colorType() == kAlpha_8_SkColorType || - info.alphaType() == kUnpremul_SkAlphaType) { p->append(SkRasterPipeline::premul); + } else if (info.alphaType() == kUnpremul_SkAlphaType && + fOutputAlphaType == kPremul_SkAlphaType) { + p->append(SkRasterPipeline::premul); + } else if (info.alphaType() == kPremul_SkAlphaType && + fOutputAlphaType == kUnpremul_SkAlphaType) { + p->append(SkRasterPipeline::unpremul); } -#if defined(SK_LEGACY_HIGH_QUALITY_SCALING_CLAMP) + + #if defined(SK_LEGACY_HIGH_QUALITY_SCALING_CLAMP) if (quality > kLow_SkFilterQuality) { // Bicubic filtering naturally produces out of range values on both sides. p->append(SkRasterPipeline::clamp_0); - p->append(SkRasterPipeline::clamp_a); + p->append(fOutputAlphaType == kPremul_SkAlphaType ? SkRasterPipeline::clamp_a + : SkRasterPipeline::clamp_1); } -#endif - append_gamut_transform(p, alloc, info.colorSpace(), rec.fDstCS, kPremul_SkAlphaType); + #endif + append_gamut_transform(p, alloc, info.colorSpace(), rec.fDstCS, fOutputAlphaType); return true; }; diff --git a/src/shaders/SkImageShader.h b/src/shaders/SkImageShader.h index a3cf3dbe7f..9ce615508d 100644 --- a/src/shaders/SkImageShader.h +++ b/src/shaders/SkImageShader.h @@ -15,8 +15,11 @@ class SkImageShader : public SkShaderBase { public: - static sk_sp<SkShader> Make(sk_sp<SkImage>, TileMode tx, TileMode ty, - const SkMatrix* localMatrix); + static sk_sp<SkShader> Make(sk_sp<SkImage>, + SkShader::TileMode tx, + SkShader::TileMode ty, + const SkMatrix* localMatrix, + SkAlphaType outputAlphaType = kPremul_SkAlphaType); bool isOpaque() const override; @@ -27,19 +30,23 @@ public: std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(const GrFPArgs&) const override; #endif - SkImageShader(sk_sp<SkImage>, TileMode tx, TileMode ty, const SkMatrix* localMatrix); - static bool IsRasterPipelineOnly(const SkMatrix& ctm, SkColorType, SkAlphaType, SkShader::TileMode tx, SkShader::TileMode ty, const SkMatrix& localM); -protected: +private: + SkImageShader(sk_sp<SkImage>, + SkShader::TileMode tx, + SkShader::TileMode ty, + const SkMatrix* localMatrix, + SkAlphaType outputAlphaType); + void flatten(SkWriteBuffer&) const override; Context* onMakeContext(const ContextRec&, SkArenaAlloc* storage) const override; #ifdef SK_SUPPORT_LEGACY_SHADER_ISABITMAP - bool onIsABitmap(SkBitmap*, SkMatrix*, TileMode*) const override; + bool onIsABitmap(SkBitmap*, SkMatrix*, SkShader::TileMode*) const override; #endif - SkImage* onIsAImage(SkMatrix*, TileMode*) const override; + SkImage* onIsAImage(SkMatrix*, SkShader::TileMode*) const override; bool onIsRasterPipelineOnly(const SkMatrix& ctm) const override; @@ -50,13 +57,12 @@ protected: &this->getLocalMatrix()); } - sk_sp<SkImage> fImage; - const TileMode fTileModeX; - const TileMode fTileModeY; + sk_sp<SkImage> fImage; + const SkShader::TileMode fTileModeX; + const SkShader::TileMode fTileModeY; + const SkAlphaType fOutputAlphaType; -private: friend class SkShaderBase; - typedef SkShaderBase INHERITED; }; |