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 SkShader_DEFINED
11#define SkShader_DEFINED
12
13#include "SkBitmap.h"
14#include "SkFlattenable.h"
15#include "SkMask.h"
16#include "SkMatrix.h"
17#include "SkPaint.h"
18
19class SkPath;
20
21/** \class SkShader
22 *
23 *  SkShader is the based class for objects that return horizontal spans of
24 *  colors during drawing. A subclass of SkShader is installed in a SkPaint
25 *  calling paint.setShader(shader). After that any object (other than a bitmap)
26 *  that is drawn with that paint will get its color(s) from the shader.
27 */
28class SK_API SkShader : public SkFlattenable {
29public:
30            SkShader();
31    virtual ~SkShader();
32
33    /**
34     *  Return true if the shader has a non-identity local matrix.
35     *  @param localM   Optional: If not null, return the shader's local matrix
36     *  @return true if the shader has a non-identity local matrix.
37     */
38    bool getLocalMatrix(SkMatrix* localM) const;
39
40    /**
41     *  Set the shader's local matrix.
42     *  @param localM   The shader's new local matrix.
43     */
44    void setLocalMatrix(const SkMatrix& localM);
45
46    /**
47     *  Reset the shader's local matrix to identity.
48     */
49    void resetLocalMatrix();
50
51    enum TileMode {
52        kClamp_TileMode,    //!< replicate the edge color if the shader draws outside of its original bounds
53        kRepeat_TileMode,   //!< repeat the shader's image horizontally and vertically
54        kMirror_TileMode,   //!< repeat the shader's image horizontally and vertically, alternating mirror images so that adjacent images always seam
55
56        kTileModeCount
57    };
58
59    // override these in your subclass
60
61    enum Flags {
62        //!< set if all of the colors will be opaque
63        kOpaqueAlpha_Flag  = 0x01,
64
65        //! set if this shader's shadeSpan16() method can be called
66        kHasSpan16_Flag = 0x02,
67
68        /** Set this bit if the shader's native data type is instrinsically 16
69            bit, meaning that calling the 32bit shadeSpan() entry point will
70            mean the the impl has to up-sample 16bit data into 32bit. Used as a
71            a means of clearing a dither request if the it will have no effect
72        */
73        kIntrinsicly16_Flag = 0x04,
74
75        /** set (after setContext) if the spans only vary in X (const in Y).
76            e.g. an Nx1 bitmap that is being tiled in Y, or a linear-gradient
77            that varies from left-to-right. This flag specifies this for
78            shadeSpan().
79         */
80        kConstInY32_Flag = 0x08,
81
82        /** same as kConstInY32_Flag, but is set if this is true for shadeSpan16
83            which may not always be the case, since shadeSpan16 may be
84            predithered, which would mean it was not const in Y, even though
85            the 32bit shadeSpan() would be const.
86         */
87        kConstInY16_Flag = 0x10
88    };
89
90    /**
91     *  Called sometimes before drawing with this shader. Return the type of
92     *  alpha your shader will return. The default implementation returns 0.
93     *  Your subclass should override if it can (even sometimes) report a
94     *  non-zero value, since that will enable various blitters to perform
95     *  faster.
96     */
97    virtual uint32_t getFlags() { return 0; }
98
99    /**
100     *  Returns true if the shader is guaranteed to produce only opaque
101     *  colors, subject to the SkPaint using the shader to apply an opaque
102     *  alpha value. Subclasses should override this to allow some
103     *  optimizations.  isOpaque() can be called at any time, unlike getFlags,
104     *  which only works properly when the context is set.
105     */
106    virtual bool isOpaque() const { return false; }
107
108    /**
109     *  Return the alpha associated with the data returned by shadeSpan16(). If
110     *  kHasSpan16_Flag is not set, this value is meaningless.
111     */
112    virtual uint8_t getSpan16Alpha() const { return fPaintAlpha; }
113
114    /**
115     *  Called once before drawing, with the current paint and device matrix.
116     *  Return true if your shader supports these parameters, or false if not.
117     *  If false is returned, nothing will be drawn.
118     */
119    virtual bool setContext(const SkBitmap& device, const SkPaint& paint,
120                            const SkMatrix& matrix);
121
122    /**
123     *  Called for each span of the object being drawn. Your subclass should
124     *  set the appropriate colors (with premultiplied alpha) that correspond
125     *  to the specified device coordinates.
126     */
127    virtual void shadeSpan(int x, int y, SkPMColor[], int count) = 0;
128
129    /**
130     *  Called only for 16bit devices when getFlags() returns
131     *  kOpaqueAlphaFlag | kHasSpan16_Flag
132     */
133    virtual void shadeSpan16(int x, int y, uint16_t[], int count);
134
135    /**
136     *  Similar to shadeSpan, but only returns the alpha-channel for a span.
137     *  The default implementation calls shadeSpan() and then extracts the alpha
138     *  values from the returned colors.
139     */
140    virtual void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count);
141
142    /**
143     *  Helper function that returns true if this shader's shadeSpan16() method
144     *  can be called.
145     */
146    bool canCallShadeSpan16() {
147        return SkShader::CanCallShadeSpan16(this->getFlags());
148    }
149
150    /**
151     *  Helper to check the flags to know if it is legal to call shadeSpan16()
152     */
153    static bool CanCallShadeSpan16(uint32_t flags) {
154        return (flags & kHasSpan16_Flag) != 0;
155    }
156
157    /**
158     *  Called before a session using the shader begins. Some shaders override
159     *  this to defer some of their work (like calling bitmap.lockPixels()).
160     *  Must be balanced by a call to endSession.
161     */
162    virtual void beginSession();
163    virtual void endSession();
164
165    /**
166     Gives method bitmap should be read to implement a shader.
167     Also determines number and interpretation of "extra" parameters returned
168     by asABitmap
169     */
170    enum BitmapType {
171        kNone_BitmapType,   //<! Shader is not represented as a bitmap
172        kDefault_BitmapType,//<! Access bitmap using local coords transformed
173                            //   by matrix. No extras
174        kRadial_BitmapType, //<! Access bitmap by transforming local coordinates
175                            //   by the matrix and taking the distance of result
176                            //   from  (0,0) as bitmap column. Bitmap is 1 pixel
177                            //   tall. No extras
178        kSweep_BitmapType,  //<! Access bitmap by transforming local coordinates
179                            //   by the matrix and taking the angle of result
180                            //   to (0,0) as bitmap x coord, where angle = 0 is
181                            //   bitmap left edge of bitmap = 2pi is the
182                            //   right edge. Bitmap is 1 pixel tall. No extras
183        kTwoPointRadial_BitmapType,
184                            //<! Matrix transforms to space where (0,0) is
185                            //   the center of the starting circle.  The second
186                            //   circle will be centered (x, 0) where x  may be
187                            //   0. The post-matrix space is normalized such
188                            //   that 1 is the second radius - first radius.
189                            //   Three extra parameters are returned:
190                            //      0: x-offset of second circle center
191                            //         to first.
192                            //      1: radius of first circle in post-matrix
193                            //         space
194                            //      2: the second radius minus the first radius
195                            //         in pre-transformed space.
196
197       kLast_BitmapType = kTwoPointRadial_BitmapType
198    };
199    /** Optional methods for shaders that can pretend to be a bitmap/texture
200        to play along with opengl. Default just returns kNone_BitmapType and
201        ignores the out parameters.
202
203        @param outTexture if non-NULL will be the bitmap representing the shader
204                          after return.
205        @param outMatrix  if non-NULL will be the matrix to apply to vertices
206                          to access the bitmap after return.
207        @param xy         if non-NULL will be the tile modes that should be
208                          used to access the bitmap after return.
209        @param twoPointRadialParams Two extra return values needed for two point
210                                    radial bitmaps. The first is the x-offset of
211                                    the second point and the second is the radius
212                                    about the first point.
213    */
214    virtual BitmapType asABitmap(SkBitmap* outTexture, SkMatrix* outMatrix,
215                         TileMode xy[2], SkScalar* twoPointRadialParams) const;
216
217    /**
218     *  If the shader subclass can be represented as a gradient, asAGradient
219     *  returns the matching GradientType enum (or kNone_GradientType if it
220     *  cannot). Also, if info is not null, asAGradient populates info with
221     *  the relevant (see below) parameters for the gradient.  fColorCount
222     *  is both an input and output parameter.  On input, it indicates how
223     *  many entries in fColors and fColorOffsets can be used, if they are
224     *  non-NULL.  After asAGradient has run, fColorCount indicates how
225     *  many color-offset pairs there are in the gradient.  If there is
226     *  insufficient space to store all of the color-offset pairs, fColors
227     *  and fColorOffsets will not be altered.  fColorOffsets specifies
228     *  where on the range of 0 to 1 to transition to the given color.
229     *  The meaning of fPoint and fRadius is dependant on the type of gradient.
230     *
231     *  None:
232     *      info is ignored.
233     *  Color:
234     *      fColorOffsets[0] is meaningless.
235     *  Linear:
236     *      fPoint[0] and fPoint[1] are the end-points of the gradient
237     *  Radial:
238     *      fPoint[0] and fRadius[0] are the center and radius
239     *  Radial2:
240     *      fPoint[0] and fRadius[0] are the center and radius of the 1st circle
241     *      fPoint[1] and fRadius[1] are the center and radius of the 2nd circle
242     *  Sweep:
243     *      fPoint[0] is the center of the sweep.
244     */
245
246    enum GradientType {
247        kNone_GradientType,
248        kColor_GradientType,
249        kLinear_GradientType,
250        kRadial_GradientType,
251        kRadial2_GradientType,
252        kSweep_GradientType,
253        kLast_GradientType = kSweep_GradientType
254    };
255
256    struct GradientInfo {
257        int         fColorCount;    //!< In-out parameter, specifies passed size
258                                    //   of fColors/fColorOffsets on input, and
259                                    //   actual number of colors/offsets on
260                                    //   output.
261        SkColor*    fColors;        //!< The colors in the gradient.
262        SkScalar*   fColorOffsets;  //!< The unit offset for color transitions.
263        SkPoint     fPoint[2];      //!< Type specific, see above.
264        SkScalar    fRadius[2];     //!< Type specific, see above.
265        TileMode    fTileMode;      //!< The tile mode used.
266    };
267
268    virtual GradientType asAGradient(GradientInfo* info) const;
269
270    //////////////////////////////////////////////////////////////////////////
271    //  Factory methods for stock shaders
272
273    /** Call this to create a new shader that will draw with the specified bitmap.
274        @param src  The bitmap to use inside the shader
275        @param tmx  The tiling mode to use when sampling the bitmap in the x-direction.
276        @param tmy  The tiling mode to use when sampling the bitmap in the y-direction.
277        @return     Returns a new shader object. Note: this function never returns null.
278    */
279    static SkShader* CreateBitmapShader(const SkBitmap& src,
280                                        TileMode tmx, TileMode tmy);
281
282    virtual void flatten(SkFlattenableWriteBuffer& ) SK_OVERRIDE;
283protected:
284    enum MatrixClass {
285        kLinear_MatrixClass,            // no perspective
286        kFixedStepInX_MatrixClass,      // fast perspective, need to call fixedStepInX() each scanline
287        kPerspective_MatrixClass        // slow perspective, need to mappoints each pixel
288    };
289    static MatrixClass ComputeMatrixClass(const SkMatrix&);
290
291    // These can be called by your subclass after setContext() has been called
292    uint8_t             getPaintAlpha() const { return fPaintAlpha; }
293    SkBitmap::Config    getDeviceConfig() const { return (SkBitmap::Config)fDeviceConfig; }
294    const SkMatrix&     getTotalInverse() const { return fTotalInverse; }
295    MatrixClass         getInverseClass() const { return (MatrixClass)fTotalInverseClass; }
296
297    SkShader(SkFlattenableReadBuffer& );
298private:
299    SkMatrix*           fLocalMatrix;
300    SkMatrix            fTotalInverse;
301    uint8_t             fPaintAlpha;
302    uint8_t             fDeviceConfig;
303    uint8_t             fTotalInverseClass;
304    SkDEBUGCODE(SkBool8 fInSession;)
305
306    static SkShader* CreateBitmapShader(const SkBitmap& src,
307                                        TileMode, TileMode,
308                                        void* storage, size_t storageSize);
309    friend class SkAutoBitmapShaderInstall;
310    typedef SkFlattenable INHERITED;
311};
312
313#endif
314
315