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
18class SkArenaAlloc;
19class SkMatrix;
20class SkPaint;
21class SkPixmap;
22struct 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*/
30class SkBlitter {
31public:
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)
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)
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     */
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     */
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
153protected:
154    SkAutoMalloc fBlitMemory;
155};
156
157/** This blitter silently never draws anything.
158*/
159class SkNullBlitter : public SkBlitter {
160public:
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*/
174class SkRectClipBlitter : public SkBlitter {
175public:
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
191    int requestRowsPreserved() const override {
192        return fBlitter->requestRowsPreserved();
193    }
194
195    void* allocBlitMemory(size_t sz) override {
196        return fBlitter->allocBlitMemory(sz);
197    }
198
199private:
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*/
208class SkRgnClipBlitter : public SkBlitter {
209public:
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
225    int requestRowsPreserved() const override {
226        return fBlitter->requestRowsPreserved();
227    }
228
229    void* allocBlitMemory(size_t sz) override {
230        return fBlitter->allocBlitMemory(sz);
231    }
232
233private:
234    SkBlitter*      fBlitter;
235    const SkRegion* fRgn;
236};
237
238#ifdef SK_DEBUG
239class SkRectClipCheckBlitter : public SkBlitter {
240public:
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
259    int requestRowsPreserved() const override {
260        return fBlitter->requestRowsPreserved();
261    }
262
263    void* allocBlitMemory(size_t sz) override {
264        return fBlitter->allocBlitMemory(sz);
265    }
266
267private:
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*/
277class SkBlitterClipper {
278public:
279    SkBlitter*  apply(SkBlitter* blitter, const SkRegion* clip,
280                      const SkIRect* bounds = nullptr);
281
282private:
283    SkNullBlitter       fNullBlitter;
284    SkRectClipBlitter   fRectBlitter;
285    SkRgnClipBlitter    fRgnBlitter;
286};
287
288#endif
289