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 }