1 /* 2 * Copyright 2019 Google LLC 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 SkImageFilters_DEFINED 9 #define SkImageFilters_DEFINED 10 11 #include "include/core/SkBlendMode.h" 12 #include "include/core/SkColor.h" 13 #include "include/core/SkImage.h" 14 #include "include/core/SkImageFilter.h" 15 #include "include/core/SkPicture.h" 16 #include "include/core/SkRect.h" 17 #include "include/core/SkTileMode.h" 18 19 #include <cstddef> 20 21 class SkBlender; 22 class SkColorFilter; 23 class SkPaint; 24 class SkRegion; 25 26 namespace skif { 27 static constexpr SkRect kNoCropRect = {SK_ScalarNegativeInfinity, SK_ScalarNegativeInfinity, 28 SK_ScalarInfinity, SK_ScalarInfinity}; 29 } 30 31 // A set of factory functions providing useful SkImageFilter effects. For image filters that take an 32 // input filter, providing nullptr means it will automatically use the dynamic source image. This 33 // source depends on how the filter is applied, but is either the contents of a saved layer when 34 // drawing with SkCanvas, or an explicit SkImage if using SkImage::makeWithFilter. 35 class SK_API SkImageFilters { 36 public: 37 // This is just a convenience type to allow passing SkIRects, SkRects, and optional pointers 38 // to those types as a crop rect for the image filter factories. It's not intended to be used 39 // directly. 40 struct CropRect { CropRectCropRect41 CropRect() : fCropRect(skif::kNoCropRect) {} 42 // Intentionally not explicit so callers don't have to use this type but can use SkIRect or 43 // SkRect as desired. CropRectCropRect44 CropRect(std::nullptr_t) : fCropRect(skif::kNoCropRect) {} CropRectCropRect45 CropRect(const SkIRect& crop) : fCropRect(SkRect::Make(crop)) {} CropRectCropRect46 CropRect(const SkRect& crop) : fCropRect(crop) {} CropRectCropRect47 CropRect(const SkIRect* optionalCrop) : fCropRect(optionalCrop ? SkRect::Make(*optionalCrop) 48 : skif::kNoCropRect) {} CropRectCropRect49 CropRect(const SkRect* optionalCrop) : fCropRect(optionalCrop ? *optionalCrop 50 : skif::kNoCropRect) {} 51 52 operator const SkRect*() const { return fCropRect == skif::kNoCropRect ? nullptr : &fCropRect; } 53 54 SkRect fCropRect; 55 }; 56 57 /** 58 * Create a filter that updates the alpha of the image based on 'region'. Pixels inside the 59 * region are made more opaque and pixels outside are made more transparent. 60 * 61 * Specifically, if a pixel is inside the region, its alpha will be set to 62 * max(innerMin, pixel's alpha). If a pixel is outside the region, its alpha will be updated to 63 * min(outerMax, pixel's alpha). 64 * @param region The geometric region controlling the inner and outer alpha thresholds. 65 * @param innerMin The minimum alpha value for pixels inside 'region'. 66 * @param outerMax The maximum alpha value for pixels outside of 'region'. 67 * @param input The input filter, or uses the source bitmap if this is null. 68 * @param cropRect Optional rectangle that crops the input and output. 69 */ 70 static sk_sp<SkImageFilter> AlphaThreshold(const SkRegion& region, SkScalar innerMin, 71 SkScalar outerMax, sk_sp<SkImageFilter> input, 72 const CropRect& cropRect = {}); 73 74 /** 75 * Create a filter that implements a custom blend mode. Each output pixel is the result of 76 * combining the corresponding background and foreground pixels using the 4 coefficients: 77 * k1 * foreground * background + k2 * foreground + k3 * background + k4 78 * @param k1, k2, k3, k4 The four coefficients used to combine the foreground and background. 79 * @param enforcePMColor If true, the RGB channels will be clamped to the calculated alpha. 80 * @param background The background content, using the source bitmap when this is null. 81 * @param foreground The foreground content, using the source bitmap when this is null. 82 * @param cropRect Optional rectangle that crops the inputs and output. 83 */ 84 static sk_sp<SkImageFilter> Arithmetic(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4, 85 bool enforcePMColor, sk_sp<SkImageFilter> background, 86 sk_sp<SkImageFilter> foreground, 87 const CropRect& cropRect = {}); 88 89 /** 90 * This filter takes an SkBlendMode and uses it to composite the two filters together. 91 * @param mode The blend mode that defines the compositing operation 92 * @param background The Dst pixels used in blending, if null the source bitmap is used. 93 * @param foreground The Src pixels used in blending, if null the source bitmap is used. 94 * @cropRect Optional rectangle to crop input and output. 95 */ 96 static sk_sp<SkImageFilter> Blend(SkBlendMode mode, sk_sp<SkImageFilter> background, 97 sk_sp<SkImageFilter> foreground = nullptr, 98 const CropRect& cropRect = {}); 99 100 /** 101 * This filter takes an SkBlendMode and uses it to composite the two filters together. 102 * @param blender The blender that defines the compositing operation 103 * @param background The Dst pixels used in blending, if null the source bitmap is used. 104 * @param foreground The Src pixels used in blending, if null the source bitmap is used. 105 * @cropRect Optional rectangle to crop input and output. 106 */ 107 static sk_sp<SkImageFilter> Blend(sk_sp<SkBlender> blender, sk_sp<SkImageFilter> background, 108 sk_sp<SkImageFilter> foreground = nullptr, 109 const CropRect& cropRect = {}); 110 111 /** 112 * Create a filter that blurs its input by the separate X and Y sigmas. The provided tile mode 113 * is used when the blur kernel goes outside the input image. 114 * @param sigmaX The Gaussian sigma value for blurring along the X axis. 115 * @param sigmaY The Gaussian sigma value for blurring along the Y axis. 116 * @param tileMode The tile mode applied at edges . 117 * TODO (michaelludwig) - kMirror is not supported yet 118 * @param input The input filter that is blurred, uses source bitmap if this is null. 119 * @param cropRect Optional rectangle that crops the input and output. 120 */ 121 static sk_sp<SkImageFilter> Blur(SkScalar sigmaX, SkScalar sigmaY, SkTileMode tileMode, 122 sk_sp<SkImageFilter> input, const CropRect& cropRect = {}); 123 // As above, but defaults to the decal tile mode. 124 static sk_sp<SkImageFilter> Blur(SkScalar sigmaX, SkScalar sigmaY, sk_sp<SkImageFilter> input, 125 const CropRect& cropRect = {}) { 126 return Blur(sigmaX, sigmaY, SkTileMode::kDecal, std::move(input), cropRect); 127 } 128 129 /** 130 * Create a filter that applies the color filter to the input filter results. 131 * @param cf The color filter that transforms the input image. 132 * @param input The input filter, or uses the source bitmap if this is null. 133 * @param cropRect Optional rectangle that crops the input and output. 134 */ 135 static sk_sp<SkImageFilter> ColorFilter(sk_sp<SkColorFilter> cf, sk_sp<SkImageFilter> input, 136 const CropRect& cropRect = {}); 137 138 /** 139 * Create a filter that composes 'inner' with 'outer', such that the results of 'inner' are 140 * treated as the source bitmap passed to 'outer', i.e. result = outer(inner(source)). 141 * @param outer The outer filter that evaluates the results of inner. 142 * @param inner The inner filter that produces the input to outer. 143 */ 144 static sk_sp<SkImageFilter> Compose(sk_sp<SkImageFilter> outer, sk_sp<SkImageFilter> inner); 145 146 /** 147 * Create a filter that moves each pixel in its color input based on an (x,y) vector encoded 148 * in its displacement input filter. Two color components of the displacement image are 149 * mapped into a vector as scale * (color[xChannel], color[yChannel]), where the channel 150 * selectors are one of R, G, B, or A. 151 * @param xChannelSelector RGBA channel that encodes the x displacement per pixel. 152 * @param yChannelSelector RGBA channel that encodes the y displacement per pixel. 153 * @param scale Scale applied to displacement extracted from image. 154 * @param displacement The filter defining the displacement image, or null to use source. 155 * @param color The filter providing the color pixels to be displaced. 156 * @param cropRect Optional rectangle that crops the color input and output. 157 */ 158 static sk_sp<SkImageFilter> DisplacementMap(SkColorChannel xChannelSelector, 159 SkColorChannel yChannelSelector, 160 SkScalar scale, sk_sp<SkImageFilter> displacement, 161 sk_sp<SkImageFilter> color, 162 const CropRect& cropRect = {}); 163 164 /** 165 * Create a filter that draws a drop shadow under the input content. This filter produces an 166 * image that includes the inputs' content. 167 * @param dx The X offset of the shadow. 168 * @param dy The Y offset of the shadow. 169 * @param sigmaX The blur radius for the shadow, along the X axis. 170 * @param sigmaY The blur radius for the shadow, along the Y axis. 171 * @param color The color of the drop shadow. 172 * @param input The input filter, or will use the source bitmap if this is null. 173 * @param cropRect Optional rectangle that crops the input and output. 174 */ 175 static sk_sp<SkImageFilter> DropShadow(SkScalar dx, SkScalar dy, 176 SkScalar sigmaX, SkScalar sigmaY, 177 SkColor color, sk_sp<SkImageFilter> input, 178 const CropRect& cropRect = {}); 179 /** 180 * Create a filter that renders a drop shadow, in exactly the same manner as ::DropShadow, 181 * except that the resulting image does not include the input content. This allows the shadow 182 * and input to be composed by a filter DAG in a more flexible manner. 183 * @param dx The X offset of the shadow. 184 * @param dy The Y offset of the shadow. 185 * @param sigmaX The blur radius for the shadow, along the X axis. 186 * @param sigmaY The blur radius for the shadow, along the Y axis. 187 * @param color The color of the drop shadow. 188 * @param input The input filter, or will use the source bitmap if this is null. 189 * @param cropRect Optional rectangle that crops the input and output. 190 */ 191 static sk_sp<SkImageFilter> DropShadowOnly(SkScalar dx, SkScalar dy, 192 SkScalar sigmaX, SkScalar sigmaY, 193 SkColor color, sk_sp<SkImageFilter> input, 194 const CropRect& cropRect = {}); 195 196 /** 197 * Create a filter that draws the 'srcRect' portion of image into 'dstRect' using the given 198 * filter quality. Similar to SkCanvas::drawImageRect. Returns null if 'image' is null. 199 * @param image The image that is output by the filter, subset by 'srcRect'. 200 * @param srcRect The source pixels sampled into 'dstRect' 201 * @param dstRect The local rectangle to draw the image into. 202 * @param sampling The sampling to use when drawing the image. 203 */ 204 static sk_sp<SkImageFilter> Image(sk_sp<SkImage> image, const SkRect& srcRect, 205 const SkRect& dstRect, const SkSamplingOptions& sampling); 206 207 /** 208 * Create a filter that draws the image using the given sampling. 209 * Similar to SkCanvas::drawImage. Returns null if 'image' is null. 210 * @param image The image that is output by the filter. 211 * @param sampling The sampling to use when drawing the image. 212 */ Image(sk_sp<SkImage> image,const SkSamplingOptions & sampling)213 static sk_sp<SkImageFilter> Image(sk_sp<SkImage> image, const SkSamplingOptions& sampling) { 214 if (image) { 215 SkRect r = SkRect::Make(image->bounds()); 216 return Image(std::move(image), r, r, sampling); 217 } else { 218 return nullptr; 219 } 220 } 221 222 /** 223 * Create a filter that draws the image using Mitchel cubic resampling. 224 * @param image The image that is output by the filter. 225 */ Image(sk_sp<SkImage> image)226 static sk_sp<SkImageFilter> Image(sk_sp<SkImage> image) { 227 return Image(std::move(image), SkSamplingOptions({1/3.0f, 1/3.0f})); 228 } 229 230 /** 231 * Create a filter that mimics a zoom/magnifying lens effect. 232 * @param srcRect 233 * @param inset 234 * @param input The input filter that is magnified, if null the source bitmap is used. 235 * @param cropRect Optional rectangle that crops the input and output. 236 */ 237 static sk_sp<SkImageFilter> Magnifier(const SkRect& srcRect, SkScalar inset, 238 sk_sp<SkImageFilter> input, 239 const CropRect& cropRect = {}); 240 241 /** 242 * Create a filter that applies an NxM image processing kernel to the input image. This can be 243 * used to produce effects such as sharpening, blurring, edge detection, etc. 244 * @param kernelSize The kernel size in pixels, in each dimension (N by M). 245 * @param kernel The image processing kernel. Must contain N * M elements, in row order. 246 * @param gain A scale factor applied to each pixel after convolution. This can be 247 * used to normalize the kernel, if it does not already sum to 1. 248 * @param bias A bias factor added to each pixel after convolution. 249 * @param kernelOffset An offset applied to each pixel coordinate before convolution. 250 * This can be used to center the kernel over the image 251 * (e.g., a 3x3 kernel should have an offset of {1, 1}). 252 * @param tileMode How accesses outside the image are treated. 253 * TODO (michaelludwig) - kMirror is not supported yet 254 * @param convolveAlpha If true, all channels are convolved. If false, only the RGB channels 255 * are convolved, and alpha is copied from the source image. 256 * @param input The input image filter, if null the source bitmap is used instead. 257 * @param cropRect Optional rectangle to which the output processing will be limited. 258 */ 259 static sk_sp<SkImageFilter> MatrixConvolution(const SkISize& kernelSize, 260 const SkScalar kernel[], SkScalar gain, 261 SkScalar bias, const SkIPoint& kernelOffset, 262 SkTileMode tileMode, bool convolveAlpha, 263 sk_sp<SkImageFilter> input, 264 const CropRect& cropRect = {}); 265 266 /** 267 * Create a filter that transforms the input image by 'matrix'. This matrix transforms the 268 * local space, which means it effectively happens prior to any transformation coming from the 269 * SkCanvas initiating the filtering. 270 * @param matrix The matrix to apply to the original content. 271 * @param sampling How the image will be sampled when it is transformed 272 * @param input The image filter to transform, or null to use the source image. 273 */ 274 static sk_sp<SkImageFilter> MatrixTransform(const SkMatrix& matrix, 275 const SkSamplingOptions& sampling, 276 sk_sp<SkImageFilter> input); 277 278 /** 279 * Create a filter that merges the 'count' filters together by drawing their results in order 280 * with src-over blending. 281 * @param filters The input filter array to merge, which must have 'count' elements. Any null 282 * filter pointers will use the source bitmap instead. 283 * @param count The number of input filters to be merged. 284 * @param cropRect Optional rectangle that crops all input filters and the output. 285 */ 286 static sk_sp<SkImageFilter> Merge(sk_sp<SkImageFilter>* const filters, int count, 287 const CropRect& cropRect = {}); 288 /** 289 * Create a filter that merges the results of the two filters together with src-over blending. 290 * @param first The first input filter, or the source bitmap if this is null. 291 * @param second The second input filter, or the source bitmap if this null. 292 * @param cropRect Optional rectangle that crops the inputs and output. 293 */ 294 static sk_sp<SkImageFilter> Merge(sk_sp<SkImageFilter> first, sk_sp<SkImageFilter> second, 295 const CropRect& cropRect = {}) { 296 sk_sp<SkImageFilter> array[] = { std::move(first), std::move(second) }; 297 return Merge(array, 2, cropRect); 298 } 299 300 /** 301 * Create a filter that offsets the input filter by the given vector. 302 * @param dx The x offset in local space that the image is shifted. 303 * @param dy The y offset in local space that the image is shifted. 304 * @param input The input that will be moved, if null the source bitmap is used instead. 305 * @param cropRect Optional rectangle to crop the input and output. 306 */ 307 static sk_sp<SkImageFilter> Offset(SkScalar dx, SkScalar dy, sk_sp<SkImageFilter> input, 308 const CropRect& cropRect = {}); 309 310 /** 311 * Create a filter that fills the output with the given paint. 312 * @param paint The paint to fill 313 * @param cropRect Optional rectangle that will be filled. If null, the source bitmap's bounds 314 * are filled even though the source bitmap itself is not used. 315 * 316 * DEPRECATED: Use Shader() instead, since many features of SkPaint are ignored when filling 317 * the target output, and paint color/alpha can be emulated with SkShaders::Color(). 318 */ 319 static sk_sp<SkImageFilter> Paint(const SkPaint& paint, const CropRect& cropRect = {}); 320 321 /** 322 * Create a filter that produces the SkPicture as its output, drawn into targetRect. Note that 323 * the targetRect is not the same as the SkIRect cropRect that many filters accept. Returns 324 * null if 'pic' is null. 325 * @param pic The picture that is drawn for the filter output. 326 * @param targetRect The drawing region for the picture. 327 */ 328 static sk_sp<SkImageFilter> Picture(sk_sp<SkPicture> pic, const SkRect& targetRect); 329 // As above, but uses SkPicture::cullRect for the drawing region. Picture(sk_sp<SkPicture> pic)330 static sk_sp<SkImageFilter> Picture(sk_sp<SkPicture> pic) { 331 SkRect target = pic ? pic->cullRect() : SkRect::MakeEmpty(); 332 return Picture(std::move(pic), target); 333 } 334 335 enum class Dither : bool { 336 kNo = false, 337 kYes = true 338 }; 339 340 /** 341 * Create a filter that fills the output with the per-pixel evaluation of the SkShader. The 342 * shader is defined in the image filter's local coordinate system, so will automatically 343 * be affected by SkCanvas' transform. 344 * 345 * Like Image() and Picture(), this is a leaf filter that can be used to introduce inputs to 346 * a complex filter graph, but should generally be combined with a filter that as at least 347 * one null input to use the implicit source image. 348 * @param shader The shader that fills the result image 349 */ 350 static sk_sp<SkImageFilter> Shader(sk_sp<SkShader> shader, const CropRect& cropRect = {}) { 351 return Shader(std::move(shader), Dither::kNo, cropRect); 352 } 353 static sk_sp<SkImageFilter> Shader(sk_sp<SkShader> shader, Dither dither, 354 const CropRect& cropRect = {}); 355 356 /** 357 * Create a tile image filter. 358 * @param src Defines the pixels to tile 359 * @param dst Defines the pixel region that the tiles will be drawn to 360 * @param input The input that will be tiled, if null the source bitmap is used instead. 361 */ 362 static sk_sp<SkImageFilter> Tile(const SkRect& src, const SkRect& dst, 363 sk_sp<SkImageFilter> input); 364 365 // Morphology filter effects 366 367 /** 368 * Create a filter that dilates each input pixel's channel values to the max value within the 369 * given radii along the x and y axes. 370 * @param radiusX The distance to dilate along the x axis to either side of each pixel. 371 * @param radiusY The distance to dilate along the y axis to either side of each pixel. 372 * @param input The image filter that is dilated, using source bitmap if this is null. 373 * @param cropRect Optional rectangle that crops the input and output. 374 */ 375 static sk_sp<SkImageFilter> Dilate(SkScalar radiusX, SkScalar radiusY, 376 sk_sp<SkImageFilter> input, 377 const CropRect& cropRect = {}); 378 379 /** 380 * Create a filter that erodes each input pixel's channel values to the minimum channel value 381 * within the given radii along the x and y axes. 382 * @param radiusX The distance to erode along the x axis to either side of each pixel. 383 * @param radiusY The distance to erode along the y axis to either side of each pixel. 384 * @param input The image filter that is eroded, using source bitmap if this is null. 385 * @param cropRect Optional rectangle that crops the input and output. 386 */ 387 static sk_sp<SkImageFilter> Erode(SkScalar radiusX, SkScalar radiusY, 388 sk_sp<SkImageFilter> input, 389 const CropRect& cropRect = {}); 390 391 // Lighting filter effects 392 393 /** 394 * Create a filter that calculates the diffuse illumination from a distant light source, 395 * interpreting the alpha channel of the input as the height profile of the surface (to 396 * approximate normal vectors). 397 * @param direction The direction to the distance light. 398 * @param lightColor The color of the diffuse light source. 399 * @param surfaceScale Scale factor to transform from alpha values to physical height. 400 * @param kd Diffuse reflectance coefficient. 401 * @param input The input filter that defines surface normals (as alpha), or uses the 402 * source bitmap when null. 403 * @param cropRect Optional rectangle that crops the input and output. 404 */ 405 static sk_sp<SkImageFilter> DistantLitDiffuse(const SkPoint3& direction, SkColor lightColor, 406 SkScalar surfaceScale, SkScalar kd, 407 sk_sp<SkImageFilter> input, 408 const CropRect& cropRect = {}); 409 /** 410 * Create a filter that calculates the diffuse illumination from a point light source, using 411 * alpha channel of the input as the height profile of the surface (to approximate normal 412 * vectors). 413 * @param location The location of the point light. 414 * @param lightColor The color of the diffuse light source. 415 * @param surfaceScale Scale factor to transform from alpha values to physical height. 416 * @param kd Diffuse reflectance coefficient. 417 * @param input The input filter that defines surface normals (as alpha), or uses the 418 * source bitmap when null. 419 * @param cropRect Optional rectangle that crops the input and output. 420 */ 421 static sk_sp<SkImageFilter> PointLitDiffuse(const SkPoint3& location, SkColor lightColor, 422 SkScalar surfaceScale, SkScalar kd, 423 sk_sp<SkImageFilter> input, 424 const CropRect& cropRect = {}); 425 /** 426 * Create a filter that calculates the diffuse illumination from a spot light source, using 427 * alpha channel of the input as the height profile of the surface (to approximate normal 428 * vectors). The spot light is restricted to be within 'cutoffAngle' of the vector between 429 * the location and target. 430 * @param location The location of the spot light. 431 * @param target The location that the spot light is point towards 432 * @param falloffExponent Exponential falloff parameter for illumination outside of cutoffAngle 433 * @param cutoffAngle Maximum angle from lighting direction that receives full light 434 * @param lightColor The color of the diffuse light source. 435 * @param surfaceScale Scale factor to transform from alpha values to physical height. 436 * @param kd Diffuse reflectance coefficient. 437 * @param input The input filter that defines surface normals (as alpha), or uses the 438 * source bitmap when null. 439 * @param cropRect Optional rectangle that crops the input and output. 440 */ 441 static sk_sp<SkImageFilter> SpotLitDiffuse(const SkPoint3& location, const SkPoint3& target, 442 SkScalar falloffExponent, SkScalar cutoffAngle, 443 SkColor lightColor, SkScalar surfaceScale, 444 SkScalar kd, sk_sp<SkImageFilter> input, 445 const CropRect& cropRect = {}); 446 447 /** 448 * Create a filter that calculates the specular illumination from a distant light source, 449 * interpreting the alpha channel of the input as the height profile of the surface (to 450 * approximate normal vectors). 451 * @param direction The direction to the distance light. 452 * @param lightColor The color of the specular light source. 453 * @param surfaceScale Scale factor to transform from alpha values to physical height. 454 * @param ks Specular reflectance coefficient. 455 * @param shininess The specular exponent determining how shiny the surface is. 456 * @param input The input filter that defines surface normals (as alpha), or uses the 457 * source bitmap when null. 458 * @param cropRect Optional rectangle that crops the input and output. 459 */ 460 static sk_sp<SkImageFilter> DistantLitSpecular(const SkPoint3& direction, SkColor lightColor, 461 SkScalar surfaceScale, SkScalar ks, 462 SkScalar shininess, sk_sp<SkImageFilter> input, 463 const CropRect& cropRect = {}); 464 /** 465 * Create a filter that calculates the specular illumination from a point light source, using 466 * alpha channel of the input as the height profile of the surface (to approximate normal 467 * vectors). 468 * @param location The location of the point light. 469 * @param lightColor The color of the specular light source. 470 * @param surfaceScale Scale factor to transform from alpha values to physical height. 471 * @param ks Specular reflectance coefficient. 472 * @param shininess The specular exponent determining how shiny the surface is. 473 * @param input The input filter that defines surface normals (as alpha), or uses the 474 * source bitmap when null. 475 * @param cropRect Optional rectangle that crops the input and output. 476 */ 477 static sk_sp<SkImageFilter> PointLitSpecular(const SkPoint3& location, SkColor lightColor, 478 SkScalar surfaceScale, SkScalar ks, 479 SkScalar shininess, sk_sp<SkImageFilter> input, 480 const CropRect& cropRect = {}); 481 /** 482 * Create a filter that calculates the specular illumination from a spot light source, using 483 * alpha channel of the input as the height profile of the surface (to approximate normal 484 * vectors). The spot light is restricted to be within 'cutoffAngle' of the vector between 485 * the location and target. 486 * @param location The location of the spot light. 487 * @param target The location that the spot light is point towards 488 * @param falloffExponent Exponential falloff parameter for illumination outside of cutoffAngle 489 * @param cutoffAngle Maximum angle from lighting direction that receives full light 490 * @param lightColor The color of the specular light source. 491 * @param surfaceScale Scale factor to transform from alpha values to physical height. 492 * @param ks Specular reflectance coefficient. 493 * @param shininess The specular exponent determining how shiny the surface is. 494 * @param input The input filter that defines surface normals (as alpha), or uses the 495 * source bitmap when null. 496 * @param cropRect Optional rectangle that crops the input and output. 497 */ 498 static sk_sp<SkImageFilter> SpotLitSpecular(const SkPoint3& location, const SkPoint3& target, 499 SkScalar falloffExponent, SkScalar cutoffAngle, 500 SkColor lightColor, SkScalar surfaceScale, 501 SkScalar ks, SkScalar shininess, 502 sk_sp<SkImageFilter> input, 503 const CropRect& cropRect = {}); 504 505 private: 506 SkImageFilters() = delete; 507 }; 508 509 #endif // SkImageFilters_DEFINED 510