1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
/*
* 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 "SkMaskFilterBase.h"
#include "SkReadBuffer.h"
#include "SkShaderMaskFilter.h"
#include "SkShaderBase.h"
#include "SkString.h"
class SkShaderMF : public SkMaskFilterBase {
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; }
void toString(SkString* str) const override;
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkShaderMF)
protected:
#if SK_SUPPORT_GPU
std::unique_ptr<GrFragmentProcessor> onAsFragmentProcessor(const GrFPArgs&) const override;
bool onHasFragmentProcessor() const override;
#endif
private:
sk_sp<SkShader> fShader;
SkShaderMF(SkReadBuffer&);
void flatten(SkWriteBuffer&) const override;
friend class SkShaderMaskFilter;
typedef SkMaskFilter INHERITED;
};
void SkShaderMF::toString(SkString* str) const {
str->set("SkShaderMF:");
}
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 {
if (src.fFormat != SkMask::kA8_Format) {
return false;
}
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);
paint.setFilterQuality(SkFilterQuality::kLow_SkFilterQuality);
// 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;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
#if SK_SUPPORT_GPU
#include "GrFragmentProcessor.h"
std::unique_ptr<GrFragmentProcessor> SkShaderMF::onAsFragmentProcessor(const GrFPArgs& args) const {
return GrFragmentProcessor::MulInputByChildAlpha(as_SB(fShader)->asFragmentProcessor(args));
}
bool SkShaderMF::onHasFragmentProcessor() const {
return true;
}
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////
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
|