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