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 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 SkShader(const SkMatrix* localMatrix = NULL); 43 ~SkShader() override; 44 45 /** 46 * Returns the local matrix. 47 * 48 * FIXME: This can be incorrect for a Shader with its own local matrix 49 * that is also wrapped via CreateLocalMatrixShader. 50 */ getLocalMatrix()51 const SkMatrix& getLocalMatrix() const { return fLocalMatrix; } 52 53 enum TileMode { 54 /** replicate the edge color if the shader draws outside of its 55 * original bounds 56 */ 57 kClamp_TileMode, 58 59 /** repeat the shader's image horizontally and vertically */ 60 kRepeat_TileMode, 61 62 /** repeat the shader's image horizontally and vertically, alternating 63 * mirror images so that adjacent images always seam 64 */ 65 kMirror_TileMode, 66 67 #if 0 68 /** only draw within the original domain, return 0 everywhere else */ 69 kDecal_TileMode, 70 #endif 71 }; 72 73 enum { 74 kTileModeCount = kMirror_TileMode + 1 75 }; 76 77 // override these in your subclass 78 79 enum Flags { 80 //!< set if all of the colors will be opaque 81 kOpaqueAlpha_Flag = 1 << 0, 82 83 /** set if the spans only vary in X (const in Y). 84 e.g. an Nx1 bitmap that is being tiled in Y, or a linear-gradient 85 that varies from left-to-right. This flag specifies this for 86 shadeSpan(). 87 */ 88 kConstInY32_Flag = 1 << 1, 89 90 /** hint for the blitter that 4f is the preferred shading mode. 91 */ 92 kPrefers4f_Flag = 1 << 2, 93 }; 94 95 /** 96 * Returns true if the shader is guaranteed to produce only opaque 97 * colors, subject to the SkPaint using the shader to apply an opaque 98 * alpha value. Subclasses should override this to allow some 99 * optimizations. 100 */ isOpaque()101 virtual bool isOpaque() const { return false; } 102 103 /** 104 * Returns true if the shader is guaranteed to produce only a single color. 105 * Subclasses can override this to allow loop-hoisting optimization. 106 */ isConstant()107 virtual bool isConstant() const { return false; } 108 109 /** 110 * ContextRec acts as a parameter bundle for creating Contexts. 111 */ 112 struct ContextRec { 113 enum DstType { 114 kPMColor_DstType, // clients prefer shading into PMColor dest 115 kPM4f_DstType, // clients prefer shading into PM4f dest 116 }; 117 ContextRecContextRec118 ContextRec(const SkPaint& paint, const SkMatrix& matrix, const SkMatrix* localM, 119 DstType dstType, SkColorSpace* dstColorSpace) 120 : fPaint(&paint) 121 , fMatrix(&matrix) 122 , fLocalMatrix(localM) 123 , fPreferredDstType(dstType) 124 , fDstColorSpace(dstColorSpace) {} 125 126 const SkPaint* fPaint; // the current paint associated with the draw 127 const SkMatrix* fMatrix; // the current matrix in the canvas 128 const SkMatrix* fLocalMatrix; // optional local matrix 129 const DstType fPreferredDstType; // the "natural" client dest type 130 SkColorSpace* fDstColorSpace; // the color space of the dest surface (if any) 131 }; 132 133 class Context : public ::SkNoncopyable { 134 public: 135 Context(const SkShader& shader, const ContextRec&); 136 137 virtual ~Context(); 138 139 /** 140 * Called sometimes before drawing with this shader. Return the type of 141 * alpha your shader will return. The default implementation returns 0. 142 * Your subclass should override if it can (even sometimes) report a 143 * non-zero value, since that will enable various blitters to perform 144 * faster. 145 */ getFlags()146 virtual uint32_t getFlags() const { return 0; } 147 148 /** 149 * Called for each span of the object being drawn. Your subclass should 150 * set the appropriate colors (with premultiplied alpha) that correspond 151 * to the specified device coordinates. 152 */ 153 virtual void shadeSpan(int x, int y, SkPMColor[], int count) = 0; 154 155 virtual void shadeSpan4f(int x, int y, SkPM4f[], int count); 156 157 struct BlitState; 158 typedef void (*BlitBW)(BlitState*, 159 int x, int y, const SkPixmap&, int count); 160 typedef void (*BlitAA)(BlitState*, 161 int x, int y, const SkPixmap&, int count, const SkAlpha[]); 162 163 struct BlitState { 164 // inputs 165 Context* fCtx; 166 SkBlendMode fMode; 167 168 // outputs 169 enum { N = 2 }; 170 void* fStorage[N]; 171 BlitBW fBlitBW; 172 BlitAA fBlitAA; 173 }; 174 175 // Returns true if one or more of the blitprocs are set in the BlitState chooseBlitProcs(const SkImageInfo & info,BlitState * state)176 bool chooseBlitProcs(const SkImageInfo& info, BlitState* state) { 177 state->fBlitBW = nullptr; 178 state->fBlitAA = nullptr; 179 if (this->onChooseBlitProcs(info, state)) { 180 SkASSERT(state->fBlitBW || state->fBlitAA); 181 return true; 182 } 183 return false; 184 } 185 186 /** 187 * The const void* ctx is only const because all the implementations are const. 188 * This can be changed to non-const if a new shade proc needs to change the ctx. 189 */ 190 typedef void (*ShadeProc)(const void* ctx, int x, int y, SkPMColor[], int count); 191 virtual ShadeProc asAShadeProc(void** ctx); 192 193 /** 194 * Similar to shadeSpan, but only returns the alpha-channel for a span. 195 * The default implementation calls shadeSpan() and then extracts the alpha 196 * values from the returned colors. 197 */ 198 virtual void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count); 199 200 // Notification from blitter::blitMask in case we need to see the non-alpha channels set3DMask(const SkMask *)201 virtual void set3DMask(const SkMask*) {} 202 203 protected: 204 // Reference to shader, so we don't have to dupe information. 205 const SkShader& fShader; 206 207 enum MatrixClass { 208 kLinear_MatrixClass, // no perspective 209 kFixedStepInX_MatrixClass, // fast perspective, need to call fixedStepInX() each 210 // scanline 211 kPerspective_MatrixClass // slow perspective, need to mappoints each pixel 212 }; 213 static MatrixClass ComputeMatrixClass(const SkMatrix&); 214 getPaintAlpha()215 uint8_t getPaintAlpha() const { return fPaintAlpha; } getTotalInverse()216 const SkMatrix& getTotalInverse() const { return fTotalInverse; } getInverseClass()217 MatrixClass getInverseClass() const { return (MatrixClass)fTotalInverseClass; } getCTM()218 const SkMatrix& getCTM() const { return fCTM; } 219 onChooseBlitProcs(const SkImageInfo &,BlitState *)220 virtual bool onChooseBlitProcs(const SkImageInfo&, BlitState*) { return false; } 221 222 private: 223 SkMatrix fCTM; 224 SkMatrix fTotalInverse; 225 uint8_t fPaintAlpha; 226 uint8_t fTotalInverseClass; 227 228 typedef SkNoncopyable INHERITED; 229 }; 230 231 /** 232 * Make a context using the memory provided by the arena. 233 * 234 * @return pointer to context or nullptr if can't be created 235 */ 236 Context* makeContext(const ContextRec&, SkArenaAlloc*) const; 237 238 #ifdef SK_SUPPORT_LEGACY_SHADER_ISABITMAP 239 /** 240 * Returns true if this shader is just a bitmap, and if not null, returns the bitmap, 241 * localMatrix, and tilemodes. If this is not a bitmap, returns false and ignores the 242 * out-parameters. 243 */ isABitmap(SkBitmap * outTexture,SkMatrix * outMatrix,TileMode xy[2])244 bool isABitmap(SkBitmap* outTexture, SkMatrix* outMatrix, TileMode xy[2]) const { 245 return this->onIsABitmap(outTexture, outMatrix, xy); 246 } 247 isABitmap()248 bool isABitmap() const { 249 return this->isABitmap(nullptr, nullptr, nullptr); 250 } 251 #endif 252 253 /** 254 * Iff this shader is backed by a single SkImage, return its ptr (the caller must ref this 255 * if they want to keep it longer than the lifetime of the shader). If not, return nullptr. 256 */ isAImage(SkMatrix * localMatrix,TileMode xy[2])257 SkImage* isAImage(SkMatrix* localMatrix, TileMode xy[2]) const { 258 return this->onIsAImage(localMatrix, xy); 259 } 260 isAImage()261 bool isAImage() const { 262 return this->isAImage(nullptr, nullptr) != nullptr; 263 } 264 265 /** 266 * If the shader subclass can be represented as a gradient, asAGradient 267 * returns the matching GradientType enum (or kNone_GradientType if it 268 * cannot). Also, if info is not null, asAGradient populates info with 269 * the relevant (see below) parameters for the gradient. fColorCount 270 * is both an input and output parameter. On input, it indicates how 271 * many entries in fColors and fColorOffsets can be used, if they are 272 * non-NULL. After asAGradient has run, fColorCount indicates how 273 * many color-offset pairs there are in the gradient. If there is 274 * insufficient space to store all of the color-offset pairs, fColors 275 * and fColorOffsets will not be altered. fColorOffsets specifies 276 * where on the range of 0 to 1 to transition to the given color. 277 * The meaning of fPoint and fRadius is dependant on the type of gradient. 278 * 279 * None: 280 * info is ignored. 281 * Color: 282 * fColorOffsets[0] is meaningless. 283 * Linear: 284 * fPoint[0] and fPoint[1] are the end-points of the gradient 285 * Radial: 286 * fPoint[0] and fRadius[0] are the center and radius 287 * Conical: 288 * fPoint[0] and fRadius[0] are the center and radius of the 1st circle 289 * fPoint[1] and fRadius[1] are the center and radius of the 2nd circle 290 * Sweep: 291 * fPoint[0] is the center of the sweep. 292 */ 293 294 enum GradientType { 295 kNone_GradientType, 296 kColor_GradientType, 297 kLinear_GradientType, 298 kRadial_GradientType, 299 kSweep_GradientType, 300 kConical_GradientType, 301 kLast_GradientType = kConical_GradientType 302 }; 303 304 struct GradientInfo { 305 int fColorCount; //!< In-out parameter, specifies passed size 306 // of fColors/fColorOffsets on input, and 307 // actual number of colors/offsets on 308 // output. 309 SkColor* fColors; //!< The colors in the gradient. 310 SkScalar* fColorOffsets; //!< The unit offset for color transitions. 311 SkPoint fPoint[2]; //!< Type specific, see above. 312 SkScalar fRadius[2]; //!< Type specific, see above. 313 TileMode fTileMode; //!< The tile mode used. 314 uint32_t fGradientFlags; //!< see SkGradientShader::Flags 315 }; 316 317 virtual GradientType asAGradient(GradientInfo* info) const; 318 319 /** 320 * If the shader subclass is composed of two shaders, return true, and if rec is not NULL, 321 * fill it out with info about the shader. 322 * 323 * These are bare pointers; the ownership and reference count are unchanged. 324 */ 325 326 struct ComposeRec { 327 const SkShader* fShaderA; 328 const SkShader* fShaderB; 329 SkBlendMode fBlendMode; 330 }; 331 asACompose(ComposeRec *)332 virtual bool asACompose(ComposeRec*) const { return false; } 333 334 #if SK_SUPPORT_GPU 335 struct AsFPArgs { AsFPArgsAsFPArgs336 AsFPArgs() {} AsFPArgsAsFPArgs337 AsFPArgs(GrContext* context, 338 const SkMatrix* viewMatrix, 339 const SkMatrix* localMatrix, 340 SkFilterQuality filterQuality, 341 SkColorSpace* dstColorSpace) 342 : fContext(context) 343 , fViewMatrix(viewMatrix) 344 , fLocalMatrix(localMatrix) 345 , fFilterQuality(filterQuality) 346 , fDstColorSpace(dstColorSpace) {} 347 348 GrContext* fContext; 349 const SkMatrix* fViewMatrix; 350 const SkMatrix* fLocalMatrix; 351 SkFilterQuality fFilterQuality; 352 SkColorSpace* fDstColorSpace; 353 }; 354 355 /** 356 * Returns a GrFragmentProcessor that implements the shader for the GPU backend. NULL is 357 * returned if there is no GPU implementation. 358 * 359 * The GPU device does not call SkShader::createContext(), instead we pass the view matrix, 360 * local matrix, and filter quality directly. 361 * 362 * The GrContext may be used by the to create textures that are required by the returned 363 * processor. 364 * 365 * The returned GrFragmentProcessor should expect an unpremultiplied input color and 366 * produce a premultiplied output. 367 */ 368 virtual sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const; 369 #endif 370 371 /** 372 * If the shader can represent its "average" luminance in a single color, return true and 373 * if color is not NULL, return that color. If it cannot, return false and ignore the color 374 * parameter. 375 * 376 * Note: if this returns true, the returned color will always be opaque, as only the RGB 377 * components are used to compute luminance. 378 */ 379 bool asLuminanceColor(SkColor*) const; 380 381 ////////////////////////////////////////////////////////////////////////// 382 // Methods to create combinations or variants of shaders 383 384 /** 385 * Return a shader that will apply the specified localMatrix to this shader. 386 * The specified matrix will be applied before any matrix associated with this shader. 387 */ 388 sk_sp<SkShader> makeWithLocalMatrix(const SkMatrix&) const; 389 390 /** 391 * Create a new shader that produces the same colors as invoking this shader and then applying 392 * the colorfilter. 393 */ 394 sk_sp<SkShader> makeWithColorFilter(sk_sp<SkColorFilter>) const; 395 396 ////////////////////////////////////////////////////////////////////////// 397 // Factory methods for stock shaders 398 399 /** 400 * Call this to create a new "empty" shader, that will not draw anything. 401 */ 402 static sk_sp<SkShader> MakeEmptyShader(); 403 404 /** 405 * Call this to create a new shader that just draws the specified color. This should always 406 * draw the same as a paint with this color (and no shader). 407 */ 408 static sk_sp<SkShader> MakeColorShader(SkColor); 409 410 /** 411 * Create a shader that draws the specified color (in the specified colorspace). 412 * 413 * This works around the limitation that SkPaint::setColor() only takes byte values, and does 414 * not support specific colorspaces. 415 */ 416 static sk_sp<SkShader> MakeColorShader(const SkColor4f&, sk_sp<SkColorSpace>); 417 418 static sk_sp<SkShader> MakeComposeShader(sk_sp<SkShader> dst, sk_sp<SkShader> src, SkBlendMode); 419 420 /** Call this to create a new shader that will draw with the specified bitmap. 421 * 422 * If the bitmap cannot be used (e.g. has no pixels, or its dimensions 423 * exceed implementation limits (currently at 64K - 1)) then SkEmptyShader 424 * may be returned. 425 * 426 * If the src is kA8_Config then that mask will be colorized using the color on 427 * the paint. 428 * 429 * @param src The bitmap to use inside the shader 430 * @param tmx The tiling mode to use when sampling the bitmap in the x-direction. 431 * @param tmy The tiling mode to use when sampling the bitmap in the y-direction. 432 * @return Returns a new shader object. Note: this function never returns null. 433 */ 434 static sk_sp<SkShader> MakeBitmapShader(const SkBitmap& src, TileMode tmx, TileMode tmy, 435 const SkMatrix* localMatrix = nullptr); 436 437 // NOTE: You can create an SkImage Shader with SkImage::newShader(). 438 439 /** Call this to create a new shader that will draw with the specified picture. 440 * 441 * @param src The picture to use inside the shader (if not NULL, its ref count 442 * is incremented). The SkPicture must not be changed after 443 * successfully creating a picture shader. 444 * @param tmx The tiling mode to use when sampling the bitmap in the x-direction. 445 * @param tmy The tiling mode to use when sampling the bitmap in the y-direction. 446 * @param tile The tile rectangle in picture coordinates: this represents the subset 447 * (or superset) of the picture used when building a tile. It is not 448 * affected by localMatrix and does not imply scaling (only translation 449 * and cropping). If null, the tile rect is considered equal to the picture 450 * bounds. 451 * @return Returns a new shader object. Note: this function never returns null. 452 */ 453 static sk_sp<SkShader> MakePictureShader(sk_sp<SkPicture> src, TileMode tmx, TileMode tmy, 454 const SkMatrix* localMatrix, const SkRect* tile); 455 456 /** 457 * If this shader can be represented by another shader + a localMatrix, return that shader and 458 * the localMatrix. If not, return nullptr and ignore the localMatrix parameter. 459 */ 460 virtual sk_sp<SkShader> makeAsALocalMatrixShader(SkMatrix* localMatrix) const; 461 462 SK_TO_STRING_VIRT() 463 SK_DEFINE_FLATTENABLE_TYPE(SkShader) 464 SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() 465 466 bool appendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*, 467 const SkMatrix& ctm, const SkPaint&) const; 468 469 protected: 470 void flatten(SkWriteBuffer&) const override; 471 472 bool computeTotalInverse(const ContextRec&, SkMatrix* totalInverse) const; 473 474 /** 475 * Specialize creating a SkShader context using the supplied allocator. 476 * @return pointer to context owned by the arena allocator. 477 */ onMakeContext(const ContextRec &,SkArenaAlloc *)478 virtual Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const { 479 return nullptr; 480 } 481 onAsLuminanceColor(SkColor *)482 virtual bool onAsLuminanceColor(SkColor*) const { 483 return false; 484 } 485 486 #ifdef SK_SUPPORT_LEGACY_SHADER_ISABITMAP onIsABitmap(SkBitmap *,SkMatrix *,TileMode[2])487 virtual bool onIsABitmap(SkBitmap*, SkMatrix*, TileMode[2]) const { 488 return false; 489 } 490 #endif 491 onIsAImage(SkMatrix *,TileMode[2])492 virtual SkImage* onIsAImage(SkMatrix*, TileMode[2]) const { 493 return nullptr; 494 } 495 496 virtual bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*, 497 const SkMatrix&, const SkPaint&, 498 const SkMatrix* /*local matrix*/) const; 499 500 private: 501 // This is essentially const, but not officially so it can be modified in 502 // constructors. 503 SkMatrix fLocalMatrix; 504 505 // So the SkLocalMatrixShader can whack fLocalMatrix in its SkReadBuffer constructor. 506 friend class SkLocalMatrixShader; 507 friend class SkBitmapProcLegacyShader; // for computeTotalInverse() 508 509 typedef SkFlattenable INHERITED; 510 }; 511 512 #endif 513