• 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/base/SkTo.h"
15 #include "src/base/SkAutoMalloc.h"
16 #include "src/shaders/SkShaderBase.h"
17 
18 class SkArenaAlloc;
19 class SkMatrix;
20 class SkMatrixProvider;
21 class SkPaint;
22 class SkPixmap;
23 class SkSurfaceProps;
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 #if defined(SK_SUPPORT_LEGACY_ALPHA_BITMAP_AS_COVERAGE)
136     void blitMaskRegion(const SkMask& mask, const SkRegion& clip);
137 #endif
138     void blitRectRegion(const SkIRect& rect, const SkRegion& clip);
139     void blitRegion(const SkRegion& clip);
140     ///@}
141 
142     /** @name Factories
143         Return the correct blitter to use given the specified context.
144      */
145     static SkBlitter* Choose(const SkPixmap& dst,
146                              const SkMatrix& ctm,
147                              const SkPaint& paint,
148                              SkArenaAlloc*,
149                              bool drawCoverage,
150                              sk_sp<SkShader> clipShader,
151                              const SkSurfaceProps& props);
152 
153     static SkBlitter* ChooseSprite(const SkPixmap& dst,
154                                    const SkPaint&,
155                                    const SkPixmap& src,
156                                    int left, int top,
157                                    SkArenaAlloc*, sk_sp<SkShader> clipShader);
158     ///@}
159 
160     static bool UseLegacyBlitter(const SkPixmap&, const SkPaint&, const SkMatrix&);
161 
162 protected:
163     SkAutoMalloc fBlitMemory;
164 };
165 
166 /** This blitter silently never draws anything.
167 */
168 class SkNullBlitter : public SkBlitter {
169 public:
170     void blitH(int x, int y, int width) override;
171     void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override;
172     void blitV(int x, int y, int height, SkAlpha alpha) override;
173     void blitRect(int x, int y, int width, int height) override;
174     void blitMask(const SkMask&, const SkIRect& clip) override;
175     const SkPixmap* justAnOpaqueColor(uint32_t* value) override;
176     bool isNullBlitter() const override;
177 };
178 
179 /** Wraps another (real) blitter, and ensures that the real blitter is only
180     called with coordinates that have been clipped by the specified clipRect.
181     This means the caller need not perform the clipping ahead of time.
182 */
183 class SkRectClipBlitter : public SkBlitter {
184 public:
init(SkBlitter * blitter,const SkIRect & clipRect)185     void init(SkBlitter* blitter, const SkIRect& clipRect) {
186         SkASSERT(!clipRect.isEmpty());
187         fBlitter = blitter;
188         fClipRect = clipRect;
189     }
190 
191     void blitH(int x, int y, int width) override;
192     void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override;
193     void blitV(int x, int y, int height, SkAlpha alpha) override;
194     void blitRect(int x, int y, int width, int height) override;
195     void blitAntiRect(int x, int y, int width, int height,
196                       SkAlpha leftAlpha, SkAlpha rightAlpha) override;
197     void blitMask(const SkMask&, const SkIRect& clip) override;
198     const SkPixmap* justAnOpaqueColor(uint32_t* value) override;
199 
requestRowsPreserved()200     int requestRowsPreserved() const override {
201         return fBlitter->requestRowsPreserved();
202     }
203 
allocBlitMemory(size_t sz)204     void* allocBlitMemory(size_t sz) override {
205         return fBlitter->allocBlitMemory(sz);
206     }
207 
208 private:
209     SkBlitter*  fBlitter;
210     SkIRect     fClipRect;
211 };
212 
213 /** Wraps another (real) blitter, and ensures that the real blitter is only
214     called with coordinates that have been clipped by the specified clipRgn.
215     This means the caller need not perform the clipping ahead of time.
216 */
217 class SkRgnClipBlitter : public SkBlitter {
218 public:
init(SkBlitter * blitter,const SkRegion * clipRgn)219     void init(SkBlitter* blitter, const SkRegion* clipRgn) {
220         SkASSERT(clipRgn && !clipRgn->isEmpty());
221         fBlitter = blitter;
222         fRgn = clipRgn;
223     }
224 
225     void blitH(int x, int y, int width) override;
226     void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override;
227     void blitV(int x, int y, int height, SkAlpha alpha) override;
228     void blitRect(int x, int y, int width, int height) override;
229     void blitAntiRect(int x, int y, int width, int height,
230                       SkAlpha leftAlpha, SkAlpha rightAlpha) override;
231     void blitMask(const SkMask&, const SkIRect& clip) override;
232     const SkPixmap* justAnOpaqueColor(uint32_t* value) override;
233 
requestRowsPreserved()234     int requestRowsPreserved() const override {
235         return fBlitter->requestRowsPreserved();
236     }
237 
allocBlitMemory(size_t sz)238     void* allocBlitMemory(size_t sz) override {
239         return fBlitter->allocBlitMemory(sz);
240     }
241 
242 private:
243     SkBlitter*      fBlitter;
244     const SkRegion* fRgn;
245 };
246 
247 #ifdef SK_DEBUG
248 class SkRectClipCheckBlitter : public SkBlitter {
249 public:
init(SkBlitter * blitter,const SkIRect & clipRect)250     void init(SkBlitter* blitter, const SkIRect& clipRect) {
251         SkASSERT(blitter);
252         SkASSERT(!clipRect.isEmpty());
253         fBlitter = blitter;
254         fClipRect = clipRect;
255     }
256 
257     void blitH(int x, int y, int width) override;
258     void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override;
259     void blitV(int x, int y, int height, SkAlpha alpha) override;
260     void blitRect(int x, int y, int width, int height) override;
261     void blitAntiRect(int x, int y, int width, int height,
262                               SkAlpha leftAlpha, SkAlpha rightAlpha) override;
263     void blitMask(const SkMask&, const SkIRect& clip) override;
264     const SkPixmap* justAnOpaqueColor(uint32_t* value) override;
265     void blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) override;
266     void blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) override;
267 
requestRowsPreserved()268     int requestRowsPreserved() const override {
269         return fBlitter->requestRowsPreserved();
270     }
271 
allocBlitMemory(size_t sz)272     void* allocBlitMemory(size_t sz) override {
273         return fBlitter->allocBlitMemory(sz);
274     }
275 
276 private:
277     SkBlitter*  fBlitter;
278     SkIRect     fClipRect;
279 };
280 #endif
281 
282 /** Factory to set up the appropriate most-efficient wrapper blitter
283     to apply a clip. Returns a pointer to a member, so lifetime must
284     be managed carefully.
285 */
286 class SkBlitterClipper {
287 public:
288     SkBlitter*  apply(SkBlitter* blitter, const SkRegion* clip,
289                       const SkIRect* bounds = nullptr);
290 
291 private:
292     SkNullBlitter       fNullBlitter;
293     SkRectClipBlitter   fRectBlitter;
294     SkRgnClipBlitter    fRgnBlitter;
295 };
296 
297 // A good size for creating shader contexts on the stack.
298 enum {kSkBlitterContextSize = 3332};
299 
300 #endif
301