aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/effects
diff options
context:
space:
mode:
authorGravatar Mike Reed <reed@google.com>2018-01-18 16:06:54 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-01-18 21:24:38 +0000
commit6e87eee2a0494e11610e5535427a9f86ccffa4bb (patch)
treed035bf913332edbcd746527cdc211c6938eb609d /src/effects
parente97e792c79afd01fe1d83e5d1e94918145794c54 (diff)
add shadermaskfilter
next steps: - gpu impl (will look a lot like shader's asFragProcessor - special-case rect-input (?) - explore stages w/ mtklein Bug: skia:7500 Change-Id: I71089e421d32443a3ddded6967b3e5bc67ed43f2 Reviewed-on: https://skia-review.googlesource.com/95104 Commit-Queue: Mike Reed <reed@google.com> Reviewed-by: Florin Malita <fmalita@chromium.org> Reviewed-by: Brian Salomon <bsalomon@google.com>
Diffstat (limited to 'src/effects')
-rw-r--r--src/effects/SkShaderMaskFilter.cpp117
1 files changed, 117 insertions, 0 deletions
diff --git a/src/effects/SkShaderMaskFilter.cpp b/src/effects/SkShaderMaskFilter.cpp
new file mode 100644
index 0000000000..8693751899
--- /dev/null
+++ b/src/effects/SkShaderMaskFilter.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkCanvas.h"
+#include "SkReadBuffer.h"
+#include "SkShaderMaskFilter.h"
+#include "SkShader.h"
+#include "SkString.h"
+
+class SkShaderMF : public SkMaskFilter {
+public:
+ SkShaderMF(sk_sp<SkShader> shader) : fShader(std::move(shader)) {}
+
+ SkMask::Format getFormat() const override { return SkMask::kA8_Format; }
+
+ bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&,
+ SkIPoint* margin) const override;
+
+ void computeFastBounds(const SkRect& src, SkRect* dst) const override {
+ *dst = src;
+ }
+
+ bool asABlur(BlurRec*) const override { return false; }
+
+ SK_TO_STRING_OVERRIDE()
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkShaderMF)
+
+private:
+ sk_sp<SkShader> fShader;
+
+ SkShaderMF(SkReadBuffer&);
+ void flatten(SkWriteBuffer&) const override;
+
+ friend class SkShaderMaskFilter;
+
+ typedef SkMaskFilter INHERITED;
+};
+
+#ifndef SK_IGNORE_TO_STRING
+void SkShaderMF::toString(SkString* str) const {
+ str->set("SkShaderMF:");
+}
+#endif
+
+sk_sp<SkFlattenable> SkShaderMF::CreateProc(SkReadBuffer& buffer) {
+ return SkShaderMaskFilter::Make(buffer.readShader());
+}
+
+void SkShaderMF::flatten(SkWriteBuffer& buffer) const {
+ buffer.writeFlattenable(fShader.get());
+}
+
+static void rect_memcpy(void* dst, size_t dstRB, const void* src, size_t srcRB,
+ size_t copyBytes, int rows) {
+ for (int i = 0; i < rows; ++i) {
+ memcpy(dst, src, copyBytes);
+ dst = (char*)dst + dstRB;
+ src = (const char*)src + srcRB;
+ }
+}
+
+bool SkShaderMF::filterMask(SkMask* dst, const SkMask& src, const SkMatrix& ctm,
+ SkIPoint* margin) const {
+ SkASSERT(src.fFormat == SkMask::kA8_Format);
+
+ if (margin) {
+ margin->set(0, 0);
+ }
+ dst->fBounds = src.fBounds;
+ dst->fRowBytes = src.fBounds.width(); // need alignment?
+ dst->fFormat = SkMask::kA8_Format;
+
+ if (src.fImage == nullptr) {
+ dst->fImage = nullptr;
+ return true;
+ }
+ size_t size = dst->computeImageSize();
+ if (0 == size) {
+ return false; // too big to allocate, abort
+ }
+
+ // Allocate and initialize dst image with a copy of the src image
+ dst->fImage = SkMask::AllocImage(size);
+ rect_memcpy(dst->fImage, dst->fRowBytes, src.fImage, src.fRowBytes,
+ src.fBounds.width() * sizeof(uint8_t), src.fBounds.height());
+
+ // Now we have a dst-mask, just need to setup a canvas and draw into it
+ SkBitmap bitmap;
+ if (!bitmap.installMaskPixels(*dst)) {
+ return false;
+ }
+
+ SkPaint paint;
+ paint.setShader(fShader);
+ // this blendmode is the trick: we only draw the shader where the mask is
+ paint.setBlendMode(SkBlendMode::kSrcIn);
+
+ SkCanvas canvas(bitmap);
+ canvas.translate(-SkIntToScalar(dst->fBounds.fLeft), -SkIntToScalar(dst->fBounds.fTop));
+ canvas.concat(ctm);
+ canvas.drawPaint(paint);
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+sk_sp<SkMaskFilter> SkShaderMaskFilter::Make(sk_sp<SkShader> shader) {
+ return shader ? sk_sp<SkMaskFilter>(new SkShaderMF(std::move(shader))) : nullptr;
+}
+
+SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkShaderMaskFilter)
+ SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkShaderMF)
+SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END