Mercurial > molko
comparison src/libmlk-core-js/core/js-drawable.c @ 363:c74ab1bbedec
js: add drawable bindings
author | David Demelier <markand@malikania.fr> |
---|---|
date | Sun, 24 Oct 2021 09:55:12 +0200 |
parents | |
children | 8ac282bd5935 |
comparison
equal
deleted
inserted
replaced
362:12367bfc2df6 | 363:c74ab1bbedec |
---|---|
1 /* | |
2 * js-drawable.c -- core drawable binding | |
3 * | |
4 * Copyright (c) 2020-2021 David Demelier <markand@malikania.fr> | |
5 * | |
6 * Permission to use, copy, modify, and/or distribute this software for any | |
7 * purpose with or without fee is hereby granted, provided that the above | |
8 * copyright notice and this permission notice appear in all copies. | |
9 * | |
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
17 */ | |
18 | |
19 #include <assert.h> | |
20 | |
21 #include <core/alloc.h> | |
22 #include <core/drawable.h> | |
23 | |
24 #include "js-drawable.h" | |
25 | |
26 #define SIGNATURE DUK_HIDDEN_SYMBOL("Mlk.Drawable") | |
27 | |
28 struct self { | |
29 duk_context *ctx; | |
30 void *ptr; | |
31 struct drawable dw; | |
32 unsigned int refc; | |
33 }; | |
34 | |
35 static inline struct self * | |
36 self(duk_context *ctx) | |
37 { | |
38 struct self *sf = NULL; | |
39 | |
40 duk_push_this(ctx); | |
41 duk_get_prop_string(ctx, -1, SIGNATURE); | |
42 sf = duk_to_pointer(ctx, -1); | |
43 duk_pop_2(ctx); | |
44 | |
45 if (!sf) | |
46 duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Drawable object"); | |
47 | |
48 return sf; | |
49 } | |
50 | |
51 static inline int | |
52 callable(struct self *s, const char *prop, duk_context **ctx) | |
53 { | |
54 int callable; | |
55 | |
56 if (!s->ptr) | |
57 return 0; | |
58 | |
59 duk_push_heapptr(s->ctx, s->ptr); | |
60 duk_get_prop_string(s->ctx, -1, prop); | |
61 duk_remove(s->ctx, -2); | |
62 | |
63 if (duk_is_callable(s->ctx, -1)) { | |
64 *ctx = s->ctx; | |
65 callable = 1; | |
66 } else { | |
67 *ctx = NULL; | |
68 callable = 0; | |
69 duk_pop(s->ctx); | |
70 } | |
71 | |
72 return callable; | |
73 } | |
74 | |
75 static int | |
76 update(struct drawable *dw, unsigned int ticks) | |
77 { | |
78 duk_context *ctx; | |
79 int ret = 0; | |
80 | |
81 if (callable(dw->data, "update", &ctx)) { | |
82 duk_push_uint(ctx, ticks); | |
83 duk_call(ctx, 1); | |
84 ret = duk_to_int(ctx, -1); | |
85 } | |
86 | |
87 return ret; | |
88 } | |
89 | |
90 static void | |
91 draw(struct drawable *dw) | |
92 { | |
93 duk_context *ctx; | |
94 | |
95 if (callable(dw->data, "draw", &ctx)) | |
96 duk_call(ctx, 0); | |
97 } | |
98 | |
99 static void | |
100 end(struct drawable *dw) | |
101 { | |
102 duk_context *ctx; | |
103 | |
104 if (callable(dw->data, "end", &ctx)) | |
105 duk_call(ctx, 0); | |
106 } | |
107 | |
108 static void | |
109 finish(struct drawable *dw) | |
110 { | |
111 struct self *sf = dw->data; | |
112 | |
113 if (!--sf->refc) | |
114 free(sf); | |
115 } | |
116 | |
117 static duk_ret_t | |
118 Drawable_getX(duk_context *ctx) | |
119 { | |
120 duk_push_uint(ctx, self(ctx)->dw.x); | |
121 | |
122 return 1; | |
123 } | |
124 | |
125 static duk_ret_t | |
126 Drawable_setX(duk_context *ctx) | |
127 { | |
128 self(ctx)->dw.x = duk_require_uint(ctx, 0); | |
129 | |
130 return 0; | |
131 } | |
132 | |
133 static duk_ret_t | |
134 Drawable_getY(duk_context *ctx) | |
135 { | |
136 duk_push_uint(ctx, self(ctx)->dw.y); | |
137 | |
138 return 1; | |
139 } | |
140 | |
141 static duk_ret_t | |
142 Drawable_setY(duk_context *ctx) | |
143 { | |
144 self(ctx)->dw.y = duk_require_uint(ctx, 0); | |
145 | |
146 return 0; | |
147 } | |
148 | |
149 static duk_ret_t | |
150 Drawable_constructor(duk_context *ctx) | |
151 { | |
152 struct self *self; | |
153 const int x = duk_require_int(ctx, 0); | |
154 const int y = duk_require_int(ctx, 1); | |
155 | |
156 self = alloc_new0(sizeof (*self)); | |
157 self->refc = 1; | |
158 self->ctx = ctx; | |
159 self->dw.x = x; | |
160 self->dw.y = y; | |
161 self->dw.data = self; | |
162 self->dw.update = update; | |
163 self->dw.finish = finish; | |
164 self->dw.draw = draw; | |
165 self->dw.end = end; | |
166 | |
167 duk_push_this(ctx); | |
168 self->ptr = duk_get_heapptr(ctx, -1); | |
169 duk_push_pointer(ctx, self); | |
170 duk_put_prop_string(ctx, -2, SIGNATURE); | |
171 duk_push_string(ctx, "x"); | |
172 duk_push_c_function(ctx, Drawable_getX, 0); | |
173 duk_push_c_function(ctx, Drawable_setX, 1); | |
174 duk_def_prop(ctx, -4, DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER); | |
175 duk_push_string(ctx, "y"); | |
176 duk_push_c_function(ctx, Drawable_getY, 0); | |
177 duk_push_c_function(ctx, Drawable_setY, 1); | |
178 duk_def_prop(ctx, -4, DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER); | |
179 duk_pop(ctx); | |
180 | |
181 return 0; | |
182 } | |
183 | |
184 static duk_ret_t | |
185 Drawable_destructor(duk_context *ctx) | |
186 { | |
187 struct self *sf; | |
188 | |
189 duk_get_prop_string(ctx, 0, SIGNATURE); | |
190 | |
191 if ((sf = duk_to_pointer(ctx, -1))) { | |
192 sf->ptr = NULL; | |
193 drawable_finish(&sf->dw); | |
194 } | |
195 | |
196 duk_del_prop_string(ctx, 0, SIGNATURE); | |
197 duk_pop(ctx); | |
198 | |
199 return 0; | |
200 } | |
201 | |
202 | |
203 void | |
204 js_drawable_bind(duk_context *ctx) | |
205 { | |
206 assert(ctx); | |
207 | |
208 duk_push_c_function(ctx, Drawable_constructor, 2); | |
209 duk_push_object(ctx); | |
210 duk_push_c_function(ctx, Drawable_destructor, 1); | |
211 duk_set_finalizer(ctx, -2); | |
212 duk_put_prop_string(ctx, -2, "prototype"); | |
213 duk_put_global_string(ctx, "Drawable"); | |
214 } | |
215 | |
216 struct drawable * | |
217 js_drawable_require(duk_context *ctx, duk_idx_t idx) | |
218 { | |
219 struct self *sf = NULL; | |
220 | |
221 if (duk_is_object(ctx, idx)) { | |
222 duk_get_prop_string(ctx, idx, SIGNATURE); | |
223 sf = duk_to_pointer(ctx, -1); | |
224 duk_pop(ctx); | |
225 } | |
226 | |
227 if (!sf) | |
228 duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Drawable object"); | |
229 | |
230 sf->refc++; | |
231 | |
232 return &sf->dw; | |
233 } |