1 module skia.DelegateProxies;
2 
3 import std.experimental.logger;
4 import skia.Definitions;
5 import skia.SkiaApi;
6 import skia.SKMatrix;
7 
8 import core.memory;
9 import std.functional;
10 import skia.DelegateProxies;
11 
12 // delegates
13 
14 alias SKBitmapReleaseDelegate = void delegate (void* address, void* context);
15 
16 alias SKDataReleaseDelegate = void delegate (void* address, void* context);
17 
18 alias SKImageRasterReleaseDelegate = void delegate (void* pixels, void* context);
19 
20 alias SKImageTextureReleaseDelegate = void delegate (void* context);
21 
22 alias SKSurfaceReleaseDelegate = void delegate (void* address, void* context);
23 
24 alias GRGlGetProcDelegate = void* delegate (void* context, string name);
25 
26 alias GRGlGetProcedureAddressDelegate = void* delegate (string name);
27 
28 alias GRVkGetProcedureAddressDelegate = void* delegate (string name, void* instance, void* device);
29 
30 // TODO: Tasks pending completion -@Administrator at 2021-01-18T11:39:32+08:00
31 // 
32 // alias SKGlyphPathDelegate = void delegate (SKPath path, SKMatrix matrix);
33 
34 
35 alias UserDataDelegate = Object delegate();
36 
37 // delegate wrappers
38 
39 /**
40  * 
41  */
42 struct DelegateWrapper(T) {
43 	T del;
44 
45 	this(T del) {
46 		this.del = del;
47 	}
48 
49 }
50 
51 alias SKBitmapReleaseDelegateWrapper = DelegateWrapper!SKBitmapReleaseDelegate;
52 alias SKDataReleaseDelegateWrapper = DelegateWrapper!SKDataReleaseDelegate;
53 alias GRGlGetProcedureAddressDelegateWrapper = DelegateWrapper!GRGlGetProcedureAddressDelegate;
54 alias GRVkGetProcedureAddressDelegateWrapper = DelegateWrapper!GRVkGetProcedureAddressDelegate;
55 
56 
57 struct DelegateProxies
58 {
59 	// references to the proxy implementations
60 
61 	static SKBitmapReleaseProxyDelegate SKBitmapReleaseDelegateProxy () { return &SKBitmapReleaseDelegateProxyImplementation; }
62 	static SKDataReleaseProxyDelegate SKDataReleaseDelegateProxy () { return &SKDataReleaseDelegateProxyImplementation; }
63 	static SKImageRasterReleaseProxyDelegate SKImageRasterReleaseDelegateProxy () { return &SKImageRasterReleaseDelegateProxyImplementation; }
64 	static SKImageRasterReleaseProxyDelegate SKImageRasterReleaseDelegateProxyForCoTaskMem () { return &SKImageRasterReleaseDelegateProxyImplementationForCoTaskMem; }
65 	static SKImageTextureReleaseProxyDelegate SKImageTextureReleaseDelegateProxy () { return &SKImageTextureReleaseDelegateProxyImplementation; }
66 	static SKSurfaceRasterReleaseProxyDelegate SKSurfaceReleaseDelegateProxy () { return &SKSurfaceReleaseDelegateProxyImplementation; }
67 	static GRGlGetProcProxyDelegate GRGlGetProcDelegateProxy () { return &GRGlGetProcDelegateProxyImplementation; }
68 	static GRVkGetProcProxyDelegate GRVkGetProcDelegateProxy () { return &GRVkGetProcDelegateProxyImplementation; }
69 	static SKGlyphPathProxyDelegate SKGlyphPathDelegateProxy () { return &SKGlyphPathDelegateProxyImplementation; }
70 
71 	// proxy implementations
72 	extern(C) private static void SKBitmapReleaseDelegateProxyImplementation (void* address, void* context)
73 	{
74 		warning("TODO - start");
75 
76 		SKBitmapReleaseDelegateWrapper* wrapper = cast(SKBitmapReleaseDelegateWrapper*)context;
77 
78 		SKBitmapReleaseDelegate del = wrapper.del;
79 		if(del !is null) {
80 			scope(exit) {
81 				// Assuming that the callback is invoked only once, the
82 				// added root can be removed again now to allow the GC
83 				// to collect it later.
84 				GC.removeRoot(context);
85 				GC.clrAttr(context, GC.BlkAttr.NO_MOVE);
86 			}
87 
88 			try {
89 				del(address, null);
90 			} catch(Throwable t) {
91 				warning(t);
92 			}
93 		}
94 
95 		warning("TODO - done");
96 		// auto del = Get<SKBitmapReleaseDelegate> ((void*)context, out var gch);
97 		// try {
98 		// 	del.Invoke ((void*)address, null);
99 		// } finally {
100 		// 	gch.Free ();
101 		// }
102 	}
103 	extern(C) private static void SKDataReleaseDelegateProxyImplementation (void* address, void* context)
104 	{
105 		warning("TODO - start");
106 
107 		SKDataReleaseDelegateWrapper* wrapper = cast(SKDataReleaseDelegateWrapper*)context;
108 
109 		SKDataReleaseDelegate del = wrapper.del;
110 		if(del !is null) {
111 			scope(exit) {
112 				GC.removeRoot(context);
113 				GC.clrAttr(context, GC.BlkAttr.NO_MOVE);
114 			}
115 
116 			try {
117 				del(address, null);
118 			} catch(Throwable t) {
119 				warning(t);
120 			}
121 		}
122 
123 		warning("TODO - done");
124 	}
125 	
126 	extern(C) private static void SKImageRasterReleaseDelegateProxyImplementationForCoTaskMem (void* pixels, void* context)
127 	{
128 		warning("TODO");
129 		// Marshal.FreeCoTaskMem ((void*)pixels);
130 	}
131 
132 	extern(C) private static void SKImageRasterReleaseDelegateProxyImplementation (void* pixels, void* context)
133 	{
134 		warning("TODO");
135 		// auto del = Get<SKImageRasterReleaseDelegate> ((void*)context, out var gch);
136 		// try {
137 		// 	del.Invoke ((void*)pixels, null);
138 		// } finally {
139 		// 	gch.Free ();
140 		// }
141 	}
142 
143 	extern(C) private static void SKImageTextureReleaseDelegateProxyImplementation (void* context)
144 	{
145 
146 		warning("TODO");
147 
148 		// auto del = Get<SKImageTextureReleaseDelegate> ((void*)context, out var gch);
149 		// try {
150 		// 	del.Invoke (null);
151 		// } finally {
152 		// 	gch.Free ();
153 		// }
154 	}
155 
156 	extern(C) private static void SKSurfaceReleaseDelegateProxyImplementation (void* address, void* context)
157 	{
158 		warning("TODO");
159 		// auto del = Get<SKSurfaceReleaseDelegate> ((void*)context, out var gch);
160 		// try {
161 		// 	del.Invoke ((void*)address, null);
162 		// } finally {
163 		// 	gch.Free ();
164 		// }
165 	}
166 
167 	extern(C) private static void* GRGlGetProcDelegateProxyImplementation (void* context, void* name)
168 	{
169 		warning("TODO");
170 		return null;
171 
172 		// auto del = Get<GRGlGetProcedureAddressDelegate> ((void*)context, out _);
173 		// return del.Invoke (Marshal.PtrToStringAnsi ((void*)name));
174 	}
175 
176 	extern(C) private static void* GRVkGetProcDelegateProxyImplementation (void* context, void* name, void* instance, void* device)
177 	{
178 		warning("TODO");
179 		return null;
180 		// auto del = Get<GRVkGetProcedureAddressDelegate> ((void*)context, out _);
181 
182 		// return del.Invoke (Marshal.PtrToStringAnsi ((void*)name), instance, device);
183 	}
184 
185 	extern(C) private static void SKGlyphPathDelegateProxyImplementation (void* pathOrNull, SKMatrix* matrix, void* context)
186 	{
187 		warning("TODO");
188 		// auto del = Get<SKGlyphPathDelegate> ((void*)context, out _);
189 		// auto path = SKPath.GetObject (pathOrNull, false);
190 		// del.Invoke (path, *matrix);
191 	}
192 
193 
194 	static T Create(T) (T nativeDel, void* context)
195 	{
196 		if (context is null) {
197 			return T.init;
198 		}
199 
200 		// Make sure that it is not collected even if it is no
201 		// longer referenced from D code (stack, GC heap, …).
202 		GC.addRoot(cast(void*)context);
203 
204 		// Also ensure that a moving collector does not relocate
205 		// the object.
206 		GC.setAttr(cast(void*)context, GC.BlkAttr.NO_MOVE);
207 
208 		// gch = GCHandle.Alloc (managedDel);
209 		// GCHandle.ToIntPtr (gch);
210 		return nativeDel;
211 	}
212 
213 	// static void Create (T nativeDel, void* context)
214 	// {
215 	// 	if (context is null) {
216 	// 		return T.init;
217 	// 	}
218 
219 	// 	// Make sure that it is not collected even if it is no
220 	// 	// longer referenced from D code (stack, GC heap, …).
221 	// 	GC.addRoot(cast(void*)context);
222 
223 	// 	// Also ensure that a moving collector does not relocate
224 	// 	// the object.
225 	// 	GC.setAttr(cast(void*)context, GC.BlkAttr.NO_MOVE);
226 
227 	// 	// gch = GCHandle.Alloc (managedDel);
228 	// 	// GCHandle.ToIntPtr (gch);
229 	// 	return nativeDel;
230 	// }
231 
232 	// user data delegates
233 
234 	// static void* CreateUserData (Object userData, bool makeWeak = false)
235 	// {
236 	// 	UserDataDelegate del = () { return userData; } ;
237 
238 	// 	void* ctx ;
239 	// 	Create (del, out _, ctx);
240 	// 	return ctx;
241 	// }
242 }