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