1 module skia.SKImageFilter; 2 3 // TODO: `asAColorFilter` 4 // TODO: `countInputs`, `getInput` 5 // TODO: `cropRectIsSet`, `getCropRect` 6 // TODO: `computeFastBounds`, `canComputeFastBounds` 7 8 import skia.SKObject; 9 import skia.SKMatrix; 10 import skia.SkiaApi; 11 import skia.SKRegion; 12 import skia.SKColorFilter; 13 import skia.SKColor; 14 import skia.SKPicture; 15 import skia.SKImage; 16 import skia.SKPaint; 17 import skia.MathTypes; 18 import skia.Definitions; 19 import skia.Exceptions; 20 21 enum SKDisplacementMapEffectChannelSelectorType 22 { 23 Unknown = 0, 24 R = 1, 25 G = 2, 26 B = 3, 27 A = 4, 28 } 29 30 enum SKDropShadowImageFilterShadowMode 31 { 32 DrawShadowAndForeground = 0, 33 DrawShadowOnly = 1, 34 } 35 36 enum SKMatrixConvolutionTileMode 37 { 38 Clamp = 0, 39 Repeat = 1, 40 ClampToBlack = 2, 41 42 } 43 44 alias ToColorChannel = SkiaExtensions.ToColorChannel; 45 alias ToShaderTileMode = SkiaExtensions.ToShaderTileMode; 46 47 struct SkiaExtensions 48 { 49 50 // static SKColorChannel ToColorChannel (this SKDisplacementMapEffectChannelSelectorType channelSelectorType) 51 static SKColorChannel ToColorChannel (SKDisplacementMapEffectChannelSelectorType channelSelectorType) 52 { 53 switch(channelSelectorType) 54 { 55 case SKDisplacementMapEffectChannelSelectorType.R: 56 return SKColorChannel.R; 57 case SKDisplacementMapEffectChannelSelectorType.G: 58 return SKColorChannel.G; 59 case SKDisplacementMapEffectChannelSelectorType.B: 60 return SKColorChannel.B; 61 case SKDisplacementMapEffectChannelSelectorType.A: 62 return SKColorChannel.A; 63 default: 64 return SKColorChannel.B; 65 } 66 } 67 68 69 // static SKShaderTileMode ToShaderTileMode (this SKMatrixConvolutionTileMode tileMode) 70 static SKShaderTileMode ToShaderTileMode (SKMatrixConvolutionTileMode tileMode) 71 { 72 switch(tileMode) 73 { 74 case SKMatrixConvolutionTileMode.Clamp: 75 return SKShaderTileMode.Clamp; 76 case SKMatrixConvolutionTileMode.Repeat: 77 return SKShaderTileMode.Repeat; 78 default: 79 return SKShaderTileMode.Decal; 80 } 81 } 82 } 83 84 class SKImageFilter : SKObject 85 { 86 this(void* handle, bool owns) 87 { 88 super(handle, owns); 89 } 90 91 protected override void Dispose (bool disposing) 92 { 93 return super.Dispose (disposing); 94 } 95 96 97 // CreateMatrix 98 99 static SKImageFilter CreateMatrix(SKMatrix matrix, SKFilterQuality quality, SKImageFilter input = null) 100 { 101 return GetObject(SkiaApi.sk_imagefilter_new_matrix(&matrix, quality, cast(sk_imagefilter_t*)(input is null ? null : input.Handle))); 102 } 103 104 // CreateAlphaThreshold 105 106 static SKImageFilter CreateAlphaThreshold(SKRectI region, float innerThreshold, float outerThreshold, SKImageFilter input = null) 107 { 108 auto reg = new SKRegion (); 109 reg.SetRect (region); 110 return CreateAlphaThreshold (reg, innerThreshold, outerThreshold, input); 111 112 } 113 114 static SKImageFilter CreateAlphaThreshold(SKRegion region, float innerThreshold, float outerThreshold, SKImageFilter input = null) 115 { 116 if (region is null) 117 throw new ArgumentNullException (region.stringof); 118 return GetObject(SkiaApi.sk_imagefilter_new_alpha_threshold(cast(sk_region_t*)region.Handle, innerThreshold, outerThreshold, cast(sk_imagefilter_t*)(input is null ? null : input.Handle))); 119 } 120 121 // CreateBlur 122 123 static SKImageFilter CreateBlur (float sigmaX, float sigmaY, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null) 124 { 125 return CreateBlur (sigmaX, sigmaY, SKShaderTileMode.Decal, input, cropRect); 126 } 127 128 129 static SKImageFilter CreateBlur (float sigmaX, float sigmaY, SKShaderTileMode tileMode, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null) 130 { 131 return GetObject (SkiaApi.sk_imagefilter_new_blur (sigmaX, sigmaY, tileMode, cast(sk_imagefilter_t*)(input is null ? null : input.Handle), cast(sk_imagefilter_croprect_t*)(cropRect is null ? null : cropRect.Handle))); 132 } 133 134 135 // CreateColorFilter 136 137 static SKImageFilter CreateColorFilter(SKColorFilter cf, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null) 138 { 139 if (cf is null) 140 throw new ArgumentNullException(cf.stringof); 141 return GetObject(SkiaApi.sk_imagefilter_new_color_filter(cast(sk_colorfilter_t*)cf.Handle, cast(sk_imagefilter_t*)(input is null ? null : input.Handle), cast(sk_imagefilter_croprect_t*)(cropRect is null ? null : cropRect.Handle))); 142 } 143 144 // CreateCompose 145 146 static SKImageFilter CreateCompose(SKImageFilter outer, SKImageFilter inner) 147 { 148 if (outer is null) 149 throw new ArgumentNullException(outer.stringof); 150 if (inner is null) 151 throw new ArgumentNullException(inner.stringof); 152 return GetObject(SkiaApi.sk_imagefilter_new_compose(cast(sk_imagefilter_t*)outer.Handle, cast(sk_imagefilter_t*)inner.Handle)); 153 } 154 155 // CreateDisplacementMapEffect 156 157 static SKImageFilter CreateDisplacementMapEffect (SKDisplacementMapEffectChannelSelectorType xChannelSelector, SKDisplacementMapEffectChannelSelectorType yChannelSelector, float scale, SKImageFilter displacement, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null) 158 { 159 return CreateDisplacementMapEffect (xChannelSelector.ToColorChannel (), yChannelSelector.ToColorChannel (), scale, displacement, input, cropRect); 160 } 161 162 163 static SKImageFilter CreateDisplacementMapEffect (SKColorChannel xChannelSelector, SKColorChannel yChannelSelector, float scale, SKImageFilter displacement, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null) 164 { 165 if (displacement is null) 166 throw new ArgumentNullException (displacement.stringof); 167 return GetObject (SkiaApi.sk_imagefilter_new_displacement_map_effect (xChannelSelector, yChannelSelector, scale, cast(sk_imagefilter_t*)displacement.Handle, cast(sk_imagefilter_t*)(input is null ? null : input.Handle), cast(sk_imagefilter_croprect_t*)(cropRect is null ? null : cropRect.Handle))); 168 } 169 170 // CreateDropShadow 171 172 static SKImageFilter CreateDropShadow (float dx, float dy, float sigmaX, float sigmaY, SKColor color, SKDropShadowImageFilterShadowMode shadowMode, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null) 173 { 174 return shadowMode == SKDropShadowImageFilterShadowMode.DrawShadowOnly 175 ? CreateDropShadowOnly (dx, dy, sigmaX, sigmaY, color, input, cropRect) 176 : CreateDropShadow (dx, dy, sigmaX, sigmaY, color, input, cropRect); 177 } 178 179 180 static SKImageFilter CreateDropShadow (float dx, float dy, float sigmaX, float sigmaY, SKColor color, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null) 181 { 182 return GetObject (SkiaApi.sk_imagefilter_new_drop_shadow (dx, dy, sigmaX, sigmaY, cast(uint)color, cast(sk_imagefilter_t*)(input is null ? null : input.Handle), cast(sk_imagefilter_croprect_t*)(cropRect is null ? null : cropRect.Handle))); 183 } 184 185 186 static SKImageFilter CreateDropShadowOnly (float dx, float dy, float sigmaX, float sigmaY, SKColor color, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null) 187 { 188 return GetObject (SkiaApi.sk_imagefilter_new_drop_shadow_only (dx, dy, sigmaX, sigmaY, cast(uint)color, cast(sk_imagefilter_t*)(input is null ? null : input.Handle), cast(sk_imagefilter_croprect_t*)(cropRect is null ? null : cropRect.Handle))); 189 } 190 191 192 // Create*LitDiffuse 193 194 static SKImageFilter CreateDistantLitDiffuse(SKPoint3 direction, SKColor lightColor, float surfaceScale, float kd, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null) 195 { 196 return GetObject(SkiaApi.sk_imagefilter_new_distant_lit_diffuse(&direction, cast(uint)lightColor, surfaceScale, kd, cast(sk_imagefilter_t*)(input is null ? null : input.Handle), cast(sk_imagefilter_croprect_t*)(cropRect is null ? null : cropRect.Handle))); 197 } 198 199 static SKImageFilter CreatePointLitDiffuse(SKPoint3 location, SKColor lightColor, float surfaceScale, float kd, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null) 200 { 201 return GetObject(SkiaApi.sk_imagefilter_new_point_lit_diffuse(&location, cast(uint)lightColor, surfaceScale, kd, cast(sk_imagefilter_t*)(input is null ? null : input.Handle), cast(sk_imagefilter_croprect_t*)(cropRect is null ? null : cropRect.Handle))); 202 } 203 204 static SKImageFilter CreateSpotLitDiffuse(SKPoint3 location, SKPoint3 target, float specularExponent, float cutoffAngle, SKColor lightColor, float surfaceScale, float kd, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null) 205 { 206 return GetObject(SkiaApi.sk_imagefilter_new_spot_lit_diffuse(&location, &target, specularExponent, cutoffAngle, cast(uint)lightColor, surfaceScale, kd, cast(sk_imagefilter_t*)(input is null ? null : input.Handle), cast(sk_imagefilter_croprect_t*)(cropRect is null ? null : cropRect.Handle))); 207 } 208 209 // Create*LitSpecular 210 211 static SKImageFilter CreateDistantLitSpecular(SKPoint3 direction, SKColor lightColor, float surfaceScale, float ks, float shininess, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null) 212 { 213 return GetObject(SkiaApi.sk_imagefilter_new_distant_lit_specular(&direction, cast(uint)lightColor, surfaceScale, ks, shininess, cast(sk_imagefilter_t*)(input is null ? null : input.Handle), cast(sk_imagefilter_croprect_t*)(cropRect is null ? null : cropRect.Handle))); 214 } 215 216 static SKImageFilter CreatePointLitSpecular(SKPoint3 location, SKColor lightColor, float surfaceScale, float ks, float shininess, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null) 217 { 218 return GetObject(SkiaApi.sk_imagefilter_new_point_lit_specular(&location, cast(uint)lightColor, surfaceScale, ks, shininess, cast(sk_imagefilter_t*)(input is null ? null : input.Handle), cast(sk_imagefilter_croprect_t*)(cropRect is null ? null : cropRect.Handle))); 219 } 220 221 static SKImageFilter CreateSpotLitSpecular(SKPoint3 location, SKPoint3 target, float specularExponent, float cutoffAngle, SKColor lightColor, float surfaceScale, float ks, float shininess, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null) 222 { 223 return GetObject(SkiaApi.sk_imagefilter_new_spot_lit_specular(&location, &target, specularExponent, cutoffAngle, cast(uint)lightColor, surfaceScale, ks, shininess, cast(sk_imagefilter_t*)(input is null ? null : input.Handle), cast(sk_imagefilter_croprect_t*)(cropRect is null ? null : cropRect.Handle))); 224 } 225 226 // CreateMagnifier 227 228 static SKImageFilter CreateMagnifier(SKRect src, float inset, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null) 229 { 230 return GetObject(SkiaApi.sk_imagefilter_new_magnifier(&src, inset, cast(sk_imagefilter_t*)(input is null ? null : input.Handle), cast(sk_imagefilter_croprect_t*)(cropRect is null ? null : cropRect.Handle))); 231 } 232 233 // CreateMatrixConvolution 234 // [Obsolete ("Use CreateMatrixConvolution(SKSizeI, float[], float, float, SKPointI, SKShaderTileMode, bool, SKImageFilter, SKImageFilter.CropRect) instead.")] 235 static SKImageFilter CreateMatrixConvolution (SKSizeI kernelSize, float[] kernel, float gain, float bias, SKPointI kernelOffset, SKMatrixConvolutionTileMode tileMode, bool convolveAlpha, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null) 236 { 237 return CreateMatrixConvolution (kernelSize, kernel, gain, bias, kernelOffset, tileMode.ToShaderTileMode (), convolveAlpha, input, cropRect); 238 } 239 240 241 static SKImageFilter CreateMatrixConvolution (SKSizeI kernelSize, float[] kernel, float gain, float bias, SKPointI kernelOffset, SKShaderTileMode tileMode, bool convolveAlpha, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null) 242 { 243 if (kernel is null) 244 throw new ArgumentNullException (kernel.stringof); 245 if (kernel.length != kernelSize.Width * kernelSize.Height) 246 throw new ArgumentException ("Kernel length must match the dimensions of the kernel size (Width * Height).", kernel.stringof); 247 float* k = kernel.ptr; 248 return GetObject (SkiaApi.sk_imagefilter_new_matrix_convolution (&kernelSize, k, gain, bias, &kernelOffset, tileMode, convolveAlpha, cast(sk_imagefilter_t*)(input is null ? null : input.Handle), cast(sk_imagefilter_croprect_t*)(cropRect is null ? null : cropRect.Handle))); 249 } 250 251 // CreateMerge 252 253 // static SKImageFilter CreateMerge(SKImageFilter first, SKImageFilter second, SKBlendMode mode, SKImageFilter.CropRect cropRect = null) 254 // { 255 // return CreateMerge(new [] { first, second }, cropRect); 256 // } 257 258 // static SKImageFilter CreateMerge(SKImageFilter first, SKImageFilter second, SKImageFilter.CropRect cropRect = null) 259 // { 260 // return CreateMerge(new [] { first, second }, cropRect); 261 // } 262 // [Obsolete("Use CreateMerge(SKImageFilter[], SKImageFilter.CropRect) instead.")] 263 static SKImageFilter CreateMerge(SKImageFilter[] filters, SKBlendMode[] modes, SKImageFilter.CropRect cropRect = null) 264 { 265 return CreateMerge (filters, cropRect); 266 } 267 268 static SKImageFilter CreateMerge(SKImageFilter[] filters, SKImageFilter.CropRect cropRect = null) 269 { 270 if (filters is null) 271 throw new ArgumentNullException(filters.stringof); 272 auto handles = new void*[filters.length]; 273 for (int i = 0; i < filters.length; i++) 274 { 275 handles[i] = filters[i].Handle ? filters[i].Handle : null; 276 } 277 void** h = handles.ptr; 278 return GetObject (SkiaApi.sk_imagefilter_new_merge (cast(sk_imagefilter_t**)h, cast(int)filters.length, cast(sk_imagefilter_croprect_t*)(cropRect is null ? null : cropRect.Handle))); 279 } 280 281 // CreateDilate 282 283 static SKImageFilter CreateDilate(int radiusX, int radiusY, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null) 284 { 285 return GetObject(SkiaApi.sk_imagefilter_new_dilate(radiusX, radiusY, cast(sk_imagefilter_t*)(input is null ? null : input.Handle), cast(sk_imagefilter_croprect_t*)(cropRect is null ? null : cropRect.Handle))); 286 } 287 288 // CreateErode 289 290 static SKImageFilter CreateErode(int radiusX, int radiusY, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null) 291 { 292 return GetObject(SkiaApi.sk_imagefilter_new_erode(radiusX, radiusY, cast(sk_imagefilter_t*)(input is null ? null : input.Handle), cast(sk_imagefilter_croprect_t*)(cropRect is null ? null : cropRect.Handle))); 293 } 294 295 // CreateOffset 296 297 static SKImageFilter CreateOffset(float dx, float dy, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null) 298 { 299 return GetObject(SkiaApi.sk_imagefilter_new_offset(dx, dy, cast(sk_imagefilter_t*)(input is null ? null : input.Handle), cast(sk_imagefilter_croprect_t*)(cropRect is null ? null : cropRect.Handle))); 300 } 301 302 // CreatePicture 303 304 static SKImageFilter CreatePicture(SKPicture picture) 305 { 306 if (picture is null) 307 throw new ArgumentNullException(picture.stringof); 308 return GetObject(SkiaApi.sk_imagefilter_new_picture(cast(sk_picture_t*)picture.Handle)); 309 } 310 311 static SKImageFilter CreatePicture(SKPicture picture, SKRect cropRect) 312 { 313 if (picture is null) 314 throw new ArgumentNullException(picture.stringof); 315 return GetObject(SkiaApi.sk_imagefilter_new_picture_with_croprect(cast(sk_picture_t*)picture.Handle, &cropRect)); 316 } 317 318 // CreateTile 319 320 static SKImageFilter CreateTile(SKRect src, SKRect dst, SKImageFilter input) 321 { 322 if (input is null) 323 throw new ArgumentNullException(input.stringof); 324 return GetObject(SkiaApi.sk_imagefilter_new_tile(&src, &dst, cast(sk_imagefilter_t*)input.Handle)); 325 } 326 327 // CreateBlendMode 328 329 static SKImageFilter CreateBlendMode(SKBlendMode mode, SKImageFilter background, SKImageFilter foreground = null, SKImageFilter.CropRect cropRect = null) 330 { 331 if (background is null) 332 throw new ArgumentNullException(background.stringof); 333 return GetObject(SkiaApi.sk_imagefilter_new_xfermode(mode, cast(sk_imagefilter_t*)background.Handle, cast(sk_imagefilter_t*)(foreground is null ? null : foreground.Handle), cast(sk_imagefilter_croprect_t*)(cropRect is null ? null : cropRect.Handle))); 334 } 335 336 // CreateArithmetic 337 338 static SKImageFilter CreateArithmetic(float k1, float k2, float k3, float k4, bool enforcePMColor, SKImageFilter background, SKImageFilter foreground = null, SKImageFilter.CropRect cropRect = null) 339 { 340 if (background is null) 341 throw new ArgumentNullException(background.stringof); 342 return GetObject(SkiaApi.sk_imagefilter_new_arithmetic(k1, k2, k3, k4, enforcePMColor, cast(sk_imagefilter_t*)background.Handle, cast(sk_imagefilter_t*)(foreground is null ? null : foreground.Handle), cast(sk_imagefilter_croprect_t*)(cropRect is null ? null : cropRect.Handle))); 343 } 344 345 // CreateImage 346 347 static SKImageFilter CreateImage(SKImage image) 348 { 349 if (image is null) 350 throw new ArgumentNullException(image.stringof); 351 return GetObject(SkiaApi.sk_imagefilter_new_image_source_default(cast(sk_image_t*)image.Handle)); 352 } 353 354 static SKImageFilter CreateImage(SKImage image, SKRect src, SKRect dst, SKFilterQuality filterQuality) 355 { 356 if (image is null) 357 throw new ArgumentNullException(image.stringof); 358 return GetObject(SkiaApi.sk_imagefilter_new_image_source(cast(sk_image_t*)image.Handle, &src, &dst, filterQuality)); 359 } 360 361 // CreatePaint 362 363 static SKImageFilter CreatePaint(SKPaint paint, SKImageFilter.CropRect cropRect = null) 364 { 365 if (paint is null) 366 throw new ArgumentNullException(paint.stringof); 367 return GetObject(SkiaApi.sk_imagefilter_new_paint(cast(sk_paint_t*)paint.Handle, cast(sk_imagefilter_croprect_t*)(cropRect is null ? null : cropRect.Handle))); 368 } 369 370 static SKImageFilter GetObject (void* handle) 371 { 372 return GetOrAddObject!(SKImageFilter)(handle, delegate SKImageFilter (h, o) { return new SKImageFilter (h, o);}); 373 // return GetOrAddObject (handle, (h, o){return new SKImageFilter (h, o);}); 374 } 375 376 377 // 378 379 class CropRect : SKObject 380 { 381 this(void* handle, bool owns) 382 { 383 super(handle, owns); 384 } 385 386 this() 387 { 388 this(SkiaApi.sk_imagefilter_croprect_new(), true); 389 } 390 391 this(SKRect rect, SKCropRectFlags flags = SKCropRectFlags.HasAll) 392 { 393 this(SkiaApi.sk_imagefilter_croprect_new_with_rect(&rect, cast(uint)flags), true); 394 } 395 396 protected override void Dispose (bool disposing) 397 { 398 return super.Dispose (disposing); 399 } 400 401 402 protected override void DisposeNative () 403 { 404 return SkiaApi.sk_imagefilter_croprect_destructor (cast(sk_imagefilter_croprect_t*)Handle); 405 } 406 407 408 SKRect Rect() 409 { 410 SKRect rect; 411 SkiaApi.sk_imagefilter_croprect_get_rect (cast(sk_imagefilter_croprect_t*)Handle, &rect); 412 return rect; 413 } 414 415 SKCropRectFlags Flags() 416 { 417 return cast(SKCropRectFlags)SkiaApi.sk_imagefilter_croprect_get_flags (cast(sk_imagefilter_croprect_t*)Handle); 418 } 419 420 } 421 }