• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 SkMatrixProvider;
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     /// 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)
blitAntiH2(int x,int y,U8CPU a0,U8CPU a1)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)
blitAntiV2(int x,int y,U8CPU a0,U8CPU a1)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      */
requestRowsPreserved()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      */
allocBlitMemory(size_t sz)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 UseLegacyBlitter(const SkPixmap&, const SkPaint&, const SkMatrix&);
158 
159 protected:
160     SkAutoMalloc fBlitMemory;
161 };
162 
163 /** This blitter silently never draws anything.
164 */
165 class SkNullBlitter : public SkBlitter {
166 public:
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 */
180 class SkRectClipBlitter : public SkBlitter {
181 public:
init(SkBlitter * blitter,const SkIRect & clipRect)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 
requestRowsPreserved()197     int requestRowsPreserved() const override {
198         return fBlitter->requestRowsPreserved();
199     }
200 
allocBlitMemory(size_t sz)201     void* allocBlitMemory(size_t sz) override {
202         return fBlitter->allocBlitMemory(sz);
203     }
204 
205 private:
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 */
214 class SkRgnClipBlitter : public SkBlitter {
215 public:
init(SkBlitter * blitter,const SkRegion * clipRgn)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 
requestRowsPreserved()231     int requestRowsPreserved() const override {
232         return fBlitter->requestRowsPreserved();
233     }
234 
allocBlitMemory(size_t sz)235     void* allocBlitMemory(size_t sz) override {
236         return fBlitter->allocBlitMemory(sz);
237     }
238 
239 private:
240     SkBlitter*      fBlitter;
241     const SkRegion* fRgn;
242 };
243 
244 #ifdef SK_DEBUG
245 class SkRectClipCheckBlitter : public SkBlitter {
246 public:
init(SkBlitter * blitter,const SkIRect & clipRect)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 
requestRowsPreserved()265     int requestRowsPreserved() const override {
266         return fBlitter->requestRowsPreserved();
267     }
268 
allocBlitMemory(size_t sz)269     void* allocBlitMemory(size_t sz) override {
270         return fBlitter->allocBlitMemory(sz);
271     }
272 
273 private:
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 */
283 class SkBlitterClipper {
284 public:
285     SkBlitter*  apply(SkBlitter* blitter, const SkRegion* clip,
286                       const SkIRect* bounds = nullptr);
287 
288 private:
289     SkNullBlitter       fNullBlitter;
290     SkRectClipBlitter   fRectBlitter;
291     SkRgnClipBlitter    fRgnBlitter;
292 };
293 
294 #define SHARD(code)   fA->code; fB->code;
295 
296 class SkPairBlitter : public SkBlitter {
297     SkBlitter*  fA = nullptr;
298     SkBlitter*  fB = nullptr;
299 public:
SkPairBlitter(SkBlitter * a,SkBlitter * b)300     SkPairBlitter(SkBlitter* a, SkBlitter* b) : fA(a), fB(b) {}
301 
blitH(int x,int y,int width)302     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[])303     void blitAntiH(int x, int y, const SkAlpha alphas[], const int16_t runs[]) override {
304          SHARD(blitAntiH(x, y, alphas, runs))
305     }
blitV(int x,int y,int height,SkAlpha alpha)306     void blitV(int x, int y, int height, SkAlpha alpha) override {
307         SHARD(blitV(x, y, height, alpha))
308     }
blitRect(int x,int y,int width,int height)309     void blitRect(int x, int y, int width, int height) override {
310         SHARD(blitRect(x, y, width, height))
311     }
blitAntiRect(int x,int y,int width,int height,SkAlpha leftAlpha,SkAlpha rightAlpha)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     }
blitMask(const SkMask & mask,const SkIRect & clip)316     void blitMask(const SkMask& mask, const SkIRect& clip) override { SHARD(blitMask(mask, clip)) }
justAnOpaqueColor(uint32_t * value)317     const SkPixmap* justAnOpaqueColor(uint32_t* value) override { return nullptr; }
blitAntiH2(int x,int y,U8CPU a0,U8CPU a1)318     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)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