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 }