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