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