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 #ifndef SkShader_DEFINED 9 #define SkShader_DEFINED 10 11 #include "SkBlendMode.h" 12 #include "SkColor.h" 13 #include "SkFilterQuality.h" 14 #include "SkFlattenable.h" 15 #include "SkImageInfo.h" 16 #include "SkMatrix.h" 17 18 class SkArenaAlloc; 19 class SkBitmap; 20 class SkColorFilter; 21 class SkColorSpace; 22 class SkColorSpaceXformer; 23 class SkImage; 24 class SkPath; 25 class SkPicture; 26 class SkRasterPipeline; 27 class GrContext; 28 class GrFragmentProcessor; 29 30 /** \class SkShader 31 * 32 * Shaders specify the source color(s) for what is being drawn. If a paint 33 * has no shader, then the paint's color is used. If the paint has a 34 * shader, then the shader's color(s) are use instead, but they are 35 * modulated by the paint's alpha. This makes it easy to create a shader 36 * once (e.g. bitmap tiling or gradient) and then change its transparency 37 * w/o having to modify the original shader... only the paint's alpha needs 38 * to be modified. 39 */ 40 class SK_API SkShader : public SkFlattenable { 41 public: 42 enum TileMode { 43 /** replicate the edge color if the shader draws outside of its 44 * original bounds 45 */ 46 kClamp_TileMode, 47 48 /** repeat the shader's image horizontally and vertically */ 49 kRepeat_TileMode, 50 51 /** repeat the shader's image horizontally and vertically, alternating 52 * mirror images so that adjacent images always seam 53 */ 54 kMirror_TileMode, 55 56 /** 57 * Only draw within the original domain, return transparent-black everywhere else. 58 * EXPERIMENTAL -- DO NOT USE YET 59 */ 60 kDecal_TileMode, 61 62 kLast_TileMode = kDecal_TileMode 63 }; 64 65 enum { 66 kTileModeCount = kLast_TileMode + 1 67 }; 68 69 /** 70 * Returns the local matrix. 71 * 72 * FIXME: This can be incorrect for a Shader with its own local matrix 73 * that is also wrapped via CreateLocalMatrixShader. 74 */ 75 const SkMatrix& getLocalMatrix() const; 76 77 /** 78 * Returns true if the shader is guaranteed to produce only opaque 79 * colors, subject to the SkPaint using the shader to apply an opaque 80 * alpha value. Subclasses should override this to allow some 81 * optimizations. 82 */ isOpaque()83 virtual bool isOpaque() const { return false; } 84 85 #ifdef SK_SUPPORT_LEGACY_SHADER_ISABITMAP 86 /** 87 * Returns true if this shader is just a bitmap, and if not null, returns the bitmap, 88 * localMatrix, and tilemodes. If this is not a bitmap, returns false and ignores the 89 * out-parameters. 90 */ 91 bool isABitmap(SkBitmap* outTexture, SkMatrix* outMatrix, TileMode xy[2]) const; 92 isABitmap()93 bool isABitmap() const { 94 return this->isABitmap(nullptr, nullptr, nullptr); 95 } 96 #endif 97 98 /** 99 * Iff this shader is backed by a single SkImage, return its ptr (the caller must ref this 100 * if they want to keep it longer than the lifetime of the shader). If not, return nullptr. 101 */ 102 SkImage* isAImage(SkMatrix* localMatrix, TileMode xy[2]) const; 103 isAImage()104 bool isAImage() const { 105 return this->isAImage(nullptr, nullptr) != nullptr; 106 } 107 108 /** 109 * If the shader subclass can be represented as a gradient, asAGradient 110 * returns the matching GradientType enum (or kNone_GradientType if it 111 * cannot). Also, if info is not null, asAGradient populates info with 112 * the relevant (see below) parameters for the gradient. fColorCount 113 * is both an input and output parameter. On input, it indicates how 114 * many entries in fColors and fColorOffsets can be used, if they are 115 * non-NULL. After asAGradient has run, fColorCount indicates how 116 * many color-offset pairs there are in the gradient. If there is 117 * insufficient space to store all of the color-offset pairs, fColors 118 * and fColorOffsets will not be altered. fColorOffsets specifies 119 * where on the range of 0 to 1 to transition to the given color. 120 * The meaning of fPoint and fRadius is dependant on the type of gradient. 121 * 122 * None: 123 * info is ignored. 124 * Color: 125 * fColorOffsets[0] is meaningless. 126 * Linear: 127 * fPoint[0] and fPoint[1] are the end-points of the gradient 128 * Radial: 129 * fPoint[0] and fRadius[0] are the center and radius 130 * Conical: 131 * fPoint[0] and fRadius[0] are the center and radius of the 1st circle 132 * fPoint[1] and fRadius[1] are the center and radius of the 2nd circle 133 * Sweep: 134 * fPoint[0] is the center of the sweep. 135 */ 136 137 enum GradientType { 138 kNone_GradientType, 139 kColor_GradientType, 140 kLinear_GradientType, 141 kRadial_GradientType, 142 kSweep_GradientType, 143 kConical_GradientType, 144 kLast_GradientType = kConical_GradientType 145 }; 146 147 struct GradientInfo { 148 int fColorCount; //!< In-out parameter, specifies passed size 149 // of fColors/fColorOffsets on input, and 150 // actual number of colors/offsets on 151 // output. 152 SkColor* fColors; //!< The colors in the gradient. 153 SkScalar* fColorOffsets; //!< The unit offset for color transitions. 154 SkPoint fPoint[2]; //!< Type specific, see above. 155 SkScalar fRadius[2]; //!< Type specific, see above. 156 TileMode fTileMode; //!< The tile mode used. 157 uint32_t fGradientFlags; //!< see SkGradientShader::Flags 158 }; 159 160 virtual GradientType asAGradient(GradientInfo* info) const; 161 162 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK 163 struct ComposeRec { 164 const SkShader* fShaderA; 165 const SkShader* fShaderB; 166 SkBlendMode fBlendMode; 167 }; asACompose(ComposeRec *)168 virtual bool asACompose(ComposeRec*) const { return false; } 169 #endif 170 171 ////////////////////////////////////////////////////////////////////////// 172 // Methods to create combinations or variants of shaders 173 174 /** 175 * Return a shader that will apply the specified localMatrix to this shader. 176 * The specified matrix will be applied before any matrix associated with this shader. 177 */ 178 sk_sp<SkShader> makeWithLocalMatrix(const SkMatrix&) const; 179 180 /** 181 * Create a new shader that produces the same colors as invoking this shader and then applying 182 * the colorfilter. 183 */ 184 sk_sp<SkShader> makeWithColorFilter(sk_sp<SkColorFilter>) const; 185 186 ////////////////////////////////////////////////////////////////////////// 187 // Factory methods for stock shaders 188 189 /** 190 * Call this to create a new "empty" shader, that will not draw anything. 191 */ 192 static sk_sp<SkShader> MakeEmptyShader(); 193 194 /** 195 * Call this to create a new shader that just draws the specified color. This should always 196 * draw the same as a paint with this color (and no shader). 197 */ 198 static sk_sp<SkShader> MakeColorShader(SkColor); 199 200 /** 201 * Create a shader that draws the specified color (in the specified colorspace). 202 * 203 * This works around the limitation that SkPaint::setColor() only takes byte values, and does 204 * not support specific colorspaces. 205 */ 206 static sk_sp<SkShader> MakeColorShader(const SkColor4f&, sk_sp<SkColorSpace>); 207 208 /** 209 * Compose two shaders together, using two operators: mode and lerp. The resulting colors 210 * are computed by first combining the src and dst shaders using mode, and then linearly 211 * interpolating between the dst and result colors using lerp. 212 * 213 * result = dst * (1 - lerp) + (src (mode) dst) * lerp 214 * 215 * If either shader is nullptr, then this returns nullptr. 216 * If lerp is NaN then this returns nullptr, otherwise lerp is clamped to [0..1]. 217 */ 218 static sk_sp<SkShader> MakeCompose(sk_sp<SkShader> dst, sk_sp<SkShader> src, 219 SkBlendMode mode, float lerp = 1); 220 221 /* 222 * DEPRECATED: call MakeCompose. 223 */ MakeComposeShader(sk_sp<SkShader> dst,sk_sp<SkShader> src,SkBlendMode mode)224 static sk_sp<SkShader> MakeComposeShader(sk_sp<SkShader> dst, sk_sp<SkShader> src, 225 SkBlendMode mode) { 226 return MakeCompose(std::move(dst), std::move(src), mode, 1); 227 } 228 229 /** 230 * Compose two shaders together using a weighted average. 231 * 232 * result = dst * (1 - lerp) + src * lerp 233 * 234 * If either shader is nullptr, then this returns nullptr. 235 * If lerp is NaN then this returns nullptr, otherwise lerp is clamped to [0..1]. 236 */ MakeMixer(sk_sp<SkShader> dst,sk_sp<SkShader> src,float lerp)237 static sk_sp<SkShader> MakeMixer(sk_sp<SkShader> dst, sk_sp<SkShader> src, float lerp) { 238 return MakeCompose(std::move(dst), std::move(src), SkBlendMode::kSrc, lerp); 239 } 240 241 /** Call this to create a new shader that will draw with the specified bitmap. 242 * 243 * If the bitmap cannot be used (e.g. has no pixels, or its dimensions 244 * exceed implementation limits (currently at 64K - 1)) then SkEmptyShader 245 * may be returned. 246 * 247 * If the src is kA8_Config then that mask will be colorized using the color on 248 * the paint. 249 * 250 * @param src The bitmap to use inside the shader 251 * @param tmx The tiling mode to use when sampling the bitmap in the x-direction. 252 * @param tmy The tiling mode to use when sampling the bitmap in the y-direction. 253 * @return Returns a new shader object. Note: this function never returns null. 254 */ 255 static sk_sp<SkShader> MakeBitmapShader(const SkBitmap& src, TileMode tmx, TileMode tmy, 256 const SkMatrix* localMatrix = nullptr); 257 258 // NOTE: You can create an SkImage Shader with SkImage::newShader(). 259 260 /** Call this to create a new shader that will draw with the specified picture. 261 * 262 * @param src The picture to use inside the shader (if not NULL, its ref count 263 * is incremented). The SkPicture must not be changed after 264 * successfully creating a picture shader. 265 * @param tmx The tiling mode to use when sampling the bitmap in the x-direction. 266 * @param tmy The tiling mode to use when sampling the bitmap in the y-direction. 267 * @param tile The tile rectangle in picture coordinates: this represents the subset 268 * (or superset) of the picture used when building a tile. It is not 269 * affected by localMatrix and does not imply scaling (only translation 270 * and cropping). If null, the tile rect is considered equal to the picture 271 * bounds. 272 * @return Returns a new shader object. Note: this function never returns null. 273 */ 274 static sk_sp<SkShader> MakePictureShader(sk_sp<SkPicture> src, TileMode tmx, TileMode tmy, 275 const SkMatrix* localMatrix, const SkRect* tile); 276 277 /** 278 * If this shader can be represented by another shader + a localMatrix, return that shader and 279 * the localMatrix. If not, return nullptr and ignore the localMatrix parameter. 280 */ 281 // TODO: clean up clients, move to SkShaderBase. 282 virtual sk_sp<SkShader> makeAsALocalMatrixShader(SkMatrix* localMatrix) const; 283 284 private: 285 SkShader() = default; 286 friend class SkShaderBase; 287 288 typedef SkFlattenable INHERITED; 289 }; 290 291 #endif 292