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