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