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