• 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/SkRefCnt.h"
14 #include "include/core/SkRegion.h"
15 #include "include/private/base/SkAssert.h"
16 #include "include/private/base/SkCPUTypes.h"
17 #include "include/private/base/SkDebug.h"
18 #include "include/private/base/SkTo.h"
19 #include "src/base/SkAutoMalloc.h"
20 
21 #include <cstddef>
22 #include <cstdint>
23 
24 class SkArenaAlloc;
25 class SkMatrix;
26 class SkPaint;
27 class SkPixmap;
28 class SkShader;
29 class SkSurfaceProps;
30 struct SkMask;
31 enum class SkDrawCoverage : bool;
32 
33 /** SkBlitter and its subclasses are responsible for actually writing pixels
34     into memory. Besides efficiency, they handle clipping and antialiasing.
35     A SkBlitter subclass contains all the context needed to generate pixels
36     for the destination and how src/generated pixels map to the destination.
37     The coordinates passed to the blitX calls are in destination pixel space.
38 */
39 class SkBlitter {
40 public:
41     virtual ~SkBlitter();
42     SkBlitter() = default;
43     SkBlitter(const SkBlitter&) = delete;
44     SkBlitter(SkBlitter&&) = delete;
45     SkBlitter& operator=(const SkBlitter&) = delete;
46     SkBlitter& operator=(SkBlitter&&) = delete;
47 
48     /// Blit a horizontal run of one or more pixels.
49     virtual void blitH(int x, int y, int width) = 0;
50 
51     /// Blit a horizontal run of antialiased pixels; runs[] is a *sparse*
52     /// zero-terminated run-length encoding of spans of constant alpha values.
53     /// The runs[] and antialias[] work together to represent long runs of pixels with the same
54     /// alphas. The runs[] contains the number of pixels with the same alpha, and antialias[]
55     /// contain the coverage value for that number of pixels. The runs[] (and antialias[]) are
56     /// encoded in a clever way. The runs array is zero terminated, and has enough entries for
57     /// each pixel plus one, in most cases some of the entries will not contain valid data. An entry
58     /// in the runs array contains the number of pixels (np) that have the same alpha value. The
59     /// next np value is found np entries away. For example, if runs[0] = 7, then the next valid
60     /// entry will by at runs[7]. The runs array and antialias[] are coupled by index. So, if the
61     /// np entry is at runs[45] = 12 then the alpha value can be found at antialias[45] = 0x88.
62     /// This would mean to use an alpha value of 0x88 for the next 12 pixels starting at pixel 45.
63     virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) = 0;
64 
65     /// Blit a vertical run of pixels with a constant alpha value.
66     virtual void blitV(int x, int y, int height, SkAlpha alpha);
67 
68     /// Blit a solid rectangle one or more pixels wide.
69     virtual void blitRect(int x, int y, int width, int height);
70 
71     /** Blit a rectangle with one alpha-blended column on the left,
72         width (zero or more) opaque pixels, and one alpha-blended column
73         on the right.
74         The result will always be at least two pixels wide.
75     */
76     virtual void blitAntiRect(int x, int y, int width, int height,
77                               SkAlpha leftAlpha, SkAlpha rightAlpha);
78 
79     // Blit a rect in AA with size at least 3 x 3 (small rect has too many edge cases...)
80     void blitFatAntiRect(const SkRect& rect);
81 
82     /// Blit a pattern of pixels defined by a rectangle-clipped mask;
83     /// typically used for text.
84     virtual void blitMask(const SkMask&, const SkIRect& clip);
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 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 #if defined(SK_SUPPORT_LEGACY_ALPHA_BITMAP_AS_COVERAGE)
135     void blitMaskRegion(const SkMask& mask, const SkRegion& clip);
136 #endif
137     void blitRectRegion(const SkIRect& rect, const SkRegion& clip);
138     void blitRegion(const SkRegion& clip);
139     ///@}
140 
141     /** @name Factories
142         Return the correct blitter to use given the specified context.
143      */
144     static SkBlitter* Choose(const SkPixmap& dst,
145                              const SkMatrix& ctm,
146                              const SkPaint& paint,
147                              SkArenaAlloc*,
148                              SkDrawCoverage,
149                              sk_sp<SkShader> clipShader,
150                              const SkSurfaceProps& props);
151 
152     static SkBlitter* ChooseSprite(const SkPixmap& dst,
153                                    const SkPaint&,
154                                    const SkPixmap& src,
155                                    int left, int top,
156                                    SkArenaAlloc*, sk_sp<SkShader> clipShader);
157     ///@}
158 
159     static bool UseLegacyBlitter(const SkPixmap&, const SkPaint&, const SkMatrix&);
160 
161 protected:
162     SkAutoMalloc fBlitMemory;
163 };
164 
165 /** This blitter silently never draws anything.
166 */
167 class SkNullBlitter final : public SkBlitter {
168 public:
blitH(int x,int y,int width)169     void blitH(int x, int y, int width) override {}
blitAntiH(int x,int y,const SkAlpha[],const int16_t runs[])170     void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override {}
blitV(int x,int y,int height,SkAlpha alpha)171     void blitV(int x, int y, int height, SkAlpha alpha) override {}
blitRect(int x,int y,int width,int height)172     void blitRect(int x, int y, int width, int height) override {}
blitMask(const SkMask &,const SkIRect & clip)173     void blitMask(const SkMask&, const SkIRect& clip) 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 final : 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 
requestRowsPreserved()196     int requestRowsPreserved() const override {
197         return fBlitter->requestRowsPreserved();
198     }
199 
allocBlitMemory(size_t sz)200     void* allocBlitMemory(size_t sz) override {
201         return fBlitter->allocBlitMemory(sz);
202     }
203 
204 private:
205     SkBlitter*  fBlitter;
206     SkIRect     fClipRect;
207 };
208 
209 /** Wraps another (real) blitter, and ensures that the real blitter is only
210     called with coordinates that have been clipped by the specified clipRgn.
211     This means the caller need not perform the clipping ahead of time.
212 */
213 class SkRgnClipBlitter final : public SkBlitter {
214 public:
init(SkBlitter * blitter,const SkRegion * clipRgn)215     void init(SkBlitter* blitter, const SkRegion* clipRgn) {
216         SkASSERT(clipRgn && !clipRgn->isEmpty());
217         fBlitter = blitter;
218         fRgn = clipRgn;
219     }
220 
221     void blitH(int x, int y, int width) override;
222     void blitAntiH(int x, int y, const SkAlpha[], const int16_t runs[]) override;
223     void blitV(int x, int y, int height, SkAlpha alpha) override;
224     void blitRect(int x, int y, int width, int height) override;
225     void blitAntiRect(int x, int y, int width, int height,
226                       SkAlpha leftAlpha, SkAlpha rightAlpha) override;
227     void blitMask(const SkMask&, const SkIRect& clip) 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 final : 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     void blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) override;
260     void blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) override;
261 
requestRowsPreserved()262     int requestRowsPreserved() const override {
263         return fBlitter->requestRowsPreserved();
264     }
265 
allocBlitMemory(size_t sz)266     void* allocBlitMemory(size_t sz) override {
267         return fBlitter->allocBlitMemory(sz);
268     }
269 
270 private:
271     SkBlitter*  fBlitter;
272     SkIRect     fClipRect;
273 };
274 #endif
275 
276 /** Factory to set up the appropriate most-efficient wrapper blitter
277     to apply a clip. Returns a pointer to a member, so lifetime must
278     be managed carefully.
279 */
280 class SkBlitterClipper {
281 public:
282     SkBlitter*  apply(SkBlitter* blitter, const SkRegion* clip,
283                       const SkIRect* bounds = nullptr);
284 
285 private:
286     SkNullBlitter       fNullBlitter;
287     SkRectClipBlitter   fRectBlitter;
288     SkRgnClipBlitter    fRgnBlitter;
289 };
290 
291 #endif
292