1 module skia.SKSurface;
2 
3 import skia.Definitions;
4 import skia.MathTypes;
5 import skia.SKImageInfo;
6 import skia.SKPixmap;
7 import skia.GRContext;
8 import skia.GRDefinitions;
9 import skia.DelegateProxies;
10 import skia.GRBackendRenderTarget;
11 import skia.SkiaApi;
12 import skia.GRBackendTexture;
13 import skia.SKColorSpace;
14 import skia.SKSurfaceProperties;
15 import skia.SKImage;
16 import skia.SKCanvas;
17 import skia.SKPaint;
18 import skia.SKVertices;
19 import skia.SKObject;
20 import skia.Exceptions;
21 import skia.EnumMappings;
22 
23 import std.experimental.logger;
24 
25 class SKSurface : SKObject, ISKSkipObjectRegistration {
26 
27 	static SKSurface Create(int width, int height, SKColorType colorType, SKAlphaType alphaType) {
28 		return Create(SKImageInfo(width, height, colorType, alphaType));
29 	}
30 
31 	static SKSurface Create(int width, int height, SKColorType colorType,
32 			SKAlphaType alphaType, SKSurfaceProps props) {
33 		return Create(SKImageInfo(width, height, colorType, alphaType), props);
34 	}
35 
36 	static SKSurface Create(int width, int height, SKColorType colorType,
37 			SKAlphaType alphaType, void* pixels, int rowBytes) {
38 		return Create(SKImageInfo(width, height, colorType, alphaType), pixels, rowBytes);
39 	}
40 
41 	static SKSurface Create(int width, int height, SKColorType colorType,
42 			SKAlphaType alphaType, void* pixels, int rowBytes, SKSurfaceProps props) {
43 		return Create(SKImageInfo(width, height, colorType, alphaType), pixels, rowBytes, props);
44 	}
45 
46 	this(void* h, bool owns) {
47 		super(h, owns);
48 	}
49 
50 	// 	protected override void Dispose (bool disposing)
51 	//   {
52 	//     return super.Dispose (disposing);
53 	//   }
54 
55 	// RASTER surface
56 
57 	static SKSurface Create(SKImageInfo info, SKSurfaceProps props) {
58 		return Create(info, 0, new SKSurfaceProperties(props));
59 	}
60 
61 	static SKSurface Create(SKImageInfo info) {
62 		return Create(info, 0, null);
63 	}
64 
65 	static SKSurface Create(SKImageInfo info, int rowBytes) {
66 		return Create(info, rowBytes, null);
67 	}
68 
69 	static SKSurface Create(SKImageInfo info, SKSurfaceProperties props) {
70 		return Create(info, 0, props);
71 	}
72 
73 	static SKSurface Create(SKImageInfo info, int rowBytes, SKSurfaceProperties props) {
74 		auto cinfo = SKImageInfo.FromManaged(info);
75 		void* handle = null;
76 		if(props !is null && props.Handle !is null) {
77 			handle = props.Handle;
78 		}
79 		return GetObject(SkiaApi.sk_surface_new_raster(&cinfo, cast(void*) rowBytes,
80 				cast(sk_surfaceprops_t*)handle));
81 	}
82 
83 	// convenience RASTER DIRECT to use a SKPixmap instead of SKImageInfo and void*
84 
85 	static SKSurface Create(SKPixmap pixmap, SKSurfaceProps props) {
86 		return Create(pixmap, new SKSurfaceProperties(props));
87 	}
88 
89 	static SKSurface Create(SKPixmap pixmap) {
90 		return Create(pixmap, null);
91 	}
92 
93 	static SKSurface Create(SKPixmap pixmap, SKSurfaceProperties props) {
94 		if (pixmap is null) {
95 			throw new ArgumentNullException(pixmap.stringof);
96 		}
97 		return Create(pixmap.Info, pixmap.GetPixels(), pixmap.RowBytes, props);
98 	}
99 
100 	// RASTER DIRECT surface
101 
102 	static SKSurface Create(SKImageInfo info, void* pixels, int rowBytes, SKSurfaceProps props) {
103 		return Create(info, pixels, rowBytes, new SKSurfaceProperties(props));
104 	}
105 
106 	static SKSurface Create(SKImageInfo info, void* pixels) {
107 		return Create(info, pixels, info.RowBytes);
108 	}
109 
110 	static SKSurface Create(SKImageInfo info, void* pixels, int rowBytes) {
111 		return Create(info, pixels, rowBytes);
112 	}
113 
114 	// static SKSurface Create (SKImageInfo info, void* pixels, int rowBytes, SKSurfaceReleaseDelegate releaseProc, object context)	
115 	// {
116 	// 	return Create (info, pixels, rowBytes, releaseProc, context, null);
117 	// }
118 
119 	static SKSurface Create(SKImageInfo info, void* pixels, SKSurfaceProperties props) {
120 		return Create(info, pixels, info.RowBytes, props);
121 	}
122 
123 	static SKSurface Create(SKImageInfo info, void* pixels, int rowBytes,
124 			SKSurfaceProperties props) {
125 		return Create(info, pixels, rowBytes, props);
126 	}
127 
128 	// static SKSurface Create (SKImageInfo info, void* pixels, int rowBytes, SKSurfaceReleaseDelegate releaseProc, object context, SKSurfaceProperties props)
129 	// {
130 	// 	auto cinfo = SKImageInfo.FromManaged (ref info);
131 	// 	auto del = releaseProc !is null && context !is null
132 	// 		? new SKSurfaceReleaseDelegate ((addr, _) {return releaseProc (addr, context);})
133 	// 		: releaseProc;
134 	// 	auto proxy = DelegateProxies.Create (del, DelegateProxies.SKSurfaceReleaseDelegateProxy,  _, out var ctx);
135 	// 	return GetObject (SkiaApi.sk_surface_new_raster_direct (&cinfo, cast(void*)pixels, cast(void*)rowBytes, proxy, cast(void*)ctx, props.Handle ? props.Handle : null));
136 	// }
137 
138 	// GPU BACKEND RENDER TARGET surface
139 
140 	static SKSurface Create(GRContext context, GRBackendRenderTargetDesc desc) {
141 		if (context is null)
142 			throw new ArgumentNullException(context.stringof);
143 
144 		auto renderTarget = new GRBackendRenderTarget(context.Backend, desc);
145 		return Create(context, renderTarget, desc.Origin, desc.Config.ToColorType(), null, null);
146 	}
147 
148 	static SKSurface Create(GRContext context, GRBackendRenderTargetDesc desc, SKSurfaceProps props) {
149 		if (context is null)
150 			throw new ArgumentNullException(context.stringof);
151 
152 		auto renderTarget = new GRBackendRenderTarget(context.Backend, desc);
153 		return Create(context, renderTarget, desc.Origin,
154 				desc.Config.ToColorType(), null, new SKSurfaceProperties(props));
155 	}
156 
157 	static SKSurface Create(GRContext context,
158 			GRBackendRenderTarget renderTarget, SKColorType colorType) {
159 		return Create(context, renderTarget, GRSurfaceOrigin.BottomLeft, colorType, null, null);
160 	}
161 
162 	static SKSurface Create(GRContext context, GRBackendRenderTarget renderTarget,
163 			GRSurfaceOrigin origin, SKColorType colorType) {
164 		return Create(context, renderTarget, origin, colorType, null, null);
165 	}
166 
167 	static SKSurface Create(GRContext context, GRBackendRenderTarget renderTarget,
168 			GRSurfaceOrigin origin, SKColorType colorType, SKColorSpace colorspace) {
169 		return Create(context, renderTarget, origin, colorType, colorspace, null);
170 	}
171 
172 	static SKSurface Create(GRContext context, GRBackendRenderTarget renderTarget,
173 			SKColorType colorType, SKSurfaceProperties props) {
174 		return Create(context, renderTarget, GRSurfaceOrigin.BottomLeft, colorType, null, props);
175 	}
176 
177 	static SKSurface Create(GRContext context, GRBackendRenderTarget renderTarget,
178 			GRSurfaceOrigin origin, SKColorType colorType, SKSurfaceProperties props) {
179 		return Create(context, renderTarget, origin, colorType, null, props);
180 	}
181 
182 	static SKSurface Create(GRContext context, GRBackendRenderTarget renderTarget,
183 			GRSurfaceOrigin origin, SKColorType colorType,
184 			SKColorSpace colorspace, SKSurfaceProperties props) {
185 		if (context is null)
186 			throw new ArgumentNullException(context.stringof);
187 		if (renderTarget is null)
188 			throw new ArgumentNullException(renderTarget.stringof);
189 
190 		return GetObject(SkiaApi.sk_surface_new_backend_render_target(cast(gr_context_t*) context.Handle,
191 				cast(gr_backendrendertarget_t*) renderTarget.Handle, origin, ToNative(colorType),
192 				cast(sk_colorspace_t*)(colorspace.Handle ? colorspace.Handle : null),
193 				cast(sk_surfaceprops_t*)(props.Handle ? props.Handle : null)));
194 	}
195 
196 	// GPU BACKEND TEXTURE surface
197 
198 	static SKSurface Create(GRContext context, GRGlBackendTextureDesc desc) {
199 		return Create(context, new GRBackendTexture(desc), desc.Origin,
200 				desc.SampleCount, desc.Config.ToColorType(), null, null);
201 	}
202 
203 	static SKSurface Create(GRContext context, GRBackendTextureDesc desc) {
204 		return Create(context, new GRBackendTexture(desc), desc.Origin,
205 				desc.SampleCount, desc.Config.ToColorType(), null, null);
206 	}
207 
208 	static SKSurface Create(GRContext context, GRGlBackendTextureDesc desc, SKSurfaceProps props) {
209 		return Create(context, new GRBackendTexture(desc), desc.Origin, desc.SampleCount,
210 				desc.Config.ToColorType(), null, new SKSurfaceProperties(props));
211 	}
212 
213 	static SKSurface Create(GRContext context, GRBackendTextureDesc desc, SKSurfaceProps props) {
214 		return Create(context, new GRBackendTexture(desc), desc.Origin, desc.SampleCount,
215 				desc.Config.ToColorType(), null, new SKSurfaceProperties(props));
216 	}
217 
218 	static SKSurface Create(GRContext context, GRBackendTexture texture, SKColorType colorType) {
219 		return Create(context, texture, GRSurfaceOrigin.BottomLeft, 0, colorType, null, null);
220 	}
221 
222 	static SKSurface Create(GRContext context, GRBackendTexture texture,
223 			GRSurfaceOrigin origin, SKColorType colorType) {
224 		return Create(context, texture, origin, 0, colorType, null, null);
225 	}
226 
227 	static SKSurface Create(GRContext context, GRBackendTexture texture,
228 			GRSurfaceOrigin origin, int sampleCount, SKColorType colorType) {
229 		return Create(context, texture, origin, sampleCount, colorType, null, null);
230 	}
231 
232 	static SKSurface Create(GRContext context, GRBackendTexture texture,
233 			GRSurfaceOrigin origin, int sampleCount, SKColorType colorType, SKColorSpace colorspace) {
234 		return Create(context, texture, origin, sampleCount, colorType, colorspace, null);
235 	}
236 
237 	static SKSurface Create(GRContext context, GRBackendTexture texture,
238 			SKColorType colorType, SKSurfaceProperties props) {
239 		return Create(context, texture, GRSurfaceOrigin.BottomLeft, 0, colorType, null, props);
240 	}
241 
242 	static SKSurface Create(GRContext context, GRBackendTexture texture,
243 			GRSurfaceOrigin origin, SKColorType colorType, SKSurfaceProperties props) {
244 		return Create(context, texture, origin, 0, colorType, null, props);
245 	}
246 
247 	static SKSurface Create(GRContext context, GRBackendTexture texture,
248 			GRSurfaceOrigin origin, int sampleCount, SKColorType colorType,
249 			SKSurfaceProperties props) {
250 		return Create(context, texture, origin, sampleCount, colorType, null, props);
251 	}
252 
253 	static SKSurface Create(GRContext context, GRBackendTexture texture, GRSurfaceOrigin origin,
254 			int sampleCount, SKColorType colorType, SKColorSpace colorspace,
255 			SKSurfaceProperties props) {
256 		if (context is null)
257 			throw new ArgumentNullException(context.stringof);
258 		if (texture is null)
259 			throw new ArgumentNullException(texture.stringof);
260 
261 		return GetObject(SkiaApi.sk_surface_new_backend_texture(cast(gr_context_t*) context.Handle,
262 				cast(gr_backendtexture_t*) texture.Handle, origin, sampleCount, ToNative(colorType),
263 				cast(sk_colorspace_t*)(colorspace.Handle ? colorspace.Handle : null),
264 				cast(sk_surfaceprops_t*)(props.Handle ? props.Handle : null)));
265 	}
266 
267 	// GPU BACKEND TEXTURE AS RENDER TARGET surface
268 
269 	static SKSurface CreateAsRenderTarget(GRContext context, GRGlBackendTextureDesc desc) {
270 		return CreateAsRenderTarget(context, new GRBackendTexture(desc),
271 				desc.Origin, desc.SampleCount, desc.Config.ToColorType(), null, null);
272 	}
273 
274 	static SKSurface CreateAsRenderTarget(GRContext context, GRBackendTextureDesc desc) {
275 		return CreateAsRenderTarget(context, new GRBackendTexture(desc),
276 				desc.Origin, desc.SampleCount, desc.Config.ToColorType(), null, null);
277 	}
278 
279 	static SKSurface CreateAsRenderTarget(GRContext context,
280 			GRGlBackendTextureDesc desc, SKSurfaceProps props) {
281 		return CreateAsRenderTarget(context, new GRBackendTexture(desc), desc.Origin,
282 				desc.SampleCount, desc.Config.ToColorType(), null, new SKSurfaceProperties(props));
283 	}
284 
285 	static SKSurface CreateAsRenderTarget(GRContext context,
286 			GRBackendTextureDesc desc, SKSurfaceProps props) {
287 		return CreateAsRenderTarget(context, new GRBackendTexture(desc), desc.Origin,
288 				desc.SampleCount, desc.Config.ToColorType(), null, new SKSurfaceProperties(props));
289 	}
290 
291 	static SKSurface CreateAsRenderTarget(GRContext context,
292 			GRBackendTexture texture, SKColorType colorType) {
293 		return CreateAsRenderTarget(context, texture,
294 				GRSurfaceOrigin.BottomLeft, 0, colorType, null, null);
295 	}
296 
297 	static SKSurface CreateAsRenderTarget(GRContext context,
298 			GRBackendTexture texture, GRSurfaceOrigin origin, SKColorType colorType) {
299 		return CreateAsRenderTarget(context, texture, origin, 0, colorType, null, null);
300 	}
301 
302 	static SKSurface CreateAsRenderTarget(GRContext context, GRBackendTexture texture,
303 			GRSurfaceOrigin origin, int sampleCount, SKColorType colorType) {
304 		return CreateAsRenderTarget(context, texture, origin, sampleCount, colorType, null, null);
305 	}
306 
307 	static SKSurface CreateAsRenderTarget(GRContext context, GRBackendTexture texture,
308 			GRSurfaceOrigin origin, int sampleCount, SKColorType colorType, SKColorSpace colorspace) {
309 		return CreateAsRenderTarget(context, texture, origin, sampleCount,
310 				colorType, colorspace, null);
311 	}
312 
313 	static SKSurface CreateAsRenderTarget(GRContext context,
314 			GRBackendTexture texture, SKColorType colorType, SKSurfaceProperties props) {
315 		return CreateAsRenderTarget(context, texture,
316 				GRSurfaceOrigin.BottomLeft, 0, colorType, null, props);
317 	}
318 
319 	static SKSurface CreateAsRenderTarget(GRContext context, GRBackendTexture texture,
320 			GRSurfaceOrigin origin, SKColorType colorType, SKSurfaceProperties props) {
321 		return CreateAsRenderTarget(context, texture, origin, 0, colorType, null, props);
322 	}
323 
324 	static SKSurface CreateAsRenderTarget(GRContext context, GRBackendTexture texture,
325 			GRSurfaceOrigin origin, int sampleCount, SKColorType colorType,
326 			SKSurfaceProperties props) {
327 		return CreateAsRenderTarget(context, texture, origin, sampleCount, colorType, null, props);
328 	}
329 
330 	static SKSurface CreateAsRenderTarget(GRContext context, GRBackendTexture texture, GRSurfaceOrigin origin,
331 			int sampleCount, SKColorType colorType, SKColorSpace colorspace,
332 			SKSurfaceProperties props) {
333 		if (context is null)
334 			throw new ArgumentNullException(context.stringof);
335 		if (texture is null)
336 			throw new ArgumentNullException(texture.stringof);
337 
338 		return GetObject(SkiaApi.sk_surface_new_backend_texture_as_render_target(cast(gr_context_t*) context.Handle,
339 				cast(gr_backendtexture_t*) texture.Handle, origin, sampleCount, ToNative(colorType),
340 				cast(sk_colorspace_t*)(colorspace.Handle ? colorspace.Handle : null),
341 				cast(sk_surfaceprops_t*)(props.Handle ? props.Handle : null)));
342 	}
343 
344 	// GPU NEW surface
345 
346 	static SKSurface Create(GRContext context, bool budgeted, SKImageInfo info,
347 			int sampleCount, SKSurfaceProps props) {
348 		return Create(context, budgeted, info, sampleCount,
349 				GRSurfaceOrigin.BottomLeft, new SKSurfaceProperties(props), false);
350 	}
351 
352 	static SKSurface Create(GRContext context, bool budgeted, SKImageInfo info) {
353 		return Create(context, budgeted, info, 0, GRSurfaceOrigin.BottomLeft, null, false);
354 	}
355 
356 	static SKSurface Create(GRContext context, bool budgeted, SKImageInfo info, int sampleCount) {
357 		return Create(context, budgeted, info, sampleCount,
358 				GRSurfaceOrigin.BottomLeft, null, false);
359 	}
360 
361 	static SKSurface Create(GRContext context, bool budgeted, SKImageInfo info,
362 			int sampleCount, GRSurfaceOrigin origin) {
363 		return Create(context, budgeted, info, sampleCount, origin, null, false);
364 	}
365 
366 	static SKSurface Create(GRContext context, bool budgeted, SKImageInfo info,
367 			SKSurfaceProperties props) {
368 		return Create(context, budgeted, info, 0, GRSurfaceOrigin.BottomLeft, props, false);
369 	}
370 
371 	static SKSurface Create(GRContext context, bool budgeted, SKImageInfo info,
372 			int sampleCount, SKSurfaceProperties props) {
373 		return Create(context, budgeted, info, sampleCount,
374 				GRSurfaceOrigin.BottomLeft, props, false);
375 	}
376 
377 	static SKSurface Create(GRContext context, bool budgeted, SKImageInfo info, int sampleCount,
378 			GRSurfaceOrigin origin, SKSurfaceProperties props, bool shouldCreateWithMips) {
379 		if (context is null)
380 			throw new ArgumentNullException(context.stringof);
381 
382 		auto cinfo = SKImageInfo.FromManaged(info);
383 		return GetObject(SkiaApi.sk_surface_new_render_target(cast(gr_context_t*) context.Handle, budgeted,
384 				&cinfo, sampleCount, origin, cast(sk_surfaceprops_t*)(props.Handle
385 				? props.Handle : null), shouldCreateWithMips));
386 	}
387 
388 	// NULL surface
389 
390 	static SKSurface CreateNull(int width, int height) {
391 		return GetObject(SkiaApi.sk_surface_new_null(width, height));
392 	}
393 
394 	//
395 
396 	SKCanvas Canvas() {
397 		return OwnedBy(SKCanvas.GetObject(SkiaApi.sk_surface_get_canvas(cast(sk_surface_t*) Handle),
398 				false, false), this);
399 	}
400 
401 	SKSurfaceProps SurfaceProps() {
402 		auto props = SurfaceProperties;
403 		SKSurfaceProps surfaceProps = SKSurfaceProps();
404 		surfaceProps.Flags = props.Flags;
405 		surfaceProps.PixelGeometry = props.PixelGeometry;
406 		return surfaceProps;
407 	}
408 
409 	SKSurfaceProperties SurfaceProperties() {
410 		return OwnedBy(SKSurfaceProperties.GetObject(cast(
411 				void*) SkiaApi.sk_surface_get_props(cast(sk_surface_t*) Handle), false), this);
412 	}
413 
414 	SKImage Snapshot() {
415 		return SKImage.GetObject(SkiaApi.sk_surface_new_image_snapshot(cast(sk_surface_t*) Handle));
416 	}
417 
418 	SKImage Snapshot(SKRectI bounds) {
419 		return SKImage.GetObject(SkiaApi.sk_surface_new_image_snapshot_with_crop(
420 				cast(sk_surface_t*) Handle, &bounds));
421 	}
422 
423 	void Draw(SKCanvas canvas, float x, float y, SKPaint paint) {
424 		if (canvas is null)
425 			throw new ArgumentNullException(canvas.stringof);
426 
427 		SkiaApi.sk_surface_draw(cast(sk_surface_t*) Handle,
428 				cast(sk_canvas_t*) canvas.Handle, x, y,
429 				cast(sk_paint_t*)(paint is null ? null : paint.Handle));
430 	}
431 
432 	SKPixmap PeekPixels() {
433 		auto pixmap = new SKPixmap();
434 		auto result = PeekPixels(pixmap);
435 		if (result) {
436 			return pixmap;
437 		} else {
438 			pixmap.Dispose();
439 			return null;
440 		}
441 	}
442 
443 	bool PeekPixels(SKPixmap pixmap) {
444 		if (pixmap is null)
445 			throw new ArgumentNullException(pixmap.stringof);
446 
447 		auto result = SkiaApi.sk_surface_peek_pixels(cast(sk_surface_t*) Handle,
448 				cast(sk_pixmap_t*) pixmap.Handle);
449 		if (result)
450 			pixmap.pixelSource = this;
451 		return result;
452 	}
453 
454 	bool ReadPixels(SKImageInfo dstInfo, void* dstPixels, int dstRowBytes, int srcX, int srcY) {
455 		auto cinfo = SKImageInfo.FromManaged(dstInfo);
456 		auto result = SkiaApi.sk_surface_read_pixels(cast(sk_surface_t*) Handle,
457 				&cinfo, cast(void*) dstPixels, cast(void*) dstRowBytes, srcX, srcY);
458 		// GC.KeepAlive (this);
459 		return result;
460 	}
461 
462 	static SKSurface GetObject(void* handle) {
463 		return handle is null ? null : new SKSurface(handle, true);
464 	}
465 
466 }