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