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
8#ifndef SkBlitter_DEFINED
9#define SkBlitter_DEFINED
10
11#include "include/core/SkColor.h"
12#include "include/core/SkRect.h"
13#include "include/core/SkRegion.h"
14#include "include/private/SkTo.h"
15#include "src/core/SkAutoMalloc.h"
16#include "src/core/SkImagePriv.h"
17#include "src/shaders/SkShaderBase.h"
18
19class SkArenaAlloc;
20class SkMatrix;
21class SkMatrixProvider;
22class SkPaint;
23class SkPixmap;
24struct SkMask;
25
26/** SkBlitter and its subclasses are responsible for actually writing pixels
27 into memory. Besides efficiency, they handle clipping and antialiasing.
28 A SkBlitter subclass contains all the context needed to generate pixels
29 for the destination and how src/generated pixels map to the destination.
30 The coordinates passed to the blitX calls are in destination pixel space.
31*/
32class SkBlitter {
33public:
34 virtual ~SkBlitter();
35
36 /// Blit a horizontal run of one or more pixels.
37 virtual void blitH(int x, int y, int width) = 0;
38
39 /// Blit a horizontal run of antialiased pixels; runs[] is a *sparse*
40 /// zero-terminated run-length encoding of spans of constant alpha values.
41 /// The runs[] and antialias[] work together to represent long runs of pixels with the same
42 /// alphas. The runs[] contains the number of pixels with the same alpha, and antialias[]
43 /// contain the coverage value for that number of pixels. The runs[] (and antialias[]) are
44 /// encoded in a clever way. The runs array is zero terminated, and has enough entries for
45 /// each pixel plus one, in most cases some of the entries will not contain valid data. An entry
46 /// in the runs array contains the number of pixels (np) that have the same alpha value. The
47 /// next np value is found np entries away. For example, if runs[0] = 7, then the next valid
48 /// entry will by at runs[7]. The runs array and antialias[] are coupled by index. So, if the
49 /// np entry is at runs[45] = 12 then the alpha value can be found at antialias[45] = 0x88.
50 /// This would mean to use an alpha value of 0x88 for the next 12 pixels starting at pixel 45.
51 virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) = 0;
52
53 /// Blit a vertical run of pixels with a constant alpha value.
54 virtual void blitV(int x, int y, int height, SkAlpha alpha);
55
56 /// Blit a solid rectangle one or more pixels wide.
57 virtual void blitRect(int x, int y, int width, int height);
58
59 /** Blit a rectangle with one alpha-blended column on the left,
60 width (zero or more) opaque pixels, and one alpha-blended column
61 on the right.
62 The result will always be at least two pixels wide.
63 */
64 virtual void blitAntiRect(int x, int y, int width, int height,
65 SkAlpha leftAlpha, SkAlpha rightAlpha);
66
67 // Blit a rect in AA with size at least 3 x 3 (small rect has too many edge cases...)
68 void blitFatAntiRect(const SkRect& rect);
69
70 /// Blit a pattern of pixels defined by a rectangle-clipped mask;
71 /// typically used for text.
72 virtual void blitMask(const SkMask&, const SkIRect& clip);
73
74 /** If the blitter just sets a single value for each pixel, return the
75 bitmap it draws into, and assign value. If not, return nullptr and ignore
76 the value parameter.
77 */
78 virtual const SkPixmap* justAnOpaqueColor(uint32_t* value);
79
80 // (x, y), (x + 1, y)
81 virtual void blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) {
82 int16_t runs[3];
83 uint8_t aa[2];
84
85 runs[0] = 1;
86 runs[1] = 1;
87 runs[2] = 0;
88 aa[0] = SkToU8(a0);
89 aa[1] = SkToU8(a1);
90 this->blitAntiH(x, y, aa, runs);
91 }
92
93 // (x, y), (x, y + 1)
94 virtual void blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) {
95 int16_t runs[2];
96 uint8_t aa[1];
97
98 runs[0] = 1;
99 runs[1] = 0;
100 aa[0] = SkToU8(a0);
101 this->blitAntiH(x, y, aa, runs);
102 // reset in case the clipping blitter modified runs
103 runs[0] = 1;
104 runs[1] = 0;
105 aa[0] = SkToU8(a1);
106 this->blitAntiH(x, y + 1, aa, runs);
107 }
108
109 /**
110 * Special method just to identify the null blitter, which is returned
111 * from Choose() if the request cannot be fulfilled. Default impl
112 * returns false.
113 */
114 virtual bool isNullBlitter() const;
115
116 /**
117 * Special methods for blitters that can blit more than one row at a time.
118 * This function returns the number of rows that this blitter could optimally
119 * process at a time. It is still required to support blitting one scanline
120 * at a time.
121 */
122 virtual int requestRowsPreserved() const { return 1; }
123
124 /**
125 * This function allocates memory for the blitter that the blitter then owns.
126 * The memory can be used by the calling function at will, but it will be
127 * released when the blitter's destructor is called. This function returns
128 * nullptr if no persistent memory is needed by the blitter.
129 */
130 virtual void* allocBlitMemory(size_t sz) {
131 return fBlitMemory.reset(sz, SkAutoMalloc::kReuse_OnShrink);
132 }
133
134 ///@name non-virtual helpers
135 void blitMaskRegion(const SkMask& mask, const SkRegion& clip);
136 void blitRectRegion(const SkIRect& rect, const SkRegion& clip);
137 void blitRegion(const SkRegion& clip);
138 ///@}
139
140 /** @name Factories
141 Return the correct blitter to use given the specified context.
142 */
143 static SkBlitter* Choose(const SkPixmap& dst,
144 const SkMatrixProvider& matrixProvider,
145 const SkPaint& paint,
146 SkArenaAlloc*,
147 bool drawCoverage,
148 sk_sp<SkShader> clipShader);
149
150 static SkBlitter* ChooseSprite(const SkPixmap& dst,
151 const SkPaint&,
152 const SkPixmap& src,
153 int left, int top,
154 SkArenaAlloc*, sk_sp<SkShader> clipShader);
155 ///@}
156
157 static bool UseRasterPipelineBlitter(const SkPixmap&, const SkPaint&, const SkMatrix&);
158
159protected:
160 SkAutoMalloc fBlitMemory;
161};
162
163/** This blitter silently never draws anything.
164*/
165class SkNullBlitter : public SkBlitter {
166public:
167 void blitH(int x, int y, int width) override;
168 void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override;
169 void blitV(int x, int y, int height, SkAlpha alpha) override;
170 void blitRect(int x, int y, int width, int height) override;
171 void blitMask(const SkMask&, const SkIRect& clip) override;
172 const SkPixmap* justAnOpaqueColor(uint32_t* value) override;
173 bool isNullBlitter() const override;
174};
175
176/** Wraps another (real) blitter, and ensures that the real blitter is only
177 called with coordinates that have been clipped by the specified clipRect.
178 This means the caller need not perform the clipping ahead of time.
179*/
180class SkRectClipBlitter : public SkBlitter {
181public:
182 void init(SkBlitter* blitter, const SkIRect& clipRect) {
183 SkASSERT(!clipRect.isEmpty());
184 fBlitter = blitter;
185 fClipRect = clipRect;
186 }
187
188 void blitH(int x, int y, int width) override;
189 void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override;
190 void blitV(int x, int y, int height, SkAlpha alpha) override;
191 void blitRect(int x, int y, int width, int height) override;
192 void blitAntiRect(int x, int y, int width, int height,
193 SkAlpha leftAlpha, SkAlpha rightAlpha) override;
194 void blitMask(const SkMask&, const SkIRect& clip) override;
195 const SkPixmap* justAnOpaqueColor(uint32_t* value) override;
196
197 int requestRowsPreserved() const override {
198 return fBlitter->requestRowsPreserved();
199 }
200
201 void* allocBlitMemory(size_t sz) override {
202 return fBlitter->allocBlitMemory(sz);
203 }
204
205private:
206 SkBlitter* fBlitter;
207 SkIRect fClipRect;
208};
209
210/** Wraps another (real) blitter, and ensures that the real blitter is only
211 called with coordinates that have been clipped by the specified clipRgn.
212 This means the caller need not perform the clipping ahead of time.
213*/
214class SkRgnClipBlitter : public SkBlitter {
215public:
216 void init(SkBlitter* blitter, const SkRegion* clipRgn) {
217 SkASSERT(clipRgn && !clipRgn->isEmpty());
218 fBlitter = blitter;
219 fRgn = clipRgn;
220 }
221
222 void blitH(int x, int y, int width) override;
223 void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override;
224 void blitV(int x, int y, int height, SkAlpha alpha) override;
225 void blitRect(int x, int y, int width, int height) override;
226 void blitAntiRect(int x, int y, int width, int height,
227 SkAlpha leftAlpha, SkAlpha rightAlpha) override;
228 void blitMask(const SkMask&, const SkIRect& clip) override;
229 const SkPixmap* justAnOpaqueColor(uint32_t* value) override;
230
231 int requestRowsPreserved() const override {
232 return fBlitter->requestRowsPreserved();
233 }
234
235 void* allocBlitMemory(size_t sz) override {
236 return fBlitter->allocBlitMemory(sz);
237 }
238
239private:
240 SkBlitter* fBlitter;
241 const SkRegion* fRgn;
242};
243
244#ifdef SK_DEBUG
245class SkRectClipCheckBlitter : public SkBlitter {
246public:
247 void init(SkBlitter* blitter, const SkIRect& clipRect) {
248 SkASSERT(blitter);
249 SkASSERT(!clipRect.isEmpty());
250 fBlitter = blitter;
251 fClipRect = clipRect;
252 }
253
254 void blitH(int x, int y, int width) override;
255 void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override;
256 void blitV(int x, int y, int height, SkAlpha alpha) override;
257 void blitRect(int x, int y, int width, int height) override;
258 void blitAntiRect(int x, int y, int width, int height,
259 SkAlpha leftAlpha, SkAlpha rightAlpha) override;
260 void blitMask(const SkMask&, const SkIRect& clip) override;
261 const SkPixmap* justAnOpaqueColor(uint32_t* value) override;
262 void blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) override;
263 void blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) override;
264
265 int requestRowsPreserved() const override {
266 return fBlitter->requestRowsPreserved();
267 }
268
269 void* allocBlitMemory(size_t sz) override {
270 return fBlitter->allocBlitMemory(sz);
271 }
272
273private:
274 SkBlitter* fBlitter;
275 SkIRect fClipRect;
276};
277#endif
278
279/** Factory to set up the appropriate most-efficient wrapper blitter
280 to apply a clip. Returns a pointer to a member, so lifetime must
281 be managed carefully.
282*/
283class SkBlitterClipper {
284public:
285 SkBlitter* apply(SkBlitter* blitter, const SkRegion* clip,
286 const SkIRect* bounds = nullptr);
287
288private:
289 SkNullBlitter fNullBlitter;
290 SkRectClipBlitter fRectBlitter;
291 SkRgnClipBlitter fRgnBlitter;
292};
293
294#define SHARD(code) fA->code; fB->code;
295
296class SkPairBlitter : public SkBlitter {
297 SkBlitter* fA = nullptr;
298 SkBlitter* fB = nullptr;
299public:
300 SkPairBlitter(SkBlitter* a, SkBlitter* b) : fA(a), fB(b) {}
301
302 void blitH(int x, int y, int width) override { SHARD(blitH(x, y, width)) }
303 void blitAntiH(int x, int y, const SkAlpha alphas[], const int16_t runs[]) override {
304 SHARD(blitAntiH(x, y, alphas, runs))
305 }
306 void blitV(int x, int y, int height, SkAlpha alpha) override {
307 SHARD(blitV(x, y, height, alpha))
308 }
309 void blitRect(int x, int y, int width, int height) override {
310 SHARD(blitRect(x, y, width, height))
311 }
312 void blitAntiRect(int x, int y, int width, int height,
313 SkAlpha leftAlpha, SkAlpha rightAlpha) override {
314 SHARD(blitAntiRect(x, y, width, height, leftAlpha, rightAlpha))
315 }
316 void blitMask(const SkMask& mask, const SkIRect& clip) override { SHARD(blitMask(mask, clip)) }
317 const SkPixmap* justAnOpaqueColor(uint32_t* value) override { return nullptr; }
318 void blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) override { SHARD(blitAntiH2(x, y, a0, a1)) }
319 void blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) override { SHARD(blitAntiV2(x, y, a0, a1)) }
320};
321#undef SHARD
322
323#endif
324