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