SkBlitter.h revision 72c9faab45124e08c85f70ca38536914862d947c
1
2/*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#ifndef SkBlitter_DEFINED
11#define SkBlitter_DEFINED
12
13#include "SkBitmap.h"
14#include "SkBitmapProcShader.h"
15#include "SkMask.h"
16#include "SkMatrix.h"
17#include "SkPaint.h"
18#include "SkRefCnt.h"
19#include "SkRegion.h"
20#include "SkShader.h"
21#include "SkSmallAllocator.h"
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 NULL and ignore
54        the value parameter.
55    */
56    virtual const SkBitmap* justAnOpaqueColor(uint32_t* value);
57
58    /**
59     *  Special method just to identify the null blitter, which is returned
60     *  from Choose() if the request cannot be fulfilled. Default impl
61     *  returns false.
62     */
63    virtual bool isNullBlitter() const;
64
65    /**
66     *  Special methods for SkShaderBlitter. On all other classes this is a no-op.
67     */
68    virtual bool resetShaderContext(const SkShader::ContextRec&);
69    virtual SkShader::Context* getShaderContext() const;
70
71    /**
72     * Special methods for blitters that can blit more than one row at a time.
73     * This function returns the number of rows that this blitter could optimally
74     * process at a time. It is still required to support blitting one scanline
75     * at a time.
76     */
77    virtual int requestRowsPreserved() const { return 1; }
78
79    /**
80     * This function allocates memory for the blitter that the blitter then owns.
81     * The memory can be used by the calling function at will, but it will be
82     * released when the blitter's destructor is called. This function returns
83     * NULL if no persistent memory is needed by the blitter.
84     */
85    virtual void* allocBlitMemory(size_t sz) {
86        return fBlitMemory.reset(sz, SkAutoMalloc::kReuse_OnShrink);
87    }
88
89    ///@name non-virtual helpers
90    void blitMaskRegion(const SkMask& mask, const SkRegion& clip);
91    void blitRectRegion(const SkIRect& rect, const SkRegion& clip);
92    void blitRegion(const SkRegion& clip);
93    ///@}
94
95    /** @name Factories
96        Return the correct blitter to use given the specified context.
97     */
98    static SkBlitter* Choose(const SkBitmap& device,
99                             const SkMatrix& matrix,
100                             const SkPaint& paint,
101                             SkTBlitterAllocator*,
102                             bool drawCoverage = false);
103
104    static SkBlitter* ChooseSprite(const SkBitmap& device,
105                                   const SkPaint&,
106                                   const SkBitmap& src,
107                                   int left, int top,
108                                   SkTBlitterAllocator*);
109    ///@}
110
111protected:
112
113    SkAutoMalloc fBlitMemory;
114
115private:
116};
117
118/** This blitter silently never draws anything.
119*/
120class SkNullBlitter : public SkBlitter {
121public:
122    void blitH(int x, int y, int width) SK_OVERRIDE;
123    virtual void blitAntiH(int x, int y, const SkAlpha[],
124                           const int16_t runs[]) SK_OVERRIDE;
125    void blitV(int x, int y, int height, SkAlpha alpha) SK_OVERRIDE;
126    void blitRect(int x, int y, int width, int height) SK_OVERRIDE;
127    void blitMask(const SkMask&, const SkIRect& clip) SK_OVERRIDE;
128    const SkBitmap* justAnOpaqueColor(uint32_t* value) SK_OVERRIDE;
129    bool isNullBlitter() const SK_OVERRIDE;
130};
131
132/** Wraps another (real) blitter, and ensures that the real blitter is only
133    called with coordinates that have been clipped by the specified clipRect.
134    This means the caller need not perform the clipping ahead of time.
135*/
136class SkRectClipBlitter : public SkBlitter {
137public:
138    void init(SkBlitter* blitter, const SkIRect& clipRect) {
139        SkASSERT(!clipRect.isEmpty());
140        fBlitter = blitter;
141        fClipRect = clipRect;
142    }
143
144    void blitH(int x, int y, int width) SK_OVERRIDE;
145    virtual void blitAntiH(int x, int y, const SkAlpha[],
146                           const int16_t runs[]) SK_OVERRIDE;
147    void blitV(int x, int y, int height, SkAlpha alpha) SK_OVERRIDE;
148    void blitRect(int x, int y, int width, int height) SK_OVERRIDE;
149    virtual void blitAntiRect(int x, int y, int width, int height,
150                     SkAlpha leftAlpha, SkAlpha rightAlpha) SK_OVERRIDE;
151    void blitMask(const SkMask&, const SkIRect& clip) SK_OVERRIDE;
152    const SkBitmap* justAnOpaqueColor(uint32_t* value) SK_OVERRIDE;
153
154    int requestRowsPreserved() const SK_OVERRIDE {
155        return fBlitter->requestRowsPreserved();
156    }
157
158    void* allocBlitMemory(size_t sz) SK_OVERRIDE {
159        return fBlitter->allocBlitMemory(sz);
160    }
161
162private:
163    SkBlitter*  fBlitter;
164    SkIRect     fClipRect;
165};
166
167/** Wraps another (real) blitter, and ensures that the real blitter is only
168    called with coordinates that have been clipped by the specified clipRgn.
169    This means the caller need not perform the clipping ahead of time.
170*/
171class SkRgnClipBlitter : public SkBlitter {
172public:
173    void init(SkBlitter* blitter, const SkRegion* clipRgn) {
174        SkASSERT(clipRgn && !clipRgn->isEmpty());
175        fBlitter = blitter;
176        fRgn = clipRgn;
177    }
178
179    void blitH(int x, int y, int width) SK_OVERRIDE;
180    virtual void blitAntiH(int x, int y, const SkAlpha[],
181                           const int16_t runs[]) SK_OVERRIDE;
182    void blitV(int x, int y, int height, SkAlpha alpha) SK_OVERRIDE;
183    void blitRect(int x, int y, int width, int height) SK_OVERRIDE;
184    virtual void blitAntiRect(int x, int y, int width, int height,
185                     SkAlpha leftAlpha, SkAlpha rightAlpha) SK_OVERRIDE;
186    void blitMask(const SkMask&, const SkIRect& clip) SK_OVERRIDE;
187    const SkBitmap* justAnOpaqueColor(uint32_t* value) SK_OVERRIDE;
188
189    int requestRowsPreserved() const SK_OVERRIDE {
190        return fBlitter->requestRowsPreserved();
191    }
192
193    void* allocBlitMemory(size_t sz) SK_OVERRIDE {
194        return fBlitter->allocBlitMemory(sz);
195    }
196
197private:
198    SkBlitter*      fBlitter;
199    const SkRegion* fRgn;
200};
201
202/** Factory to set up the appropriate most-efficient wrapper blitter
203    to apply a clip. Returns a pointer to a member, so lifetime must
204    be managed carefully.
205*/
206class SkBlitterClipper {
207public:
208    SkBlitter*  apply(SkBlitter* blitter, const SkRegion* clip,
209                      const SkIRect* bounds = NULL);
210
211private:
212    SkNullBlitter       fNullBlitter;
213    SkRectClipBlitter   fRectBlitter;
214    SkRgnClipBlitter    fRgnBlitter;
215};
216
217#endif
218