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 colors during drawing.
     31     A subclass of SkShader is installed in a SkPaint calling paint.setShader(shader). After that
     32     any object (other than a bitmap) that is drawn with that paint will get its color(s) from the
     33     shader.
     34 */
     35 class SkShader : public SkFlattenable {
     36 public:
     37             SkShader();
     38     virtual ~SkShader();
     39 
     40     /** Return true if the shader has a non-identity local matrix.
     41         @param localM   Optional: If not null, return the shader's local matrix
     42         @return true if the shader has a non-identity local matrix.
     43     */
     44     bool getLocalMatrix(SkMatrix* localM) const;
     45     /** Set the shader's local matrix.
     46         @param localM   The shader's new local matrix.
     47     */
     48     void setLocalMatrix(const SkMatrix& localM);
     49     /** Reset the shader's local matrix to identity.
     50     */
     51     void resetLocalMatrix();
     52 
     53     enum TileMode {
     54         kClamp_TileMode,    //!< replicate the edge color if the shader draws outside of its original bounds
     55         kRepeat_TileMode,   //!< repeat the shader's image horizontally and vertically
     56         kMirror_TileMode,   //!< repeat the shader's image horizontally and vertically, alternating mirror images so that adjacent images always seam
     57 
     58         kTileModeCount
     59     };
     60 
     61     // override these in your subclass
     62 
     63     enum Flags {
     64         //!< set if all of the colors will be opaque
     65         kOpaqueAlpha_Flag  = 0x01,
     66 
     67         //! set if this shader's shadeSpan16() method can be called
     68         kHasSpan16_Flag = 0x02,
     69 
     70         /** Set this bit if the shader's native data type is instrinsically 16
     71             bit, meaning that calling the 32bit shadeSpan() entry point will
     72             mean the the impl has to up-sample 16bit data into 32bit. Used as a
     73             a means of clearing a dither request if the it will have no effect
     74         */
     75         kIntrinsicly16_Flag = 0x04,
     76 
     77         /** set (after setContext) if the spans only vary in X (const in Y).
     78             e.g. an Nx1 bitmap that is being tiled in Y, or a linear-gradient
     79             that varies from left-to-right. This flag specifies this for
     80             shadeSpan().
     81          */
     82         kConstInY32_Flag = 0x08,
     83 
     84         /** same as kConstInY32_Flag, but is set if this is true for shadeSpan16
     85             which may not always be the case, since shadeSpan16 may be
     86             predithered, which would mean it was not const in Y, even though
     87             the 32bit shadeSpan() would be const.
     88          */
     89         kConstInY16_Flag = 0x10
     90     };
     91 
     92     /** Called sometimes before drawing with this shader.
     93         Return the type of alpha your shader will return.
     94         The default implementation returns 0. Your subclass should override if it can
     95         (even sometimes) report a non-zero value, since that will enable various blitters
     96         to perform faster.
     97     */
     98     virtual uint32_t getFlags() { return 0; }
     99 
    100     /** Return the alpha associated with the data returned by shadeSpan16(). If
    101         kHasSpan16_Flag is not set, this value is meaningless.
    102     */
    103     virtual uint8_t getSpan16Alpha() const { return fPaintAlpha; }
    104 
    105     /** Called once before drawing, with the current paint and
    106         device matrix. Return true if your shader supports these
    107         parameters, or false if not. If false is returned, nothing
    108         will be drawn.
    109     */
    110     virtual bool setContext(const SkBitmap& device, const SkPaint& paint,
    111                             const SkMatrix& matrix);
    112 
    113     /** Called for each span of the object being drawn. Your subclass
    114         should set the appropriate colors (with premultiplied alpha) that
    115         correspond to the specified device coordinates.
    116     */
    117     virtual void shadeSpan(int x, int y, SkPMColor[], int count) = 0;
    118     /** Called only for 16bit devices when getFlags() returns
    119         kOpaqueAlphaFlag | kHasSpan16_Flag
    120     */
    121     virtual void shadeSpan16(int x, int y, uint16_t[], int count);
    122     /** Similar to shadeSpan, but only returns the alpha-channel for a span.
    123         The default implementation calls shadeSpan() and then extracts the alpha
    124         values from the returned colors.
    125     */
    126     virtual void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count);
    127 
    128     /** Helper function that returns true if this shader's shadeSpan16() method can
    129         be called.
    130     */
    131     bool canCallShadeSpan16() {
    132         return SkShader::CanCallShadeSpan16(this->getFlags());
    133     }
    134 
    135     /** Helper to check the flags to know if it is legal to call shadeSpan16()
    136     */
    137     static bool CanCallShadeSpan16(uint32_t flags) {
    138         return (flags & kHasSpan16_Flag) != 0;
    139     }
    140 
    141     /** Called before a session using the shader begins. Some shaders override
    142         this to defer some of their work (like calling bitmap.lockPixels()).
    143         Must be balanced by a call to endSession.
    144     */
    145     virtual void beginSession();
    146     virtual void endSession();
    147 
    148     /** Optional methods for shaders that can pretend to be a bitmap/texture
    149         to play along with opengl. Default just returns false and ignores
    150         the out parameters.
    151     */
    152     virtual bool asABitmap(SkBitmap* outTexture, SkMatrix* outMatrix,
    153                            TileMode xy[2]);
    154 
    155     //////////////////////////////////////////////////////////////////////////
    156     //  Factory methods for stock shaders
    157 
    158     /** Call this to create a new shader that will draw with the specified bitmap.
    159         @param src  The bitmap to use inside the shader
    160         @param tmx  The tiling mode to use when sampling the bitmap in the x-direction.
    161         @param tmy  The tiling mode to use when sampling the bitmap in the y-direction.
    162         @return     Returns a new shader object. Note: this function never returns null.
    163     */
    164     static SkShader* CreateBitmapShader(const SkBitmap& src,
    165                                         TileMode tmx, TileMode tmy);
    166 
    167     virtual void flatten(SkFlattenableWriteBuffer& );
    168 protected:
    169     enum MatrixClass {
    170         kLinear_MatrixClass,            // no perspective
    171         kFixedStepInX_MatrixClass,      // fast perspective, need to call fixedStepInX() each scanline
    172         kPerspective_MatrixClass        // slow perspective, need to mappoints each pixel
    173     };
    174     static MatrixClass ComputeMatrixClass(const SkMatrix&);
    175 
    176     // These can be called by your subclass after setContext() has been called
    177     uint8_t             getPaintAlpha() const { return fPaintAlpha; }
    178     SkBitmap::Config    getDeviceConfig() const { return (SkBitmap::Config)fDeviceConfig; }
    179     const SkMatrix&     getTotalInverse() const { return fTotalInverse; }
    180     MatrixClass         getInverseClass() const { return (MatrixClass)fTotalInverseClass; }
    181 
    182     SkShader(SkFlattenableReadBuffer& );
    183 private:
    184     SkMatrix*           fLocalMatrix;
    185     SkMatrix            fTotalInverse;
    186     uint8_t             fPaintAlpha;
    187     uint8_t             fDeviceConfig;
    188     uint8_t             fTotalInverseClass;
    189     SkDEBUGCODE(SkBool8 fInSession;)
    190 
    191     static SkShader* CreateBitmapShader(const SkBitmap& src,
    192                                         TileMode, TileMode,
    193                                         void* storage, size_t storageSize);
    194     friend class SkAutoBitmapShaderInstall;
    195     typedef SkFlattenable INHERITED;
    196 };
    197 
    198 #endif
    199 
    200