aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/shaders
diff options
context:
space:
mode:
Diffstat (limited to 'src/shaders')
-rw-r--r--src/shaders/SkImageShader.cpp46
-rw-r--r--src/shaders/SkImageShader.h30
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;
};