Flutter Engine
The Flutter Engine
SkBlitter_A8.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2006 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
9
13#include "include/core/SkRect.h"
14#include "include/core/SkShader.h" // IWYU pragma: keep
18#include "src/core/SkMask.h"
19
20#include <cstring>
21#include <optional>
22
24 : fDevice(device)
25{
26 SkASSERT(nullptr == paint.getShader());
27 SkASSERT(nullptr == paint.getColorFilter());
28}
29
30void SkA8_Coverage_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
31 const int16_t runs[]) {
32 uint8_t* device = fDevice.writable_addr8(x, y);
33 SkDEBUGCODE(int totalCount = 0;)
34
35 for (;;) {
36 int count = runs[0];
37 SkASSERT(count >= 0);
38 if (count == 0) {
39 return;
40 }
41 if (antialias[0]) {
42 memset(device, antialias[0], count);
43 }
44 runs += count;
45 antialias += count;
46 device += count;
47
48 SkDEBUGCODE(totalCount += count;)
49 }
50 SkASSERT(fDevice.width() == totalCount);
51}
52
54 memset(fDevice.writable_addr8(x, y), 0xFF, width);
55}
56
57void SkA8_Coverage_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
58 if (0 == alpha) {
59 return;
60 }
61
62 uint8_t* dst = fDevice.writable_addr8(x, y);
63 const size_t dstRB = fDevice.rowBytes();
64 while (--height >= 0) {
65 *dst = alpha;
66 dst += dstRB;
67 }
68}
69
71 uint8_t* dst = fDevice.writable_addr8(x, y);
72 const size_t dstRB = fDevice.rowBytes();
73 while (--height >= 0) {
74 memset(dst, 0xFF, width);
75 dst += dstRB;
76 }
77}
78
80 if (SkMask::kA8_Format != mask.fFormat) {
81 this->SkBlitter::blitMask(mask, clip);
82 return;
83 }
84
85 int x = clip.fLeft;
86 int y = clip.fTop;
87 int width = clip.width();
88 int height = clip.height();
89
90 uint8_t* dst = fDevice.writable_addr8(x, y);
91 const uint8_t* src = mask.getAddr8(x, y);
92 const size_t srcRB = mask.fRowBytes;
93 const size_t dstRB = fDevice.rowBytes();
94
95 while (--height >= 0) {
96 memcpy(dst, src, width);
97 dst += dstRB;
98 src += srcRB;
99 }
100}
101
102//////////////
103
104static inline uint8_t div255(unsigned prod) {
105 SkASSERT(prod <= 255*255);
106 return (prod + 128) * 257 >> 16;
107}
108
109static inline unsigned u8_lerp(uint8_t a, uint8_t b, uint8_t t) {
110 return div255((255 - t) * a + t * b);
111}
112
113using AlphaProc = uint8_t(*)(uint8_t src, uint8_t dst);
114
115static uint8_t srcover_p (uint8_t src, uint8_t dst) { return src + div255((255 - src) * dst); }
116static uint8_t src_p (uint8_t src, uint8_t dst) { return src; }
117
118template <typename Mode> void A8_row_bw(uint8_t dst[], uint8_t src, int N, Mode proc) {
119 for (int i = 0; i < N; ++i) {
120 dst[i] = proc(src, dst[i]);
121 }
122}
123using A8_RowBlitBW = void(*)(uint8_t[], uint8_t, int);
124
125template <typename Mode>
126void A8_row_aa(uint8_t dst[], uint8_t src, int N, uint8_t aa, Mode proc, const bool canFoldAA) {
127 if (canFoldAA) {
128 src = div255(src * aa);
129 for (int i = 0; i < N; ++i) {
130 dst[i] = proc(src, dst[i]);
131 }
132 } else {
133 for (int i = 0; i < N; ++i) {
134 dst[i] = u8_lerp(dst[i], proc(src, dst[i]), aa);
135 }
136 }
137}
138using A8_RowBlitAA = void(*)(uint8_t[], uint8_t, int, uint8_t aa);
139
140#define WRAP_BLIT(proc, canFoldAA) \
141 proc, \
142 [](uint8_t dst[], uint8_t src, int N) \
143 { A8_row_bw(dst, src, N, proc); }, \
144 [](uint8_t dst[], uint8_t src, int N, uint8_t aa) \
145 { A8_row_aa(dst, src, N, aa, proc, canFoldAA); }
146
152};
156};
157#undef WRAP_BLIT
158
160 for (auto& pair : gA8_RowBlitPairs) {
161 if (pair.mode == bm) {
162 return &pair;
163 }
164 }
165 return nullptr;
166}
167
168class SkA8_Blitter : public SkBlitter {
169public:
170 SkA8_Blitter(const SkPixmap& device, const SkPaint& paint);
171 void blitH(int x, int y, int width) override;
172 void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override;
173 void blitV(int x, int y, int height, SkAlpha alpha) override;
174 void blitRect(int x, int y, int width, int height) override;
175 void blitMask(const SkMask&, const SkIRect&) override;
176
177private:
178 const SkPixmap fDevice;
179 AlphaProc fOneProc;
180 A8_RowBlitBW fBWProc;
181 A8_RowBlitAA fAAProc;
182 SkAlpha fSrc;
183
184 using INHERITED = SkBlitter;
185};
186
188 const SkPaint& paint) : fDevice(device) {
189 SkASSERT(nullptr == paint.getShader());
190 SkASSERT(nullptr == paint.getColorFilter());
191 auto mode = paint.asBlendMode();
192 SkASSERT(mode);
193 auto pair = find_a8_rowproc_pair(*mode);
194 SkASSERT(pair);
195
196 fOneProc = pair->oneProc;
197 fBWProc = pair->bwProc;
198 fAAProc = pair->aaProc;
199 fSrc = paint.getAlpha();
200}
201
202void SkA8_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) {
203 uint8_t* device = fDevice.writable_addr8(x, y);
204 SkDEBUGCODE(int totalCount = 0;)
205
206 for (;;) {
207 int count = runs[0];
208 SkASSERT(count >= 0);
209 if (count == 0) {
210 return;
211 }
212
213 if (antialias[0] == 0xFF) {
214 fBWProc(device, fSrc, count);
215 } else if (antialias[0] != 0) {
216 fAAProc(device, fSrc, count, antialias[0]);
217 }
218
219 runs += count;
220 antialias += count;
221 device += count;
222
223 SkDEBUGCODE(totalCount += count;)
224 }
225 SkASSERT(fDevice.width() == totalCount);
226}
227
228void SkA8_Blitter::blitH(int x, int y, int width) {
229 fBWProc(fDevice.writable_addr8(x, y), fSrc, width);
230}
231
232void SkA8_Blitter::blitV(int x, int y, int height, SkAlpha aa) {
233 uint8_t* device = fDevice.writable_addr8(x, y);
234 const size_t dstRB = fDevice.rowBytes();
235
236 if (aa == 0xFF) {
237 while (--height >= 0) {
238 *device = fOneProc(fSrc, *device);
239 device += dstRB;
240 }
241 } else if (aa != 0) {
242 while (--height >= 0) {
243 fAAProc(device, fSrc, 1, aa);
244 device += dstRB;
245 }
246 }
247}
248
249void SkA8_Blitter::blitRect(int x, int y, int width, int height) {
250 uint8_t* device = fDevice.writable_addr8(x, y);
251 const size_t dstRB = fDevice.rowBytes();
252
253 while (--height >= 0) {
254 fBWProc(device, fSrc, width);
255 device += dstRB;
256 }
257}
258
259void SkA8_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
260 if (SkMask::kA8_Format != mask.fFormat) {
261 this->INHERITED::blitMask(mask, clip);
262 return;
263 }
264
265 int x = clip.fLeft;
266 int y = clip.fTop;
267 int width = clip.width();
268 int height = clip.height();
269
270 uint8_t* dst = fDevice.writable_addr8(x, y);
271 const uint8_t* src = mask.getAddr8(x, y);
272 const size_t srcRB = mask.fRowBytes;
273 const size_t dstRB = fDevice.rowBytes();
274
275 while (--height >= 0) {
276 for (int i = 0; i < width; ++i) {
277 dst[i] = u8_lerp(dst[i], fOneProc(fSrc, dst[i]), src[i]);
278 }
279 dst += dstRB;
280 src += srcRB;
281 }
282}
283
284//////////////////
285
287 const SkMatrix& ctm,
288 const SkPaint& paint,
289 SkArenaAlloc* alloc,
290 bool drawCoverage,
291 sk_sp<SkShader> clipShader,
292 const SkSurfaceProps&) {
293 if (dst.colorType() != SkColorType::kAlpha_8_SkColorType) {
294 return nullptr;
295 }
296 if (paint.getShader() || paint.getColorFilter()) {
297 return nullptr;
298 }
299 if (clipShader) {
300 return nullptr; // would not be hard to support ...?
301 }
302
303 if (drawCoverage) {
304 return alloc->make<SkA8_Coverage_Blitter>(dst, paint);
305 } else {
306 // we only support certain blendmodes...
307 auto mode = paint.asBlendMode();
308 if (mode && find_a8_rowproc_pair(*mode)) {
309 return alloc->make<SkA8_Blitter>(dst, paint);
310 }
311 }
312 return nullptr;
313}
314
int count
Definition: FontMgrTest.cpp:50
#define SkASSERT(cond)
Definition: SkAssert.h:116
SkBlendMode
Definition: SkBlendMode.h:38
@ kSrcOver
r = s + (1-sa)*d
constexpr A8_RowBlitBWPair gA8_RowBlitPairs[]
static uint8_t srcover_p(uint8_t src, uint8_t dst)
void(*)(uint8_t[], uint8_t, int, uint8_t aa) A8_RowBlitAA
void A8_row_bw(uint8_t dst[], uint8_t src, int N, Mode proc)
#define WRAP_BLIT(proc, canFoldAA)
void A8_row_aa(uint8_t dst[], uint8_t src, int N, uint8_t aa, Mode proc, const bool canFoldAA)
uint8_t(*)(uint8_t src, uint8_t dst) AlphaProc
static uint8_t div255(unsigned prod)
static const A8_RowBlitBWPair * find_a8_rowproc_pair(SkBlendMode bm)
void(*)(uint8_t[], uint8_t, int) A8_RowBlitBW
static unsigned u8_lerp(uint8_t a, uint8_t b, uint8_t t)
SkBlitter * SkA8Blitter_Choose(const SkPixmap &dst, const SkMatrix &ctm, const SkPaint &paint, SkArenaAlloc *alloc, bool drawCoverage, sk_sp< SkShader > clipShader, const SkSurfaceProps &)
static uint8_t src_p(uint8_t src, uint8_t dst)
@ kAlpha_8_SkColorType
pixel with alpha in 8-bit byte
Definition: SkColorType.h:21
uint8_t SkAlpha
Definition: SkColor.h:26
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition: SkPath.cpp:3892
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
#define N
Definition: beziers.cpp:19
void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override
SkA8_Blitter(const SkPixmap &device, const SkPaint &paint)
void blitV(int x, int y, int height, SkAlpha alpha) override
Blit a vertical run of pixels with a constant alpha value.
void blitH(int x, int y, int width) override
Blit a horizontal run of one or more pixels.
void blitMask(const SkMask &, const SkIRect &) override
void blitRect(int x, int y, int width, int height) override
Blit a solid rectangle one or more pixels wide.
void blitMask(const SkMask &, const SkIRect &) override
void blitRect(int x, int y, int width, int height) override
Blit a solid rectangle one or more pixels wide.
void blitH(int x, int y, int width) override
Blit a horizontal run of one or more pixels.
SkA8_Coverage_Blitter(const SkPixmap &device, const SkPaint &paint)
void blitV(int x, int y, int height, SkAlpha alpha) override
Blit a vertical run of pixels with a constant alpha value.
void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override
auto make(Ctor &&ctor) -> decltype(ctor(nullptr))
Definition: SkArenaAlloc.h:120
virtual void blitMask(const SkMask &, const SkIRect &clip)
Definition: SkBlitter.cpp:201
size_t rowBytes() const
Definition: SkPixmap.h:145
int width() const
Definition: SkPixmap.h:160
uint8_t * writable_addr8(int x, int y) const
Definition: SkPixmap.h:508
const Paint & paint
Definition: color_source.cc:38
VkDevice device
Definition: main.cc:53
static bool b
struct MyStruct a[10]
double y
double x
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
Definition: switches.h:228
dst
Definition: cp.py:12
int32_t height
int32_t width
SkBlendMode mode
A8_RowBlitBW bwProc
A8_RowBlitAA aaProc
Definition: SkRect.h:32
Definition: SkMask.h:25
const uint32_t fRowBytes
Definition: SkMask.h:43
@ kA8_Format
8bits per pixel mask (e.g. antialiasing)
Definition: SkMask.h:28
const uint8_t * getAddr8(int x, int y) const
Definition: SkMask.h:79
const Format fFormat
Definition: SkMask.h:44