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