Index: src/core/SkLocalMatrixImageFilter.cpp |
diff --git a/src/core/SkLocalMatrixImageFilter.cpp b/src/core/SkLocalMatrixImageFilter.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ff84f9d497620a07041d0116fd4ccc61176c5aca |
--- /dev/null |
+++ b/src/core/SkLocalMatrixImageFilter.cpp |
@@ -0,0 +1,256 @@ |
+/* |
+ * Copyright 2015 Google Inc. |
+ * |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+ |
+#include "SkImageFilter.h" |
+#include "SkReadBuffer.h" |
+#include "SkString.h" |
+ |
+/** |
+ * Wraps another imagefilter + matrix, such that using this filter will give the same result |
+ * as using the wrapped filter with the matrix applied to its context. |
+ */ |
+class SkLocalMatrixImageFilter : public SkImageFilter { |
+public: |
+ static SkImageFilter* Create(SkImageFilter* base, const SkMatrix& localM) { |
+ if (localM.getType() & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) { |
+ return nullptr; |
+ } |
+ if (localM.isIdentity()) { |
+ // return SkRef(base); |
+ } |
+ return new SkLocalMatrixImageFilter(base, localM); |
+ } |
+ |
+ void computeFastBounds(const SkRect&, SkRect*) const override; |
+ |
+ SK_TO_STRING_OVERRIDE() |
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLocalMatrixImageFilter) |
+ |
+protected: |
+ bool onIsColorFilterNode(SkColorFilter** /*filterPtr*/) const override; |
+ bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&, |
+ const SkIRect& bounds) const override; |
+ bool affectsTransparentBlack() const override; |
+ bool canComputeFastBounds() const override; |
+ |
+ void flatten(SkWriteBuffer&) const override; |
+ bool onFilterImage(Proxy*, const SkBitmap& src, const Context&, |
+ SkBitmap* result, SkIPoint* offset) const override; |
+ bool onFilterBounds(const SkIRect& src, const SkMatrix&, SkIRect* dst) const override; |
+ bool canFilterImageGPU() const override; |
+ bool filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx, |
+ SkBitmap* result, SkIPoint* offset) const override; |
+ bool usesSrcInput() const override; |
+ |
+ bool applyCropRect(const Context&, const SkBitmap& src, const SkIPoint& srcOffset, |
+ SkIRect* bounds) const override; |
+ bool applyCropRect(const Context&, Proxy* proxy, const SkBitmap& src, |
+ SkIPoint* srcOffset, SkIRect* bounds, SkBitmap* result) const override; |
+ |
+private: |
+ SkLocalMatrixImageFilter(SkImageFilter* base, const SkMatrix& localM) |
+ : INHERITED(0, nullptr), fBase(SkRef(base)), fLocalM(localM) |
+ {} |
+ |
+ SkAutoTUnref<SkImageFilter> fBase; |
+ SkMatrix fLocalM; |
+ |
+ typedef SkImageFilter INHERITED; |
+}; |
+ |
+static SkMatrix concat(const SkMatrix& a, const SkMatrix& b) { |
+ SkMatrix c; |
+ c.setConcat(a, b); |
+ return c; |
+} |
+ |
+SkFlattenable* SkLocalMatrixImageFilter::CreateProc(SkReadBuffer& buffer) { |
+ SkMatrix lm; |
+ buffer.readMatrix(&lm); |
+ SkAutoTUnref<SkImageFilter> filter(buffer.readImageFilter()); |
+ if (!filter) { |
+ return nullptr; |
+ } |
+ return SkLocalMatrixImageFilter::Create(filter, lm); |
+} |
+ |
+bool SkLocalMatrixImageFilter::onIsColorFilterNode(SkColorFilter** filterPtr) const { |
+ return fBase->onIsColorFilterNode(filterPtr); |
+} |
+ |
+bool SkLocalMatrixImageFilter::asFragmentProcessor(GrFragmentProcessor** procs, GrTexture* tex, |
+ const SkMatrix& matrix, |
+ const SkIRect& bounds) const { |
+ return fBase->asFragmentProcessor(procs, tex, concat(matrix, fLocalM), bounds); |
+} |
+ |
+bool SkLocalMatrixImageFilter::affectsTransparentBlack() const { |
+ return fBase->affectsTransparentBlack(); |
+} |
+ |
+bool SkLocalMatrixImageFilter::canComputeFastBounds() const { |
+ return fBase->canComputeFastBounds(); |
+} |
+ |
+bool SkLocalMatrixImageFilter::usesSrcInput() const { |
+ return fBase->usesSrcInput(); |
+} |
+ |
+void SkLocalMatrixImageFilter::flatten(SkWriteBuffer& buffer) const { |
+ buffer.writeMatrix(fLocalM); |
+ buffer.writeFlattenable(fBase); |
+} |
+ |
+void SkLocalMatrixImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const { |
+ fBase->computeFastBounds(src, dst); |
+} |
+ |
+bool SkLocalMatrixImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, const Context& ctx, |
+ SkBitmap* result, SkIPoint* offset) const { |
+ Context localCtx(concat(ctx.ctm(), fLocalM), ctx.clipBounds(), ctx.cache()); |
+ return fBase->onFilterImage(proxy, src, localCtx, result, offset); |
+} |
+ |
+bool SkLocalMatrixImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& matrix, |
+ SkIRect* dst) const { |
+ return fBase->onFilterBounds(src, concat(matrix, fLocalM), dst); |
+} |
+ |
+bool SkLocalMatrixImageFilter::canFilterImageGPU() const { |
+ return fBase->canFilterImageGPU(); |
+} |
+ |
+bool SkLocalMatrixImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx, |
+ SkBitmap* result, SkIPoint* offset) const { |
+ Context localCtx(concat(ctx.ctm(), fLocalM), ctx.clipBounds(), ctx.cache()); |
+ return fBase->filterImageGPU(proxy, src, localCtx, result, offset); |
+} |
+ |
+#ifndef SK_IGNORE_TO_STRING |
+void SkLocalMatrixImageFilter::toString(SkString* str) const { |
+ str->append("SkLocalMatrixImageFilter: ("); |
+ fBase->toString(str); |
+ str->append(")"); |
+} |
+#endif |
+ |
+bool SkLocalMatrixImageFilter::applyCropRect(const Context& ctx, const SkBitmap& src, |
+ const SkIPoint& srcOffset, SkIRect* bounds) const { |
+ Context localCtx(concat(ctx.ctm(), fLocalM), ctx.clipBounds(), ctx.cache()); |
+ return fBase->applyCropRect(localCtx, src, srcOffset, bounds); |
+} |
+ |
+bool SkLocalMatrixImageFilter::applyCropRect(const Context& ctx, Proxy* proxy, const SkBitmap& src, |
+ SkIPoint* srcOffset, SkIRect* bounds, |
+ SkBitmap* result) const { |
+ Context localCtx(concat(ctx.ctm(), fLocalM), ctx.clipBounds(), ctx.cache()); |
+ return fBase->applyCropRect(localCtx, proxy, src, srcOffset, bounds, result); |
+} |
+ |
+/////////////////////////////////////////////////////////////////////////////////////////////////// |
+ |
+class SkLocalMatrixImageFilterAsInput : public SkImageFilter { |
+public: |
+ static SkImageFilter* Create(SkImageFilter* base, const SkMatrix& localM) { |
+ if (localM.getType() & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) { |
+ return nullptr; |
+ } |
+ if (localM.isIdentity()) { |
+ // return SkRef(base); |
+ } |
+ return new SkLocalMatrixImageFilterAsInput(base, localM); |
+ } |
+ |
+ SK_TO_STRING_OVERRIDE() |
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLocalMatrixImageFilterAsInput) |
+ |
+protected: |
+ bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&, |
+ const SkIRect& bounds) const override; |
+ |
+ void flatten(SkWriteBuffer&) const override; |
+ bool onFilterImage(Proxy*, const SkBitmap& src, const Context&, |
+ SkBitmap* result, SkIPoint* offset) const override; |
+ bool onFilterBounds(const SkIRect& src, const SkMatrix&, SkIRect* dst) const override; |
+ |
+ bool applyCropRect(const Context&, const SkBitmap& src, const SkIPoint& srcOffset, |
+ SkIRect* bounds) const override; |
+ bool applyCropRect(const Context&, Proxy* proxy, const SkBitmap& src, |
+ SkIPoint* srcOffset, SkIRect* bounds, SkBitmap* result) const override; |
+ |
+private: |
+ SkLocalMatrixImageFilterAsInput(SkImageFilter* base, const SkMatrix& localM) |
+ : INHERITED(1, &base, nullptr), fLocalM(localM) |
+ {} |
+ |
+ SkMatrix fLocalM; |
+ |
+ typedef SkImageFilter INHERITED; |
+}; |
+ |
+SkFlattenable* SkLocalMatrixImageFilterAsInput::CreateProc(SkReadBuffer& buffer) { |
+ SkMatrix lm; |
+ buffer.readMatrix(&lm); |
+ SkAutoTUnref<SkImageFilter> filter(buffer.readImageFilter()); |
+ if (!filter) { |
+ return nullptr; |
+ } |
+ return SkLocalMatrixImageFilter::Create(filter, lm); |
+} |
+ |
+bool SkLocalMatrixImageFilterAsInput::asFragmentProcessor(GrFragmentProcessor** procs, |
+ GrTexture* tex, const SkMatrix& matrix, |
+ const SkIRect& bounds) const { |
+ return this->INHERITED::asFragmentProcessor(procs, tex, concat(matrix, fLocalM), bounds); |
+} |
+ |
+void SkLocalMatrixImageFilterAsInput::flatten(SkWriteBuffer& buffer) const { |
+ buffer.writeMatrix(fLocalM); |
+ this->INHERITED::flatten(buffer); |
+} |
+ |
+bool SkLocalMatrixImageFilterAsInput::onFilterImage(Proxy* proxy, const SkBitmap& src, |
+ const Context& ctx, SkBitmap* result, |
+ SkIPoint* offset) const { |
+ Context localCtx(concat(ctx.ctm(), fLocalM), ctx.clipBounds(), ctx.cache()); |
+ return this->INHERITED::onFilterImage(proxy, src, localCtx, result, offset); |
+} |
+ |
+bool SkLocalMatrixImageFilterAsInput::onFilterBounds(const SkIRect& src, const SkMatrix& matrix, |
+ SkIRect* dst) const { |
+ return this->INHERITED::onFilterBounds(src, concat(matrix, fLocalM), dst); |
+} |
+ |
+#ifndef SK_IGNORE_TO_STRING |
+void SkLocalMatrixImageFilterAsInput::toString(SkString* str) const { |
+ str->append("SkLocalMatrixImageFilterAsInput: ("); |
+ this->getInput(0)->toString(str); |
+ str->append(")"); |
+} |
+#endif |
+ |
+bool SkLocalMatrixImageFilterAsInput::applyCropRect(const Context& ctx, const SkBitmap& src, |
+ const SkIPoint& srcOffset, |
+ SkIRect* bounds) const { |
+ Context localCtx(concat(ctx.ctm(), fLocalM), ctx.clipBounds(), ctx.cache()); |
+ return this->INHERITED::applyCropRect(localCtx, src, srcOffset, bounds); |
+} |
+ |
+bool SkLocalMatrixImageFilterAsInput::applyCropRect(const Context& ctx, Proxy* proxy, |
+ const SkBitmap& src, |
+ SkIPoint* srcOffset, SkIRect* bounds, |
+ SkBitmap* result) const { |
+ Context localCtx(concat(ctx.ctm(), fLocalM), ctx.clipBounds(), ctx.cache()); |
+ return this->INHERITED::applyCropRect(localCtx, proxy, src, srcOffset, bounds, result); |
+} |
+ |
+/////////////////////////////////////////////////////////////////////////////////////////////////// |
+ |
+SkImageFilter* SkImageFilter::newWithLocalMatrix(const SkMatrix& localMatrix) const { |
+// return SkLocalMatrixImageFilterAsInput::Create(const_cast<SkImageFilter*>(this), localMatrix); |
+ return SkLocalMatrixImageFilter::Create(const_cast<SkImageFilter*>(this), localMatrix); |
+} |