• 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 #ifndef SkShader_DEFINED
9 #define SkShader_DEFINED
10 
11 #include "SkBitmap.h"
12 #include "SkFlattenable.h"
13 #include "SkImageInfo.h"
14 #include "SkMask.h"
15 #include "SkMatrix.h"
16 #include "SkPaint.h"
17 #include "../gpu/GrColor.h"
18 
19 class SkColorFilter;
20 class SkPath;
21 class SkPicture;
22 class SkXfermode;
23 class GrContext;
24 class GrFragmentProcessor;
25 
26 /** \class SkShader
27  *
28  *  Shaders specify the source color(s) for what is being drawn. If a paint
29  *  has no shader, then the paint's color is used. If the paint has a
30  *  shader, then the shader's color(s) are use instead, but they are
31  *  modulated by the paint's alpha. This makes it easy to create a shader
32  *  once (e.g. bitmap tiling or gradient) and then change its transparency
33  *  w/o having to modify the original shader... only the paint's alpha needs
34  *  to be modified.
35  */
36 class SK_API SkShader : public SkFlattenable {
37 public:
38     SkShader(const SkMatrix* localMatrix = NULL);
39     virtual ~SkShader();
40 
41     /**
42      *  Returns the local matrix.
43      *
44      *  FIXME: This can be incorrect for a Shader with its own local matrix
45      *  that is also wrapped via CreateLocalMatrixShader.
46      */
getLocalMatrix()47     const SkMatrix& getLocalMatrix() const { return fLocalMatrix; }
48 
49     enum TileMode {
50         /** replicate the edge color if the shader draws outside of its
51          *  original bounds
52          */
53         kClamp_TileMode,
54 
55         /** repeat the shader's image horizontally and vertically */
56         kRepeat_TileMode,
57 
58         /** repeat the shader's image horizontally and vertically, alternating
59          *  mirror images so that adjacent images always seam
60          */
61         kMirror_TileMode,
62 
63 #if 0
64         /** only draw within the original domain, return 0 everywhere else */
65         kDecal_TileMode,
66 #endif
67     };
68 
69     enum {
70         kTileModeCount = kMirror_TileMode + 1
71     };
72 
73     // override these in your subclass
74 
75     enum Flags {
76         //!< set if all of the colors will be opaque
77         kOpaqueAlpha_Flag = 1 << 0,
78 
79         /** set if the spans only vary in X (const in Y).
80             e.g. an Nx1 bitmap that is being tiled in Y, or a linear-gradient
81             that varies from left-to-right. This flag specifies this for
82             shadeSpan().
83          */
84         kConstInY32_Flag = 1 << 1,
85 
86         /** hint for the blitter that 4f is the preferred shading mode.
87          */
88         kPrefers4f_Flag  = 1 << 2,
89     };
90 
91     /**
92      *  Returns true if the shader is guaranteed to produce only opaque
93      *  colors, subject to the SkPaint using the shader to apply an opaque
94      *  alpha value. Subclasses should override this to allow some
95      *  optimizations.
96      */
isOpaque()97     virtual bool isOpaque() const { return false; }
98 
99     /**
100      *  ContextRec acts as a parameter bundle for creating Contexts.
101      */
102     struct ContextRec {
103         enum DstType {
104             kPMColor_DstType, // clients prefer shading into PMColor dest
105             kPM4f_DstType,    // clients prefer shading into PM4f dest
106         };
107 
ContextRecContextRec108         ContextRec(const SkPaint& paint, const SkMatrix& matrix, const SkMatrix* localM,
109                    DstType dstType)
110             : fPaint(&paint)
111             , fMatrix(&matrix)
112             , fLocalMatrix(localM)
113             , fPreferredDstType(dstType) {}
114 
115         const SkPaint*  fPaint;            // the current paint associated with the draw
116         const SkMatrix* fMatrix;           // the current matrix in the canvas
117         const SkMatrix* fLocalMatrix;      // optional local matrix
118         const DstType   fPreferredDstType; // the "natural" client dest type
119     };
120 
121     class Context : public ::SkNoncopyable {
122     public:
123         Context(const SkShader& shader, const ContextRec&);
124 
125         virtual ~Context();
126 
127         /**
128          *  Called sometimes before drawing with this shader. Return the type of
129          *  alpha your shader will return. The default implementation returns 0.
130          *  Your subclass should override if it can (even sometimes) report a
131          *  non-zero value, since that will enable various blitters to perform
132          *  faster.
133          */
getFlags()134         virtual uint32_t getFlags() const { return 0; }
135 
136         /**
137          *  Called for each span of the object being drawn. Your subclass should
138          *  set the appropriate colors (with premultiplied alpha) that correspond
139          *  to the specified device coordinates.
140          */
141         virtual void shadeSpan(int x, int y, SkPMColor[], int count) = 0;
142 
143         virtual void shadeSpan4f(int x, int y, SkPM4f[], int count);
144 
145         /**
146          * The const void* ctx is only const because all the implementations are const.
147          * This can be changed to non-const if a new shade proc needs to change the ctx.
148          */
149         typedef void (*ShadeProc)(const void* ctx, int x, int y, SkPMColor[], int count);
150         virtual ShadeProc asAShadeProc(void** ctx);
151 
152         /**
153          *  Similar to shadeSpan, but only returns the alpha-channel for a span.
154          *  The default implementation calls shadeSpan() and then extracts the alpha
155          *  values from the returned colors.
156          */
157         virtual void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count);
158 
159         // Notification from blitter::blitMask in case we need to see the non-alpha channels
set3DMask(const SkMask *)160         virtual void set3DMask(const SkMask*) {}
161 
162     protected:
163         // Reference to shader, so we don't have to dupe information.
164         const SkShader& fShader;
165 
166         enum MatrixClass {
167             kLinear_MatrixClass,            // no perspective
168             kFixedStepInX_MatrixClass,      // fast perspective, need to call fixedStepInX() each
169                                             // scanline
170             kPerspective_MatrixClass        // slow perspective, need to mappoints each pixel
171         };
172         static MatrixClass ComputeMatrixClass(const SkMatrix&);
173 
getPaintAlpha()174         uint8_t         getPaintAlpha() const { return fPaintAlpha; }
getTotalInverse()175         const SkMatrix& getTotalInverse() const { return fTotalInverse; }
getInverseClass()176         MatrixClass     getInverseClass() const { return (MatrixClass)fTotalInverseClass; }
getCTM()177         const SkMatrix& getCTM() const { return fCTM; }
178     private:
179         SkMatrix    fCTM;
180         SkMatrix    fTotalInverse;
181         uint8_t     fPaintAlpha;
182         uint8_t     fTotalInverseClass;
183 
184         typedef SkNoncopyable INHERITED;
185     };
186 
187     /**
188      *  Create the actual object that does the shading.
189      *  Size of storage must be >= contextSize.
190      */
191     Context* createContext(const ContextRec&, void* storage) const;
192 
193     /**
194      *  Return the size of a Context returned by createContext.
195      *
196      *  Override this if your subclass overrides createContext, to return the correct size of
197      *  your subclass' context.
198      */
199     virtual size_t contextSize(const ContextRec&) const;
200 
201     /**
202      *  Returns true if this shader is just a bitmap, and if not null, returns the bitmap,
203      *  localMatrix, and tilemodes. If this is not a bitmap, returns false and ignores the
204      *  out-parameters.
205      */
isABitmap(SkBitmap * outTexture,SkMatrix * outMatrix,TileMode xy[2])206     bool isABitmap(SkBitmap* outTexture, SkMatrix* outMatrix, TileMode xy[2]) const {
207         return this->onIsABitmap(outTexture, outMatrix, xy);
208     }
209 
isABitmap()210     bool isABitmap() const {
211         return this->isABitmap(nullptr, nullptr, nullptr);
212     }
213 
214     /**
215      *  If the shader subclass can be represented as a gradient, asAGradient
216      *  returns the matching GradientType enum (or kNone_GradientType if it
217      *  cannot). Also, if info is not null, asAGradient populates info with
218      *  the relevant (see below) parameters for the gradient.  fColorCount
219      *  is both an input and output parameter.  On input, it indicates how
220      *  many entries in fColors and fColorOffsets can be used, if they are
221      *  non-NULL.  After asAGradient has run, fColorCount indicates how
222      *  many color-offset pairs there are in the gradient.  If there is
223      *  insufficient space to store all of the color-offset pairs, fColors
224      *  and fColorOffsets will not be altered.  fColorOffsets specifies
225      *  where on the range of 0 to 1 to transition to the given color.
226      *  The meaning of fPoint and fRadius is dependant on the type of gradient.
227      *
228      *  None:
229      *      info is ignored.
230      *  Color:
231      *      fColorOffsets[0] is meaningless.
232      *  Linear:
233      *      fPoint[0] and fPoint[1] are the end-points of the gradient
234      *  Radial:
235      *      fPoint[0] and fRadius[0] are the center and radius
236      *  Conical:
237      *      fPoint[0] and fRadius[0] are the center and radius of the 1st circle
238      *      fPoint[1] and fRadius[1] are the center and radius of the 2nd circle
239      *  Sweep:
240      *      fPoint[0] is the center of the sweep.
241      */
242 
243     enum GradientType {
244         kNone_GradientType,
245         kColor_GradientType,
246         kLinear_GradientType,
247         kRadial_GradientType,
248         kSweep_GradientType,
249         kConical_GradientType,
250         kLast_GradientType = kConical_GradientType
251     };
252 
253     struct GradientInfo {
254         int         fColorCount;    //!< In-out parameter, specifies passed size
255                                     //   of fColors/fColorOffsets on input, and
256                                     //   actual number of colors/offsets on
257                                     //   output.
258         SkColor*    fColors;        //!< The colors in the gradient.
259         SkScalar*   fColorOffsets;  //!< The unit offset for color transitions.
260         SkPoint     fPoint[2];      //!< Type specific, see above.
261         SkScalar    fRadius[2];     //!< Type specific, see above.
262         TileMode    fTileMode;      //!< The tile mode used.
263         uint32_t    fGradientFlags; //!< see SkGradientShader::Flags
264     };
265 
266     virtual GradientType asAGradient(GradientInfo* info) const;
267 
268     /**
269      *  If the shader subclass is composed of two shaders, return true, and if rec is not NULL,
270      *  fill it out with info about the shader.
271      *
272      *  These are bare pointers; the ownership and reference count are unchanged.
273      */
274 
275     struct ComposeRec {
276         const SkShader*     fShaderA;
277         const SkShader*     fShaderB;
278         const SkXfermode*   fMode;
279     };
280 
asACompose(ComposeRec *)281     virtual bool asACompose(ComposeRec*) const { return false; }
282 
283 
284     /**
285      *  Returns a GrFragmentProcessor that implements the shader for the GPU backend. NULL is
286      *  returned if there is no GPU implementation.
287      *
288      *  The GPU device does not call SkShader::createContext(), instead we pass the view matrix,
289      *  local matrix, and filter quality directly.
290      *
291      *  The GrContext may be used by the to create textures that are required by the returned
292      *  processor.
293      *
294      *  The returned GrFragmentProcessor should expect an unpremultiplied input color and
295      *  produce a premultiplied output.
296      */
297     virtual const GrFragmentProcessor* asFragmentProcessor(GrContext*,
298                                                            const SkMatrix& viewMatrix,
299                                                            const SkMatrix* localMatrix,
300                                                            SkFilterQuality) const;
301 
302     /**
303      *  If the shader can represent its "average" luminance in a single color, return true and
304      *  if color is not NULL, return that color. If it cannot, return false and ignore the color
305      *  parameter.
306      *
307      *  Note: if this returns true, the returned color will always be opaque, as only the RGB
308      *  components are used to compute luminance.
309      */
310     bool asLuminanceColor(SkColor*) const;
311 
312 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
313     /**
314      *  If the shader is a custom shader which has data the caller might want, call this function
315      *  to get that data.
316      */
asACustomShader(void **)317     virtual bool asACustomShader(void** /* customData */) const { return false; }
318 #endif
319 
320     //////////////////////////////////////////////////////////////////////////
321     //  Methods to create combinations or variants of shaders
322 
323     /**
324      *  Return a shader that will apply the specified localMatrix to this shader.
325      *  The specified matrix will be applied before any matrix associated with this shader.
326      */
327     SkShader* newWithLocalMatrix(const SkMatrix&) const;
328 
329     /**
330      *  Create a new shader that produces the same colors as invoking this shader and then applying
331      *  the colorfilter.
332      */
333     SkShader* newWithColorFilter(SkColorFilter*) const;
334 
335     //////////////////////////////////////////////////////////////////////////
336     //  Factory methods for stock shaders
337 
338     /**
339      *  Call this to create a new "empty" shader, that will not draw anything.
340      */
341     static SkShader* CreateEmptyShader();
342 
343     /**
344      *  Call this to create a new shader that just draws the specified color. This should always
345      *  draw the same as a paint with this color (and no shader).
346      */
347     static SkShader* CreateColorShader(SkColor);
348 
349     static SkShader* CreateComposeShader(SkShader* dst, SkShader* src, SkXfermode::Mode);
350 
351     /**
352      *  Create a new compose shader, given shaders dst, src, and a combining xfermode mode.
353      *  The xfermode is called with the output of the two shaders, and its output is returned.
354      *  If xfer is null, SkXfermode::kSrcOver_Mode is assumed.
355      *
356      *  Ownership of the shaders, and the xfermode if not null, is not transfered, so the caller
357      *  is still responsible for managing its reference-count for those objects.
358      */
359     static SkShader* CreateComposeShader(SkShader* dst, SkShader* src, SkXfermode* xfer);
360 
361     /** Call this to create a new shader that will draw with the specified bitmap.
362      *
363      *  If the bitmap cannot be used (e.g. has no pixels, or its dimensions
364      *  exceed implementation limits (currently at 64K - 1)) then SkEmptyShader
365      *  may be returned.
366      *
367      *  If the src is kA8_Config then that mask will be colorized using the color on
368      *  the paint.
369      *
370      *  @param src  The bitmap to use inside the shader
371      *  @param tmx  The tiling mode to use when sampling the bitmap in the x-direction.
372      *  @param tmy  The tiling mode to use when sampling the bitmap in the y-direction.
373      *  @return     Returns a new shader object. Note: this function never returns null.
374     */
375     static SkShader* CreateBitmapShader(const SkBitmap& src,
376                                         TileMode tmx, TileMode tmy,
377                                         const SkMatrix* localMatrix = NULL);
378 
379     // NOTE: You can create an SkImage Shader with SkImage::newShader().
380 
381     /** Call this to create a new shader that will draw with the specified picture.
382      *
383      *  @param src  The picture to use inside the shader (if not NULL, its ref count
384      *              is incremented). The SkPicture must not be changed after
385      *              successfully creating a picture shader.
386      *  @param tmx  The tiling mode to use when sampling the bitmap in the x-direction.
387      *  @param tmy  The tiling mode to use when sampling the bitmap in the y-direction.
388      *  @param tile The tile rectangle in picture coordinates: this represents the subset
389      *              (or superset) of the picture used when building a tile. It is not
390      *              affected by localMatrix and does not imply scaling (only translation
391      *              and cropping). If null, the tile rect is considered equal to the picture
392      *              bounds.
393      *  @return     Returns a new shader object. Note: this function never returns null.
394     */
395     static SkShader* CreatePictureShader(const SkPicture* src,
396                                          TileMode tmx, TileMode tmy,
397                                          const SkMatrix* localMatrix,
398                                          const SkRect* tile);
399 
400     /**
401      *  If this shader can be represented by another shader + a localMatrix, return that shader
402      *  and, if not NULL, the localMatrix. If not, return NULL and ignore the localMatrix parameter.
403      *
404      *  Note: the returned shader (if not NULL) will have been ref'd, and it is the responsibility
405      *  of the caller to balance that with unref() when they are done.
406      */
407     virtual SkShader* refAsALocalMatrixShader(SkMatrix* localMatrix) const;
408 
409     SK_TO_STRING_VIRT()
410     SK_DEFINE_FLATTENABLE_TYPE(SkShader)
411 
412 protected:
413     void flatten(SkWriteBuffer&) const override;
414 
415     bool computeTotalInverse(const ContextRec&, SkMatrix* totalInverse) const;
416 
417     /**
418      *  Your subclass must also override contextSize() if it overrides onCreateContext().
419      *  Base class impl returns NULL.
420      */
421     virtual Context* onCreateContext(const ContextRec&, void* storage) const;
422 
onAsLuminanceColor(SkColor *)423     virtual bool onAsLuminanceColor(SkColor*) const {
424         return false;
425     }
426 
onIsABitmap(SkBitmap *,SkMatrix *,TileMode[2])427     virtual bool onIsABitmap(SkBitmap*, SkMatrix*, TileMode[2]) const {
428         return false;
429     }
430 
431 private:
432     // This is essentially const, but not officially so it can be modified in
433     // constructors.
434     SkMatrix fLocalMatrix;
435 
436     // So the SkLocalMatrixShader can whack fLocalMatrix in its SkReadBuffer constructor.
437     friend class SkLocalMatrixShader;
438     friend class SkBitmapProcShader;    // for computeTotalInverse()
439 
440     typedef SkFlattenable INHERITED;
441 };
442 
443 #endif
444