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