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>
This commit is contained in:
parent
e97e792c79
commit
6e87eee2a0
57
gm/shadermaskfilter.cpp
Normal file
57
gm/shadermaskfilter.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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 "gm.h"
|
||||
#include "sk_tool_utils.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkImage.h"
|
||||
#include "SkShaderMaskFilter.h"
|
||||
|
||||
static void draw_masked_image(SkCanvas* canvas, const SkImage* image, SkScalar x, SkScalar y,
|
||||
const SkImage* mask) {
|
||||
SkMatrix matrix = SkMatrix::MakeScale(SkIntToScalar(image->width()) / mask->width(),
|
||||
SkIntToScalar(image->height() / mask->height()));
|
||||
SkPaint paint;
|
||||
paint.setMaskFilter(SkShaderMaskFilter::Make(mask->makeShader(&matrix)));
|
||||
canvas->drawImage(image, x, y, &paint);
|
||||
}
|
||||
|
||||
#include "SkGradientShader.h"
|
||||
static sk_sp<SkShader> make_shader(const SkRect& r) {
|
||||
const SkPoint pts[] = {
|
||||
{ r.fLeft, r.fTop }, { r.fRight, r.fBottom },
|
||||
};
|
||||
const SkColor colors[] = { 0, SK_ColorWHITE };
|
||||
return SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkShader::kRepeat_TileMode);
|
||||
}
|
||||
|
||||
DEF_SIMPLE_GM(shadermaskfilter_gradient, canvas, 512, 512) {
|
||||
SkRect r = { 0, 0, 100, 150 };
|
||||
auto shader = make_shader(r);
|
||||
auto mf = SkShaderMaskFilter::Make(shader);
|
||||
|
||||
canvas->translate(20, 20);
|
||||
canvas->scale(2, 2);
|
||||
|
||||
SkPaint paint;
|
||||
paint.setMaskFilter(mf);
|
||||
paint.setColor(SK_ColorRED);
|
||||
canvas->drawOval(r, paint);
|
||||
}
|
||||
|
||||
#include "Resources.h"
|
||||
DEF_SIMPLE_GM(shadermaskfilter_image, canvas, 512, 512) {
|
||||
canvas->scale(1.25f, 1.25f);
|
||||
|
||||
auto image = GetResourceAsImage("images/mandrill_128.png");
|
||||
auto mask = GetResourceAsImage("images/color_wheel.png");
|
||||
|
||||
canvas->drawImage(image, 10, 10, nullptr);
|
||||
canvas->drawImage(mask, 10 + image->width() + 10.f, 10, nullptr);
|
||||
|
||||
draw_masked_image(canvas, image.get(), 10, 10 + image->height() + 10.f, mask.get());
|
||||
}
|
@ -52,6 +52,7 @@ skia_effects_sources = [
|
||||
"$_src/effects/SkPaintImageFilter.cpp",
|
||||
"$_src/effects/SkPictureImageFilter.cpp",
|
||||
"$_src/effects/SkRRectsGaussianEdgeMaskFilter.cpp",
|
||||
"$_src/effects/SkShaderMaskFilter.cpp",
|
||||
"$_src/effects/SkTableColorFilter.cpp",
|
||||
"$_src/effects/SkTableMaskFilter.cpp",
|
||||
"$_src/effects/SkTileImageFilter.cpp",
|
||||
|
@ -263,6 +263,7 @@ gm_sources = [
|
||||
"$_gm/samplerstress.cpp",
|
||||
"$_gm/savelayer.cpp",
|
||||
"$_gm/scaledstrokes.cpp",
|
||||
"$_gm/shadermaskfilter.cpp",
|
||||
"$_gm/shadertext.cpp",
|
||||
"$_gm/shadertext2.cpp",
|
||||
"$_gm/shadertext3.cpp",
|
||||
|
24
include/effects/SkShaderMaskFilter.h
Normal file
24
include/effects/SkShaderMaskFilter.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkShaderMaskFilter_DEFINED
|
||||
#define SkShaderMaskFilter_DEFINED
|
||||
|
||||
#include "SkMaskFilter.h"
|
||||
|
||||
class SkShader;
|
||||
|
||||
class SK_API SkShaderMaskFilter {
|
||||
public:
|
||||
static sk_sp<SkMaskFilter> Make(sk_sp<SkShader> shader);
|
||||
|
||||
private:
|
||||
static void InitializeFlattenables();
|
||||
friend class SkFlattenable;
|
||||
};
|
||||
|
||||
#endif
|
117
src/effects/SkShaderMaskFilter.cpp
Normal file
117
src/effects/SkShaderMaskFilter.cpp
Normal file
@ -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
|
@ -37,6 +37,7 @@
|
||||
#include "SkPerlinNoiseShader.h"
|
||||
#include "SkPictureImageFilter.h"
|
||||
#include "SkRRectsGaussianEdgeMaskFilter.h"
|
||||
#include "SkShaderMaskFilter.h"
|
||||
#include "SkTableColorFilter.h"
|
||||
#include "SkTileImageFilter.h"
|
||||
#include "SkToSRGBColorFilter.h"
|
||||
@ -64,6 +65,7 @@ void SkFlattenable::PrivateInitializer::InitEffects() {
|
||||
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkEmbossMaskFilter)
|
||||
SkBlurMaskFilter::InitializeFlattenables();
|
||||
SkRRectsGaussianEdgeMaskFilter::InitializeFlattenables();
|
||||
SkShaderMaskFilter::InitializeFlattenables();
|
||||
|
||||
// DrawLooper
|
||||
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLayerDrawLooper)
|
||||
|
Loading…
Reference in New Issue
Block a user