Index: src/effects/SkXfermodeImageFilter.cpp |
diff --git a/src/effects/SkXfermodeImageFilter.cpp b/src/effects/SkXfermodeImageFilter.cpp |
index 952ce977aaf20cd6fb6dd6b2a3d11346c872a5f1..b0735168b51a857d2d6672d651e833eecb2dcd18 100644 |
--- a/src/effects/SkXfermodeImageFilter.cpp |
+++ b/src/effects/SkXfermodeImageFilter.cpp |
@@ -6,6 +6,7 @@ |
*/ |
#include "SkXfermodeImageFilter.h" |
+#include "SkArithmeticModePriv.h" |
#include "SkCanvas.h" |
#include "SkColorPriv.h" |
@@ -27,7 +28,7 @@ |
class SkXfermodeImageFilter_Base : public SkImageFilter { |
public: |
- SkXfermodeImageFilter_Base(sk_sp<SkXfermode> mode, sk_sp<SkImageFilter> inputs[2], |
+ SkXfermodeImageFilter_Base(SkBlendMode mode, sk_sp<SkImageFilter> inputs[2], |
const CropRect* cropRect); |
SK_TO_STRING_OVERRIDE() |
@@ -55,7 +56,7 @@ protected: |
#endif |
private: |
- sk_sp<SkXfermode> fMode; |
+ SkBlendMode fMode; |
friend class SkXfermodeImageFilter; |
@@ -64,7 +65,7 @@ private: |
/////////////////////////////////////////////////////////////////////////////// |
-sk_sp<SkImageFilter> SkXfermodeImageFilter::Make(sk_sp<SkXfermode> mode, |
+sk_sp<SkImageFilter> SkXfermodeImageFilter::Make(SkBlendMode mode, |
sk_sp<SkImageFilter> background, |
sk_sp<SkImageFilter> foreground, |
const SkImageFilter::CropRect* cropRect) { |
@@ -72,23 +73,59 @@ sk_sp<SkImageFilter> SkXfermodeImageFilter::Make(sk_sp<SkXfermode> mode, |
return sk_sp<SkImageFilter>(new SkXfermodeImageFilter_Base(mode, inputs, cropRect)); |
} |
-SkXfermodeImageFilter_Base::SkXfermodeImageFilter_Base(sk_sp<SkXfermode> mode, |
- sk_sp<SkImageFilter> inputs[2], |
- const CropRect* cropRect) |
+#ifdef SK_SUPPORT_LEGACY_XFERMODE_OBJECT |
+sk_sp<SkImageFilter> SkXfermodeImageFilter::Make(sk_sp<SkXfermode> mode, |
+ sk_sp<SkImageFilter> background, |
+ sk_sp<SkImageFilter> foreground, |
+ const SkImageFilter::CropRect* cropRect) { |
+ return Make(mode ? mode->blend() : SkBlendMode::kSrcOver, |
+ std::move(background), std::move(foreground), cropRect); |
+} |
+#endif |
+ |
+SkXfermodeImageFilter_Base::SkXfermodeImageFilter_Base(SkBlendMode mode, |
+ sk_sp<SkImageFilter> inputs[2], |
+ const CropRect* cropRect) |
: INHERITED(inputs, 2, cropRect) |
- , fMode(std::move(mode)) { |
+ , fMode(mode) |
+{} |
+ |
+static int unflatten_blendmode(SkReadBuffer& buffer, SkArithmeticParams* arith) { |
+ if (buffer.isVersionLT(SkReadBuffer::kXfermodeToBlendMode_Version)) { |
+ sk_sp<SkXfermode> xfer = buffer.readXfermode(); |
+ if (xfer) { |
+ if (xfer->isArithmetic(arith)) { |
+ return -1; |
+ } |
+ return (int)xfer->blend(); |
+ } else { |
+ return (int)SkBlendMode::kSrcOver; |
+ } |
+ } else { |
+ uint32_t mode = buffer.read32(); |
+ (void)buffer.validate(mode <= (unsigned)SkBlendMode::kLastMode); |
+ return mode; |
+ } |
} |
sk_sp<SkFlattenable> SkXfermodeImageFilter_Base::CreateProc(SkReadBuffer& buffer) { |
SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 2); |
- sk_sp<SkXfermode> mode(buffer.readXfermode()); |
- return SkXfermodeImageFilter::Make(std::move(mode), common.getInput(0), common.getInput(1), |
- &common.cropRect()); |
+ SkArithmeticParams arith; |
+ int mode = unflatten_blendmode(buffer, &arith); |
+ if (mode >= 0) { |
+ return SkXfermodeImageFilter::Make((SkBlendMode)mode, common.getInput(0), |
+ common.getInput(1), &common.cropRect()); |
+ } else { |
+ return SkXfermodeImageFilter::MakeArithmetic(arith.fK[0], arith.fK[1], arith.fK[2], |
+ arith.fK[3], arith.fEnforcePMColor, |
+ common.getInput(0), |
+ common.getInput(1), &common.cropRect()); |
+ } |
} |
void SkXfermodeImageFilter_Base::flatten(SkWriteBuffer& buffer) const { |
this->INHERITED::flatten(buffer); |
- buffer.writeFlattenable(fMode.get()); |
+ buffer.write32((unsigned)fMode); |
} |
sk_sp<SkSpecialImage> SkXfermodeImageFilter_Base::onFilterImage(SkSpecialImage* source, |
@@ -147,7 +184,7 @@ sk_sp<SkSpecialImage> SkXfermodeImageFilter_Base::onFilterImage(SkSpecialImage* |
if (background) { |
SkPaint paint; |
- paint.setXfermodeMode(SkXfermode::kSrc_Mode); |
+ paint.setBlendMode(SkBlendMode::kSrc); |
background->draw(canvas, |
SkIntToScalar(backgroundOffset.fX), SkIntToScalar(backgroundOffset.fY), |
&paint); |
@@ -161,7 +198,7 @@ sk_sp<SkSpecialImage> SkXfermodeImageFilter_Base::onFilterImage(SkSpecialImage* |
void SkXfermodeImageFilter_Base::drawForeground(SkCanvas* canvas, SkSpecialImage* img, |
const SkIRect& fgBounds) const { |
SkPaint paint; |
- paint.setXfermode(fMode); |
+ paint.setBlendMode(fMode); |
if (img) { |
img->draw(canvas, SkIntToScalar(fgBounds.fLeft), SkIntToScalar(fgBounds.fTop), &paint); |
} |
@@ -175,11 +212,7 @@ void SkXfermodeImageFilter_Base::drawForeground(SkCanvas* canvas, SkSpecialImage |
#ifndef SK_IGNORE_TO_STRING |
void SkXfermodeImageFilter_Base::toString(SkString* str) const { |
str->appendf("SkXfermodeImageFilter: ("); |
- str->appendf("xfermode: ("); |
- if (fMode) { |
- fMode->toString(str); |
- } |
- str->append(")"); |
+ str->appendf("blendmode: (%d)", (int)fMode); |
if (this->getInput(0)) { |
str->appendf("foreground: ("); |
this->getInput(0)->toString(str); |
@@ -266,7 +299,7 @@ sk_sp<SkSpecialImage> SkXfermodeImageFilter_Base::filterImageGPU( |
paint.addColorFragmentProcessor(std::move(bgFP)); |
} |
- paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); |
+ paint.setPorterDuffXPFactory(SkBlendMode::kSrc); |
sk_sp<GrDrawContext> drawContext( |
context->makeDrawContext(SkBackingFit::kApprox, bounds.width(), bounds.height(), |
@@ -290,8 +323,9 @@ sk_sp<SkSpecialImage> SkXfermodeImageFilter_Base::filterImageGPU( |
sk_sp<GrFragmentProcessor> |
SkXfermodeImageFilter_Base::makeFGFrag(sk_sp<GrFragmentProcessor> bgFP) const { |
// A null fMode is interpreted to mean kSrcOver_Mode (to match raster). |
- SkAutoTUnref<SkXfermode> mode(SkSafeRef(fMode.get())); |
- if (!mode) { |
+ SkXfermode* xfer = SkXfermode::Peek(fMode); |
+ sk_sp<SkXfermode> srcover; |
+ if (!xfer) { |
// It would be awesome to use SkXfermode::Create here but it knows better |
// than us and won't return a kSrcOver_Mode SkXfermode. That means we |
// have to get one the hard way. |
@@ -299,9 +333,11 @@ SkXfermodeImageFilter_Base::makeFGFrag(sk_sp<GrFragmentProcessor> bgFP) const { |
rec.fProc = SkXfermode::GetProc(SkXfermode::kSrcOver_Mode); |
SkXfermode::ModeAsCoeff(SkXfermode::kSrcOver_Mode, &rec.fSC, &rec.fDC); |
- mode.reset(new SkProcCoeffXfermode(rec, SkXfermode::kSrcOver_Mode)); |
+ srcover.reset(new SkProcCoeffXfermode(rec, SkXfermode::kSrcOver_Mode)); |
+ xfer = srcover.get(); |
+ |
} |
- return mode->makeFragmentProcessorForImageFilter(std::move(bgFP)); |
+ return xfer->makeFragmentProcessorForImageFilter(std::move(bgFP)); |
} |
#endif |
@@ -312,7 +348,8 @@ class SkArithmeticImageFilter : public SkXfermodeImageFilter_Base { |
public: |
SkArithmeticImageFilter(float k1, float k2, float k3, float k4, bool enforcePMColor, |
sk_sp<SkImageFilter> inputs[2], const CropRect* cropRect) |
- : SkXfermodeImageFilter_Base(nullptr, inputs, cropRect) |
+ // need to pass a blendmode to our inherited constructor, but we ignore it |
+ : SkXfermodeImageFilter_Base(SkBlendMode::kSrcOver, inputs, cropRect) |
, fK{ k1, k2, k3, k4 } |
, fEnforcePMColor(enforcePMColor) |
{} |
@@ -347,8 +384,11 @@ sk_sp<SkFlattenable> SkArithmeticImageFilter::CreateProc(SkReadBuffer& buffer) { |
SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 2); |
// skip the mode (srcover) our parent-class wrote |
- sk_sp<SkXfermode> mode(buffer.readXfermode()); |
- SkASSERT(nullptr == mode); |
+ SkDEBUGCODE(int mode =) unflatten_blendmode(buffer, nullptr); |
+ if (!buffer.isValid()) { |
+ return nullptr; |
+ } |
+ SkASSERT(SkBlendMode::kSrcOver == (SkBlendMode)mode); |
float k[4]; |
for (int i = 0; i < 4; ++i) { |
@@ -475,16 +515,16 @@ sk_sp<SkImageFilter> SkXfermodeImageFilter::MakeArithmetic(float k1, float k2, f |
int mode = -1; // illegal mode |
if (SkScalarNearlyZero(k1) && SkScalarNearlyEqual(k2, SK_Scalar1) && |
SkScalarNearlyZero(k3) && SkScalarNearlyZero(k4)) { |
- mode = SkXfermode::kSrc_Mode; |
+ mode = (int)SkBlendMode::kSrc; |
} else if (SkScalarNearlyZero(k1) && SkScalarNearlyZero(k2) && |
SkScalarNearlyEqual(k3, SK_Scalar1) && SkScalarNearlyZero(k4)) { |
- mode = SkXfermode::kDst_Mode; |
+ mode = (int)SkBlendMode::kDst; |
} else if (SkScalarNearlyZero(k1) && SkScalarNearlyZero(k2) && |
SkScalarNearlyZero(k3) && SkScalarNearlyZero(k4)) { |
- mode = SkXfermode::kClear_Mode; |
+ mode = (int)SkBlendMode::kClear; |
} |
if (mode >= 0) { |
- return SkXfermodeImageFilter::Make(SkXfermode::Make((SkXfermode::Mode)mode), |
+ return SkXfermodeImageFilter::Make((SkBlendMode)mode, |
std::move(background), std::move(foreground), crop); |
} |