simplify handle-affine: subclass overrides just describe their leaf behavior
added new test case (that would have failed before) of blur with a colorfilter input
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1915943002
Review URL: https://codereview.chromium.org/1915943002
diff --git a/include/core/SkImageFilter.h b/include/core/SkImageFilter.h
index e2ec756..32a52d9 100644
--- a/include/core/SkImageFilter.h
+++ b/include/core/SkImageFilter.h
@@ -220,7 +220,7 @@
* them can handle affine (or more complex) matrices. This call returns true iff the filter
* and all of its (non-null) inputs can handle these more complex matrices.
*/
- bool canHandleAffine() const { return this->onCanHandleAffine(); }
+ bool canHandleComplexCTM() const;
/**
* Return an imagefilter which transforms its input by the given matrix.
@@ -349,7 +349,11 @@
return false;
}
- virtual bool onCanHandleAffine() const;
+ /**
+ * Override this to describe the behavior of your subclass - as a leaf node. The caller will
+ * take care of calling your inputs (and return false if any of them could not handle it).
+ */
+ virtual bool onCanHandleComplexCTM() const { return false; }
/** Given a "srcBounds" rect, computes destination bounds for this filter.
* "dstBounds" are computed by transforming the crop rect by the context's
diff --git a/include/effects/SkColorFilterImageFilter.h b/include/effects/SkColorFilterImageFilter.h
index 10e1ffa..4d438e3 100644
--- a/include/effects/SkColorFilterImageFilter.h
+++ b/include/effects/SkColorFilterImageFilter.h
@@ -36,7 +36,7 @@
sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
SkIPoint* offset) const override;
bool onIsColorFilterNode(SkColorFilter**) const override;
- bool onCanHandleAffine() const override;
+ bool onCanHandleComplexCTM() const override { return true; }
bool affectsTransparentBlack() const override;
private:
diff --git a/include/effects/SkComposeImageFilter.h b/include/effects/SkComposeImageFilter.h
index fe0814a..378b904 100644
--- a/include/effects/SkComposeImageFilter.h
+++ b/include/effects/SkComposeImageFilter.h
@@ -34,6 +34,7 @@
sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
SkIPoint* offset) const override;
SkIRect onFilterBounds(const SkIRect&, const SkMatrix&, MapDirection) const override;
+ bool onCanHandleComplexCTM() const override { return true; }
private:
typedef SkImageFilter INHERITED;
diff --git a/include/effects/SkMergeImageFilter.h b/include/effects/SkMergeImageFilter.h
index 3bab08b..20620d6 100644
--- a/include/effects/SkMergeImageFilter.h
+++ b/include/effects/SkMergeImageFilter.h
@@ -51,6 +51,7 @@
void flatten(SkWriteBuffer&) const override;
sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
SkIPoint* offset) const override;
+ bool onCanHandleComplexCTM() const override { return true; }
private:
SkMergeImageFilter(sk_sp<SkImageFilter> filters[], int count, const SkXfermode::Mode modes[],
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index f8731e9..7552626 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -1217,7 +1217,7 @@
* Perhaps in the future we could augment #5 to apply REMAINDER as part of the draw (no longer
* a sprite operation) to avoid the extra buffer/overhead of MatrixImageFilter.
*/
- if (imageFilter && !stashedMatrix.isScaleTranslate() && !imageFilter->canHandleAffine() &&
+ if (imageFilter && !stashedMatrix.isScaleTranslate() && !imageFilter->canHandleComplexCTM() &&
stashedMatrix.decomposeScale(&scale, &remainder))
{
// We will restore the matrix (which we are overwriting here) in restore via fStashedMatrix
diff --git a/src/core/SkImageFilter.cpp b/src/core/SkImageFilter.cpp
index 6c73be2..ab175884 100644
--- a/src/core/SkImageFilter.cpp
+++ b/src/core/SkImageFilter.cpp
@@ -330,22 +330,18 @@
return true;
}
-bool SkImageFilter::onCanHandleAffine() const {
- bool hasInputs = false;
-
+bool SkImageFilter::canHandleComplexCTM() const {
+ if (!this->onCanHandleComplexCTM()) {
+ return false;
+ }
const int count = this->countInputs();
for (int i = 0; i < count; ++i) {
SkImageFilter* input = this->getInput(i);
- if (input) {
- if (!input->canHandleAffine()) {
- return false;
- }
- hasInputs = true;
+ if (input && !input->canHandleComplexCTM()) {
+ return false;
}
}
- // We return true iff we had 1 or more inputs, and all of them can handle affine.
- // If we have no inputs, or 1 or more of them do not handle affine, then we return false.
- return hasInputs;
+ return true;
}
bool SkImageFilter::applyCropRect(const Context& ctx, const SkIRect& srcBounds,
diff --git a/src/effects/SkColorFilterImageFilter.cpp b/src/effects/SkColorFilterImageFilter.cpp
index 7a2f4cc..8d412cc 100644
--- a/src/effects/SkColorFilterImageFilter.cpp
+++ b/src/effects/SkColorFilterImageFilter.cpp
@@ -126,12 +126,6 @@
return false;
}
-bool SkColorFilterImageFilter::onCanHandleAffine() const {
- SkASSERT(1 == this->countInputs());
- SkImageFilter* input = this->getInput(0);
- return !input || input->canHandleAffine();
-}
-
bool SkColorFilterImageFilter::affectsTransparentBlack() const {
return fColorFilter->affectsTransparentBlack();
}
diff --git a/tests/ImageFilterTest.cpp b/tests/ImageFilterTest.cpp
index 7aefd48..952e5e5 100644
--- a/tests/ImageFilterTest.cpp
+++ b/tests/ImageFilterTest.cpp
@@ -1711,11 +1711,11 @@
* Test that colorfilterimagefilter does not require its CTM to be decomposed when it has more
* than just scale/translate, but that other filters do.
*/
-DEF_TEST(ImageFilterDecomposeCTM, reporter) {
+DEF_TEST(ImageFilterComplexCTM, reporter) {
// just need a colorfilter to exercise the corresponding imagefilter
sk_sp<SkColorFilter> cf = SkColorFilter::MakeModeFilter(SK_ColorRED, SkXfermode::kSrcATop_Mode);
- sk_sp<SkImageFilter> cfif = SkColorFilterImageFilter::Make(cf, nullptr);
- sk_sp<SkImageFilter> blif = SkBlurImageFilter::Make(3, 3, nullptr);
+ sk_sp<SkImageFilter> cfif = SkColorFilterImageFilter::Make(cf, nullptr); // can handle
+ sk_sp<SkImageFilter> blif = SkBlurImageFilter::Make(3, 3, nullptr); // cannot handle
struct {
sk_sp<SkImageFilter> fFilter;
@@ -1724,13 +1724,17 @@
{ cfif, true },
{ SkColorFilterImageFilter::Make(cf, cfif), true },
{ SkMergeImageFilter::Make(cfif, cfif), true },
+ { SkComposeImageFilter::Make(cfif, cfif), true },
+
{ blif, false },
- { SkMergeImageFilter::Make(cfif, blif), false },
+ { SkBlurImageFilter::Make(3, 3, cfif), false },
{ SkColorFilterImageFilter::Make(cf, blif), false },
+ { SkMergeImageFilter::Make(cfif, blif), false },
+ { SkComposeImageFilter::Make(blif, cfif), false },
};
for (const auto& rec : recs) {
- const bool canHandle = rec.fFilter->canHandleAffine();
+ const bool canHandle = rec.fFilter->canHandleComplexCTM();
REPORTER_ASSERT(reporter, canHandle == rec.fExpectCanHandle);
}
}