Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
7643 views
1
#include "mupdf/pdf.h"
2
3
#include <mujs.h>
4
5
#define MAXARGS 16
6
7
#define OBJ(i) ((pdf_jsimp_obj*)((intptr_t)(i)))
8
#define IDX(p) ((intptr_t)(p))
9
#define NEWOBJ(J,x) OBJ(js_gettop(J) + (x))
10
11
struct pdf_jsimp_s
12
{
13
fz_context *ctx;
14
void *jsctx;
15
js_State *J;
16
};
17
18
static void *alloc(void *ud, void *ptr, unsigned int n)
19
{
20
fz_context *ctx = ud;
21
if (n == 0) {
22
fz_free(ctx, ptr);
23
return NULL;
24
}
25
if (ptr)
26
return fz_resize_array(ctx, ptr, n, 1);
27
return fz_malloc_array(ctx, n, 1);
28
}
29
30
pdf_jsimp *pdf_new_jsimp(fz_context *ctx, void *jsctx)
31
{
32
js_State *J;
33
pdf_jsimp *imp;
34
35
J = js_newstate(alloc, ctx, 0);
36
js_setcontext(J, jsctx);
37
38
imp = fz_malloc_struct(ctx, pdf_jsimp);
39
imp->ctx = ctx;
40
imp->jsctx = jsctx;
41
imp->J = J;
42
return imp;
43
}
44
45
void pdf_drop_jsimp(pdf_jsimp *imp)
46
{
47
if (imp)
48
{
49
js_freestate(imp->J);
50
fz_free(imp->ctx, imp);
51
}
52
}
53
54
pdf_jsimp_type *pdf_jsimp_new_type(pdf_jsimp *imp, pdf_jsimp_dtr *dtr, char *name)
55
{
56
js_State *J = imp->J;
57
js_newobject(J);
58
js_setregistry(J, name);
59
return (pdf_jsimp_type*)name;
60
}
61
62
void pdf_jsimp_drop_type(pdf_jsimp *imp, pdf_jsimp_type *type)
63
{
64
if (imp && type)
65
{
66
js_State *J = imp->J;
67
js_delregistry(J, (const char *)type);
68
}
69
}
70
71
static void wrapmethod(js_State *J)
72
{
73
pdf_jsimp_obj *args[MAXARGS];
74
pdf_jsimp_obj *ret;
75
pdf_jsimp_method *meth;
76
const char *type;
77
void *jsctx;
78
void *obj;
79
int i;
80
81
int argc = js_gettop(J) - 1;
82
83
jsctx = js_getcontext(J);
84
85
js_currentfunction(J);
86
{
87
js_getproperty(J, -1, "__call");
88
meth = js_touserdata(J, -1, "method");
89
js_pop(J, 1);
90
91
js_getproperty(J, -1, "__type");
92
type = js_tostring(J, -1);
93
js_pop(J, 1);
94
}
95
js_pop(J, 1);
96
97
if (js_isuserdata(J, 0, type))
98
obj = js_touserdata(J, 0, type);
99
else
100
obj = NULL;
101
102
if (argc > MAXARGS)
103
js_rangeerror(J, "too many arguments");
104
105
for (i = 0; i < argc; ++i)
106
args[i] = OBJ(i+1);
107
ret = meth(jsctx, obj, argc, args);
108
if (ret)
109
js_copy(J, IDX(ret));
110
else
111
js_pushundefined(J);
112
}
113
114
static void wrapgetter(js_State *J)
115
{
116
pdf_jsimp_obj *ret;
117
pdf_jsimp_getter *get;
118
const char *type;
119
void *jsctx;
120
void *obj;
121
122
jsctx = js_getcontext(J);
123
124
js_currentfunction(J);
125
{
126
js_getproperty(J, -1, "__get");
127
get = js_touserdata(J, -1, "getter");
128
js_pop(J, 1);
129
130
js_getproperty(J, -1, "__type");
131
type = js_tostring(J, -1);
132
js_pop(J, 1);
133
}
134
js_pop(J, 1);
135
136
if (js_isuserdata(J, 0, type))
137
obj = js_touserdata(J, 0, type);
138
else
139
obj = NULL;
140
141
ret = get(jsctx, obj);
142
if (ret)
143
js_copy(J, IDX(ret));
144
else
145
js_pushundefined(J);
146
}
147
148
static void wrapsetter(js_State *J)
149
{
150
pdf_jsimp_setter *set;
151
const char *type;
152
void *jsctx;
153
void *obj;
154
155
jsctx = js_getcontext(J);
156
157
js_currentfunction(J);
158
{
159
js_getproperty(J, -1, "__set");
160
set = js_touserdata(J, -1, "setter");
161
js_pop(J, 1);
162
163
js_getproperty(J, -1, "__type");
164
type = js_tostring(J, -1);
165
js_pop(J, 1);
166
}
167
js_pop(J, 1);
168
169
if (js_isuserdata(J, 0, type))
170
obj = js_touserdata(J, 0, type);
171
else
172
obj = NULL;
173
174
set(jsctx, obj, OBJ(1));
175
176
js_pushundefined(J);
177
}
178
179
void pdf_jsimp_addmethod(pdf_jsimp *imp, pdf_jsimp_type *type, char *name, pdf_jsimp_method *meth)
180
{
181
js_State *J = imp->J;
182
js_getregistry(J, (const char *)type);
183
{
184
js_newcfunction(J, wrapmethod, name, 0);
185
{
186
js_pushnull(J);
187
js_newuserdata(J, "method", meth, NULL);
188
js_defproperty(J, -2, "__call", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
189
js_pushstring(J, (const char *)type);
190
js_defproperty(J, -2, "__type", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
191
}
192
js_defproperty(J, -2, name, JS_READONLY | JS_DONTCONF);
193
}
194
js_pop(J, 1);
195
}
196
197
void pdf_jsimp_addproperty(pdf_jsimp *imp, pdf_jsimp_type *type, char *name, pdf_jsimp_getter *get, pdf_jsimp_setter *set)
198
{
199
js_State *J = imp->J;
200
js_getregistry(J, (const char *)type);
201
{
202
js_newcfunction(J, wrapgetter, name, 0);
203
{
204
js_pushnull(J);
205
js_newuserdata(J, "getter", get, NULL);
206
js_defproperty(J, -2, "__get", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
207
js_pushstring(J, (const char *)type);
208
js_defproperty(J, -2, "__type", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
209
}
210
js_newcfunction(J, wrapsetter, name, 0);
211
{
212
js_pushnull(J);
213
js_newuserdata(J, "setter", set, NULL);
214
js_defproperty(J, -2, "__set", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
215
js_pushstring(J, (const char *)type);
216
js_defproperty(J, -2, "__type", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
217
}
218
js_defaccessor(J, -3, name, JS_READONLY | JS_DONTCONF);
219
}
220
js_pop(J, 1);
221
}
222
223
void pdf_jsimp_set_global_type(pdf_jsimp *imp, pdf_jsimp_type *type)
224
{
225
js_State *J = imp->J;
226
const char *name;
227
228
js_getregistry(J, (const char *)type);
229
js_pushiterator(J, -1, 1);
230
while ((name = js_nextiterator(J, -1)))
231
{
232
js_getproperty(J, -2, name);
233
js_setglobal(J, name);
234
}
235
}
236
237
pdf_jsimp_obj *pdf_jsimp_new_obj(pdf_jsimp *imp, pdf_jsimp_type *type, void *natobj)
238
{
239
js_State *J = imp->J;
240
js_getregistry(J, (const char *)type);
241
js_newuserdata(J, (const char *)type, natobj, NULL);
242
return NEWOBJ(J, -1);
243
}
244
245
void pdf_jsimp_drop_obj(pdf_jsimp *imp, pdf_jsimp_obj *obj)
246
{
247
}
248
249
int pdf_jsimp_to_type(pdf_jsimp *imp, pdf_jsimp_obj *obj)
250
{
251
js_State *J = imp->J;
252
if (js_isnull(J, IDX(obj))) return JS_TYPE_NULL;
253
if (js_isboolean(J, IDX(obj))) return JS_TYPE_BOOLEAN;
254
if (js_isnumber(J, IDX(obj))) return JS_TYPE_NUMBER;
255
if (js_isstring(J, IDX(obj))) return JS_TYPE_STRING;
256
if (js_isarray(J, IDX(obj))) return JS_TYPE_ARRAY;
257
return JS_TYPE_UNKNOWN;
258
}
259
260
pdf_jsimp_obj *pdf_jsimp_from_string(pdf_jsimp *imp, char *str)
261
{
262
js_State *J = imp->J;
263
js_pushstring(J, str);
264
return NEWOBJ(J, -1);
265
}
266
267
char *pdf_jsimp_to_string(pdf_jsimp *imp, pdf_jsimp_obj *obj)
268
{
269
/* cast away const :( */
270
return (char*)js_tostring(imp->J, IDX(obj));
271
}
272
273
pdf_jsimp_obj *pdf_jsimp_from_number(pdf_jsimp *imp, double num)
274
{
275
js_State *J = imp->J;
276
js_pushnumber(J, num);
277
return NEWOBJ(J, -1);
278
}
279
280
double pdf_jsimp_to_number(pdf_jsimp *imp, pdf_jsimp_obj *obj)
281
{
282
return js_tonumber(imp->J, IDX(obj));
283
}
284
285
int pdf_jsimp_array_len(pdf_jsimp *imp, pdf_jsimp_obj *obj)
286
{
287
js_State *J = imp->J;
288
return js_getlength(J, IDX(obj));
289
}
290
291
pdf_jsimp_obj *pdf_jsimp_array_item(pdf_jsimp *imp, pdf_jsimp_obj *obj, int i)
292
{
293
js_State *J = imp->J;
294
js_getindex(J, IDX(obj), i);
295
return NEWOBJ(J, -1);
296
}
297
298
pdf_jsimp_obj *pdf_jsimp_property(pdf_jsimp *imp, pdf_jsimp_obj *obj, char *prop)
299
{
300
js_State *J = imp->J;
301
js_getproperty(J, IDX(obj), prop);
302
return NEWOBJ(J, -1);
303
}
304
305
void pdf_jsimp_execute(pdf_jsimp *imp, char *code)
306
{
307
js_State *J = imp->J;
308
js_dostring(J, code, 0);
309
}
310
311
void pdf_jsimp_execute_count(pdf_jsimp *imp, char *code, int count)
312
{
313
char *terminated = fz_malloc(imp->ctx, count+1);
314
memcpy(terminated, code, count);
315
terminated[count] = 0;
316
pdf_jsimp_execute(imp, terminated);
317
fz_free(imp->ctx, terminated);
318
}
319
320