Home | History | Annotate | Download | only in core
      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 
     19 class 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  */
     28 class SK_API SkShader : public SkFlattenable {
     29 public:
     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;
    283 protected:
    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& );
    298 private:
    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