• 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 
9 #ifndef SkShader_DEFINED
10 #define SkShader_DEFINED
11 
12 #include "SkBitmap.h"
13 #include "SkFlattenable.h"
14 #include "SkMask.h"
15 #include "SkMatrix.h"
16 #include "SkPaint.h"
17 #include "../gpu/GrColor.h"
18 
19 class SkPath;
20 class SkPicture;
21 class SkXfermode;
22 class GrContext;
23 class GrFragmentProcessor;
24 
25 /** \class SkShader
26  *
27  *  Shaders specify the source color(s) for what is being drawn. If a paint
28  *  has no shader, then the paint's color is used. If the paint has a
29  *  shader, then the shader's color(s) are use instead, but they are
30  *  modulated by the paint's alpha. This makes it easy to create a shader
31  *  once (e.g. bitmap tiling or gradient) and then change its transparency
32  *  w/o having to modify the original shader... only the paint's alpha needs
33  *  to be modified.
34  */
35 class SK_API SkShader : public SkFlattenable {
36 public:
37     SK_DECLARE_INST_COUNT(SkShader)
38 
39     SkShader(const SkMatrix* localMatrix = NULL);
40     virtual ~SkShader();
41 
42     /**
43      *  Returns the local matrix.
44      *
45      *  FIXME: This can be incorrect for a Shader with its own local matrix
46      *  that is also wrapped via CreateLocalMatrixShader.
47      */
getLocalMatrix()48     const SkMatrix& getLocalMatrix() const { return fLocalMatrix; }
49 
50     enum TileMode {
51         /** replicate the edge color if the shader draws outside of its
52          *  original bounds
53          */
54         kClamp_TileMode,
55 
56         /** repeat the shader's image horizontally and vertically */
57         kRepeat_TileMode,
58 
59         /** repeat the shader's image horizontally and vertically, alternating
60          *  mirror images so that adjacent images always seam
61          */
62         kMirror_TileMode,
63 
64 #if 0
65         /** only draw within the original domain, return 0 everywhere else */
66         kDecal_TileMode,
67 #endif
68     };
69 
70     enum {
71         kTileModeCount = kMirror_TileMode + 1
72     };
73 
74     // override these in your subclass
75 
76     enum Flags {
77         //!< set if all of the colors will be opaque
78         kOpaqueAlpha_Flag  = 0x01,
79 
80         //! set if this shader's shadeSpan16() method can be called
81         kHasSpan16_Flag = 0x02,
82 
83         /** Set this bit if the shader's native data type is instrinsically 16
84             bit, meaning that calling the 32bit shadeSpan() entry point will
85             mean the the impl has to up-sample 16bit data into 32bit. Used as a
86             a means of clearing a dither request if the it will have no effect
87         */
88         kIntrinsicly16_Flag = 0x04,
89 
90         /** set if the spans only vary in X (const in Y).
91             e.g. an Nx1 bitmap that is being tiled in Y, or a linear-gradient
92             that varies from left-to-right. This flag specifies this for
93             shadeSpan().
94          */
95         kConstInY32_Flag = 0x08,
96 
97         /** same as kConstInY32_Flag, but is set if this is true for shadeSpan16
98             which may not always be the case, since shadeSpan16 may be
99             predithered, which would mean it was not const in Y, even though
100             the 32bit shadeSpan() would be const.
101          */
102         kConstInY16_Flag = 0x10
103     };
104 
105     /**
106      *  Returns true if the shader is guaranteed to produce only opaque
107      *  colors, subject to the SkPaint using the shader to apply an opaque
108      *  alpha value. Subclasses should override this to allow some
109      *  optimizations.
110      */
isOpaque()111     virtual bool isOpaque() const { return false; }
112 
113     /**
114      *  ContextRec acts as a parameter bundle for creating Contexts.
115      */
116     struct ContextRec {
ContextRecContextRec117         ContextRec() : fDevice(NULL), fPaint(NULL), fMatrix(NULL), fLocalMatrix(NULL) {}
ContextRecContextRec118         ContextRec(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix)
119             : fDevice(&device)
120             , fPaint(&paint)
121             , fMatrix(&matrix)
122             , fLocalMatrix(NULL) {}
123 
124         const SkBitmap* fDevice;        // the bitmap we are drawing into
125         const SkPaint*  fPaint;         // the current paint associated with the draw
126         const SkMatrix* fMatrix;        // the current matrix in the canvas
127         const SkMatrix* fLocalMatrix;   // optional local matrix
128     };
129 
130     class Context : public ::SkNoncopyable {
131     public:
132         Context(const SkShader& shader, const ContextRec&);
133 
134         virtual ~Context();
135 
136         /**
137          *  Called sometimes before drawing with this shader. Return the type of
138          *  alpha your shader will return. The default implementation returns 0.
139          *  Your subclass should override if it can (even sometimes) report a
140          *  non-zero value, since that will enable various blitters to perform
141          *  faster.
142          */
getFlags()143         virtual uint32_t getFlags() const { return 0; }
144 
145         /**
146          *  Return the alpha associated with the data returned by shadeSpan16(). If
147          *  kHasSpan16_Flag is not set, this value is meaningless.
148          */
getSpan16Alpha()149         virtual uint8_t getSpan16Alpha() const { return fPaintAlpha; }
150 
151         /**
152          *  Called for each span of the object being drawn. Your subclass should
153          *  set the appropriate colors (with premultiplied alpha) that correspond
154          *  to the specified device coordinates.
155          */
156         virtual void shadeSpan(int x, int y, SkPMColor[], int count) = 0;
157 
158         typedef void (*ShadeProc)(void* ctx, int x, int y, SkPMColor[], int count);
159         virtual ShadeProc asAShadeProc(void** ctx);
160 
161         /**
162          *  Called only for 16bit devices when getFlags() returns
163          *  kOpaqueAlphaFlag | kHasSpan16_Flag
164          */
165         virtual void shadeSpan16(int x, int y, uint16_t[], int count);
166 
167         /**
168          *  Similar to shadeSpan, but only returns the alpha-channel for a span.
169          *  The default implementation calls shadeSpan() and then extracts the alpha
170          *  values from the returned colors.
171          */
172         virtual void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count);
173 
174         /**
175          *  Helper function that returns true if this shader's shadeSpan16() method
176          *  can be called.
177          */
canCallShadeSpan16()178         bool canCallShadeSpan16() {
179             return SkShader::CanCallShadeSpan16(this->getFlags());
180         }
181 
182         // Notification from blitter::blitMask in case we need to see the non-alpha channels
set3DMask(const SkMask *)183         virtual void set3DMask(const SkMask*) {}
184 
185     protected:
186         // Reference to shader, so we don't have to dupe information.
187         const SkShader& fShader;
188 
189         enum MatrixClass {
190             kLinear_MatrixClass,            // no perspective
191             kFixedStepInX_MatrixClass,      // fast perspective, need to call fixedStepInX() each
192                                             // scanline
193             kPerspective_MatrixClass        // slow perspective, need to mappoints each pixel
194         };
195         static MatrixClass ComputeMatrixClass(const SkMatrix&);
196 
getPaintAlpha()197         uint8_t         getPaintAlpha() const { return fPaintAlpha; }
getTotalInverse()198         const SkMatrix& getTotalInverse() const { return fTotalInverse; }
getInverseClass()199         MatrixClass     getInverseClass() const { return (MatrixClass)fTotalInverseClass; }
getCTM()200         const SkMatrix& getCTM() const { return fCTM; }
201     private:
202         SkMatrix    fCTM;
203         SkMatrix    fTotalInverse;
204         uint8_t     fPaintAlpha;
205         uint8_t     fTotalInverseClass;
206 
207         typedef SkNoncopyable INHERITED;
208     };
209 
210     /**
211      *  Create the actual object that does the shading.
212      *  Size of storage must be >= contextSize.
213      */
214     Context* createContext(const ContextRec&, void* storage) const;
215 
216     /**
217      *  Return the size of a Context returned by createContext.
218      *
219      *  Override this if your subclass overrides createContext, to return the correct size of
220      *  your subclass' context.
221      */
222     virtual size_t contextSize() const;
223 
224     /**
225      *  Helper to check the flags to know if it is legal to call shadeSpan16()
226      */
CanCallShadeSpan16(uint32_t flags)227     static bool CanCallShadeSpan16(uint32_t flags) {
228         return (flags & kHasSpan16_Flag) != 0;
229     }
230 
231     /**
232      Gives method bitmap should be read to implement a shader.
233      Also determines number and interpretation of "extra" parameters returned
234      by asABitmap
235      */
236     enum BitmapType {
237         kNone_BitmapType,   //<! Shader is not represented as a bitmap
238         kDefault_BitmapType,//<! Access bitmap using local coords transformed
239                             //   by matrix. No extras
240         kRadial_BitmapType, //<! Access bitmap by transforming local coordinates
241                             //   by the matrix and taking the distance of result
242                             //   from  (0,0) as bitmap column. Bitmap is 1 pixel
243                             //   tall. No extras
244         kSweep_BitmapType,  //<! Access bitmap by transforming local coordinates
245                             //   by the matrix and taking the angle of result
246                             //   to (0,0) as bitmap x coord, where angle = 0 is
247                             //   bitmap left edge of bitmap = 2pi is the
248                             //   right edge. Bitmap is 1 pixel tall. No extras
249         kTwoPointConical_BitmapType,
250                             //<! Matrix transforms to space where (0,0) is
251                             //   the center of the starting circle.  The second
252                             //   circle will be centered (x, 0) where x  may be
253                             //   0.
254                             //   Three extra parameters are returned:
255                             //      0: x-offset of second circle center
256                             //         to first.
257                             //      1: radius of first circle
258                             //      2: the second radius minus the first radius
259         kLinear_BitmapType, //<! Access bitmap using local coords transformed
260                             //   by matrix. No extras
261 
262        kLast_BitmapType = kLinear_BitmapType
263     };
264     /** Optional methods for shaders that can pretend to be a bitmap/texture
265         to play along with opengl. Default just returns kNone_BitmapType and
266         ignores the out parameters.
267 
268         @param outTexture if non-NULL will be the bitmap representing the shader
269                           after return.
270         @param outMatrix  if non-NULL will be the matrix to apply to vertices
271                           to access the bitmap after return.
272         @param xy         if non-NULL will be the tile modes that should be
273                           used to access the bitmap after return.
274         @param twoPointRadialParams Two extra return values needed for two point
275                                     radial bitmaps. The first is the x-offset of
276                                     the second point and the second is the radius
277                                     about the first point.
278     */
279     virtual BitmapType asABitmap(SkBitmap* outTexture, SkMatrix* outMatrix,
280                          TileMode xy[2]) const;
281 
282     /**
283      *  If the shader subclass can be represented as a gradient, asAGradient
284      *  returns the matching GradientType enum (or kNone_GradientType if it
285      *  cannot). Also, if info is not null, asAGradient populates info with
286      *  the relevant (see below) parameters for the gradient.  fColorCount
287      *  is both an input and output parameter.  On input, it indicates how
288      *  many entries in fColors and fColorOffsets can be used, if they are
289      *  non-NULL.  After asAGradient has run, fColorCount indicates how
290      *  many color-offset pairs there are in the gradient.  If there is
291      *  insufficient space to store all of the color-offset pairs, fColors
292      *  and fColorOffsets will not be altered.  fColorOffsets specifies
293      *  where on the range of 0 to 1 to transition to the given color.
294      *  The meaning of fPoint and fRadius is dependant on the type of gradient.
295      *
296      *  None:
297      *      info is ignored.
298      *  Color:
299      *      fColorOffsets[0] is meaningless.
300      *  Linear:
301      *      fPoint[0] and fPoint[1] are the end-points of the gradient
302      *  Radial:
303      *      fPoint[0] and fRadius[0] are the center and radius
304      *  Conical:
305      *      fPoint[0] and fRadius[0] are the center and radius of the 1st circle
306      *      fPoint[1] and fRadius[1] are the center and radius of the 2nd circle
307      *  Sweep:
308      *      fPoint[0] is the center of the sweep.
309      */
310 
311     enum GradientType {
312         kNone_GradientType,
313         kColor_GradientType,
314         kLinear_GradientType,
315         kRadial_GradientType,
316         kSweep_GradientType,
317         kConical_GradientType,
318         kLast_GradientType = kConical_GradientType
319     };
320 
321     struct GradientInfo {
322         int         fColorCount;    //!< In-out parameter, specifies passed size
323                                     //   of fColors/fColorOffsets on input, and
324                                     //   actual number of colors/offsets on
325                                     //   output.
326         SkColor*    fColors;        //!< The colors in the gradient.
327         SkScalar*   fColorOffsets;  //!< The unit offset for color transitions.
328         SkPoint     fPoint[2];      //!< Type specific, see above.
329         SkScalar    fRadius[2];     //!< Type specific, see above.
330         TileMode    fTileMode;      //!< The tile mode used.
331         uint32_t    fGradientFlags; //!< see SkGradientShader::Flags
332     };
333 
334     virtual GradientType asAGradient(GradientInfo* info) const;
335 
336     /**
337      *  If the shader subclass is composed of two shaders, return true, and if rec is not NULL,
338      *  fill it out with info about the shader.
339      *
340      *  These are bare pointers; the ownership and reference count are unchanged.
341      */
342 
343     struct ComposeRec {
344         const SkShader*     fShaderA;
345         const SkShader*     fShaderB;
346         const SkXfermode*   fMode;
347     };
348 
asACompose(ComposeRec *)349     virtual bool asACompose(ComposeRec*) const { return false; }
350 
351 
352     /**
353      *  Returns true if the shader subclass succeeds in creating an effect or if none is required.
354      *  False is returned if it fails or if there is not an implementation of this method in the
355      *  shader subclass.
356      *
357      *  On success an implementation of this method must inspect the SkPaint and set paintColor to
358      *  the color the effect expects as its input color. If the SkShader wishes to emit a solid
359      *  color then it should set paintColor to that color and not create an effect. Note that
360      *  GrColor is always premul. The common patterns are to convert paint's SkColor to GrColor or
361      *  to extract paint's alpha and replicate it to all channels in paintColor. Upon failure
362      *  paintColor should not be modified. It is not recommended to specialize the effect to
363      *  the paint's color as then many GPU shaders may be generated.
364      *
365      *  The GrContext may be used by the effect to create textures. The GPU device does not
366      *  call createContext. Instead we pass the SkPaint here in case the shader needs paint info.
367      *
368      *  A view matrix is always required to create the correct GrFragmentProcessor.  Some shaders
369      *  may also use the optional localMatrix to define a matrix relevant only for sampling.
370      */
371     virtual bool asFragmentProcessor(GrContext*, const SkPaint&, const SkMatrix& viewM,
372                                      const SkMatrix* localMatrix, GrColor*,
373                                      GrFragmentProcessor**) const;
374 
375     /**
376      *  If the shader can represent its "average" luminance in a single color, return true and
377      *  if color is not NULL, return that color. If it cannot, return false and ignore the color
378      *  parameter.
379      *
380      *  Note: if this returns true, the returned color will always be opaque, as only the RGB
381      *  components are used to compute luminance.
382      */
383     bool asLuminanceColor(SkColor*) const;
384 
385 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
386     /**
387      *  If the shader is a custom shader which has data the caller might want, call this function
388      *  to get that data.
389      */
asACustomShader(void **)390     virtual bool asACustomShader(void** /* customData */) const { return false; }
391 #endif
392 
393     //////////////////////////////////////////////////////////////////////////
394     //  Factory methods for stock shaders
395 
396     /**
397      *  Call this to create a new "empty" shader, that will not draw anything.
398      */
399     static SkShader* CreateEmptyShader();
400 
401     /**
402      *  Call this to create a new shader that just draws the specified color. This should always
403      *  draw the same as a paint with this color (and no shader).
404      */
405     static SkShader* CreateColorShader(SkColor);
406 
407     /** Call this to create a new shader that will draw with the specified bitmap.
408      *
409      *  If the bitmap cannot be used (e.g. has no pixels, or its dimensions
410      *  exceed implementation limits (currently at 64K - 1)) then SkEmptyShader
411      *  may be returned.
412      *
413      *  If the src is kA8_Config then that mask will be colorized using the color on
414      *  the paint.
415      *
416      *  @param src  The bitmap to use inside the shader
417      *  @param tmx  The tiling mode to use when sampling the bitmap in the x-direction.
418      *  @param tmy  The tiling mode to use when sampling the bitmap in the y-direction.
419      *  @return     Returns a new shader object. Note: this function never returns null.
420     */
421     static SkShader* CreateBitmapShader(const SkBitmap& src,
422                                         TileMode tmx, TileMode tmy,
423                                         const SkMatrix* localMatrix = NULL);
424 
425     /** Call this to create a new shader that will draw with the specified picture.
426      *
427      *  @param src  The picture to use inside the shader (if not NULL, its ref count
428      *              is incremented). The SkPicture must not be changed after
429      *              successfully creating a picture shader.
430      *  @param tmx  The tiling mode to use when sampling the bitmap in the x-direction.
431      *  @param tmy  The tiling mode to use when sampling the bitmap in the y-direction.
432      *  @param tile The tile rectangle in picture coordinates: this represents the subset
433      *              (or superset) of the picture used when building a tile. It is not
434      *              affected by localMatrix and does not imply scaling (only translation
435      *              and cropping). If null, the tile rect is considered equal to the picture
436      *              bounds.
437      *  @return     Returns a new shader object. Note: this function never returns null.
438     */
439     static SkShader* CreatePictureShader(const SkPicture* src,
440                                          TileMode tmx, TileMode tmy,
441                                          const SkMatrix* localMatrix,
442                                          const SkRect* tile);
443 
444     /**
445      *  Return a shader that will apply the specified localMatrix to the proxy shader.
446      *  The specified matrix will be applied before any matrix associated with the proxy.
447      *
448      *  Note: ownership of the proxy is not transferred (though a ref is taken).
449      */
450     static SkShader* CreateLocalMatrixShader(SkShader* proxy, const SkMatrix& localMatrix);
451 
452     /**
453      *  If this shader can be represented by another shader + a localMatrix, return that shader
454      *  and, if not NULL, the localMatrix. If not, return NULL and ignore the localMatrix parameter.
455      *
456      *  Note: the returned shader (if not NULL) will have been ref'd, and it is the responsibility
457      *  of the caller to balance that with unref() when they are done.
458      */
459     virtual SkShader* refAsALocalMatrixShader(SkMatrix* localMatrix) const;
460 
461     SK_TO_STRING_VIRT()
462     SK_DEFINE_FLATTENABLE_TYPE(SkShader)
463 
464 protected:
465     void flatten(SkWriteBuffer&) const override;
466 
467     bool computeTotalInverse(const ContextRec&, SkMatrix* totalInverse) const;
468 
469     /**
470      *  Your subclass must also override contextSize() if it overrides onCreateContext().
471      *  Base class impl returns NULL.
472      */
473     virtual Context* onCreateContext(const ContextRec&, void* storage) const;
474 
onAsLuminanceColor(SkColor *)475     virtual bool onAsLuminanceColor(SkColor*) const {
476         return false;
477     }
478 private:
479     // This is essentially const, but not officially so it can be modified in
480     // constructors.
481     SkMatrix fLocalMatrix;
482 
483     // So the SkLocalMatrixShader can whack fLocalMatrix in its SkReadBuffer constructor.
484     friend class SkLocalMatrixShader;
485 
486     typedef SkFlattenable INHERITED;
487 };
488 
489 #endif
490