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 */ getFlags()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 */ isOpaque()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 */ getSpan16Alpha()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 */ canCallShadeSpan16()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 */ CanCallShadeSpan16(uint32_t flags)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 getPaintAlpha()292 uint8_t getPaintAlpha() const { return fPaintAlpha; } getDeviceConfig()293 SkBitmap::Config getDeviceConfig() const { return (SkBitmap::Config)fDeviceConfig; } getTotalInverse()294 const SkMatrix& getTotalInverse() const { return fTotalInverse; } getInverseClass()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