beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / lua / limglib.c
blob44f1d72bff0c0badcc160efbeab94c1d767f1af8
1 /* limglib.c
3 Copyright 2006-2013 Taco Hoekwater <taco@luatex.org>
5 This file is part of LuaTeX.
7 LuaTeX is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2 of the License, or (at your
10 option) any later version.
12 LuaTeX is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License along
18 with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */
20 #include "ptexlib.h"
21 #include "lua/luatex-api.h"
22 #include <stdio.h>
23 #include <string.h>
24 #include "lua.h"
25 #include "lauxlib.h"
27 #define img_types_max 7
29 const char *img_types[] = {
30 "none",
31 "pdf",
32 "png",
33 "jpg",
34 "jp2",
35 "jbig2",
36 "stream",
37 "memstream",
38 NULL
41 static void copy_image(lua_State * L, lua_Number scale)
43 image *a, **aa, *b, **bb;
44 image_dict *d;
45 if (lua_gettop(L) == 0)
46 luaL_error(L, "img.copy needs an image as argument");
47 aa = (image **) luaL_checkudata(L, 1, TYPE_IMG); /* a */
48 lua_pop(L, 1); /* - */
49 a = *aa;
50 bb = (image **) lua_newuserdata(L, sizeof(image *)); /* b */
51 luaL_getmetatable(L, TYPE_IMG); /* m b */
52 lua_setmetatable(L, -2); /* b */
53 b = *bb = new_image();
54 if (!is_wd_running(a))
55 img_width(b) = do_zround(img_width(a) * scale);
56 if (!is_ht_running(a))
57 img_height(b) = do_zround(img_height(a) * scale);
58 if (!is_dp_running(a))
59 img_depth(b) = do_zround(img_depth(a) * scale);
60 img_transform(b) = img_transform(a);
61 img_dict(b) = img_dict(a);
62 if (img_dictref(a) != LUA_NOREF) {
63 lua_rawgeti(L, LUA_REGISTRYINDEX, img_dictref(a)); /* ad b */
64 img_dictref(b) = luaL_ref(L, LUA_REGISTRYINDEX); /* b */
65 d = img_dict(*aa);
66 img_luaref(d) += 1;
67 } else if (img_state(img_dict(a)) < DICT_REFERED) {
68 luaL_error(L, "img.copy needs an proper image as argument");
72 static void lua_to_image(lua_State * L, image * a, image_dict * d);
74 int l_new_image(lua_State * L)
76 image *a, **aa;
77 image_dict **add;
78 if (lua_gettop(L) > 0 && ! lua_istable(L, -1)) {
79 luaL_error(L, "img.new needs table as optional argument"); /* (t) */
81 aa = (image **) lua_newuserdata(L, sizeof(image *)); /* i (t) */
82 luaL_getmetatable(L, TYPE_IMG); /* m i (t) */
83 lua_setmetatable(L, -2); /* i (t) */
84 a = *aa = new_image();
85 add = (image_dict **) lua_newuserdata(L, sizeof(image_dict *)); /* ad i (t) */
86 luaL_getmetatable(L, TYPE_IMG_DICT); /* m ad i (t) */
87 lua_setmetatable(L, -2); /* ad i (t) */
88 img_dict(a) = *add = new_image_dict();
89 img_dictref(a) = luaL_ref(L, LUA_REGISTRYINDEX); /* i (t) */
90 img_luaref(*add) += 1;
91 if (lua_gettop(L) == 2) { /* i t, else just i */
92 lua_insert(L, -2); /* t i */
93 lua_pushnil(L); /* n t i (1st key for iterator) */
94 while (lua_next(L, -2) != 0) { /* v k t i */
95 lua_to_image(L, a, *add); /* v k t i */
96 lua_pop(L, 1); /* k t i */
97 } /* t i */
98 lua_pop(L, 1); /* i */
99 } /* i */
100 return 1; /* i */
103 static int l_copy_image(lua_State * L)
105 if (lua_gettop(L) != 1) {
106 luaL_error(L, "img.copy needs an image as argument");
107 } else if (lua_istable(L, 1)) {
108 (void) l_new_image(L);
109 } else {
110 (void) copy_image(L, 1.0);
112 return 1;
115 static void read_scale_img(image * a)
117 image_dict *ad;
118 if (a == NULL) {
119 luaL_error(Luas, "the image scaler needs a valid image");
120 } else {
121 ad = img_dict(a);
122 if (a == NULL) {
123 luaL_error(Luas, "the image scaler needs a valid dictionary");
124 } else {
125 if (img_state(ad) == DICT_NEW) {
126 if (img_type(ad) == IMG_TYPE_PDFSTREAM)
127 check_pdfstream_dict(ad);
128 else {
129 read_img(ad);
132 if ((img_type(ad) == IMG_TYPE_NONE) || (img_state(ad) == DICT_NEW)) {
133 normal_warning("image","don't rely on the image data to be okay");
134 img_width(a) = 0;
135 img_height(a) = 0;
136 img_depth(a) = 0;
137 } else if (is_wd_running(a) || is_ht_running(a) || is_dp_running(a)) {
138 img_dimen(a) = scale_img(ad, img_dimen(a), img_transform(a));
144 static int l_scan_image(lua_State * L)
146 image *a, **aa;
147 if (lua_gettop(L) != 1)
148 luaL_error(L, "img.scan needs exactly 1 argument");
149 if (lua_istable(L, 1))
150 (void) l_new_image(L);
151 aa = (image **) luaL_checkudata(L, 1, TYPE_IMG);
152 a = *aa;
153 check_o_mode(static_pdf, "img.scan", 1 << OMODE_PDF, false);
154 read_scale_img(a);
155 return 1;
158 static halfword img_to_node(lua_State * L, image * a)
160 image_dict *ad;
161 halfword n = null;
162 if (a == NULL) {
163 luaL_error(L, "img.tonode needs a valid image");
164 } else {
165 ad = img_dict(a);
166 if (a == NULL) {
167 luaL_error(L, "img.tonode image has no dictionary");
168 } else if (img_objnum(ad) == 0) {
169 luaL_error(L, "img.tonode got image without object number");
170 } else {
171 n = new_rule(image_rule);
172 rule_index(n) = img_index(ad);
173 width(n) = img_width(a);
174 height(n) = img_height(a);
175 depth(n) = img_depth(a);
176 rule_transform(n) = img_transform(a);
179 return n;
182 typedef enum {
183 WR_WRITE,
184 WR_IMMEDIATEWRITE,
185 WR_NODE,
186 WR_VF_IMG
187 } wrtype_e;
189 const char *wrtype_s[] = {
190 "img.write()",
191 "img.immediatewrite()",
192 "img.node()",
193 "write vf image"
196 static void setup_image(PDF pdf, image * a, wrtype_e writetype)
198 image_dict *ad;
199 if (a == NULL)
200 luaL_error(Luas, "no valid image passed"); /* todo, also check in caller */
201 ad = img_dict(a);
202 check_o_mode(pdf, wrtype_s[writetype], 1 << OMODE_PDF, false);
203 read_scale_img(a);
204 if (img_objnum(ad) == 0) { /* latest needed just before out_img() */
205 pdf->ximage_count++;
206 img_objnum(ad) = pdf_create_obj(pdf, obj_type_ximage, pdf->ximage_count);
207 img_index(ad) = pdf->ximage_count;
208 idict_to_array(ad); /* from now on ad is read-only */
209 obj_data_ptr(pdf, pdf->obj_ptr) = img_index(ad);
213 static void write_image_or_node(lua_State * L, wrtype_e writetype)
215 image *a, **aa;
216 image_dict *ad;
217 halfword n;
218 if (lua_gettop(L) != 1)
219 luaL_error(L, "%s expects an argument", wrtype_s[writetype]);
220 if (lua_istable(L, 1))
221 (void) l_new_image(L);
222 aa = (image **) luaL_checkudata(L, 1, TYPE_IMG);
223 a = *aa;
224 ad = img_dict(a);
225 setup_image(static_pdf, a, writetype);
226 switch (writetype) {
227 case WR_WRITE:
228 n = img_to_node(L, a);
229 tail_append(n);
230 break;
231 case WR_IMMEDIATEWRITE:
232 write_img(static_pdf, ad);
233 break;
234 case WR_NODE:
235 lua_pop(L, 1); /* - */
236 n = img_to_node(L, a);
237 lua_nodelib_push_fast(L, n);
238 break;
239 default:
240 luaL_error(L, "%s expects an valid image", wrtype_s[writetype]);
242 if (img_state(ad) < DICT_REFERED)
243 img_state(ad) = DICT_REFERED;
246 static int l_write_image(lua_State * L)
248 write_image_or_node(L, WR_WRITE);
249 return 1;
252 static int l_immediatewrite_image(lua_State * L)
254 check_o_mode(static_pdf, "img.immediatewrite", 1 << OMODE_PDF, true);
255 if (global_shipping_mode != NOT_SHIPPING) {
256 luaL_error(L, "img.immediatewrite can not be used with \\latelua");
257 } else {
258 write_image_or_node(L, WR_IMMEDIATEWRITE);
260 return 1;
263 static int l_image_node(lua_State * L)
265 write_image_or_node(L, WR_NODE);
266 return 1;
269 static int l_image_keys(lua_State * L)
271 return lua_show_valid_keys(L, img_parms, img_parms_max);
274 static int l_image_types(lua_State * L)
276 return lua_show_valid_list(L, img_types, img_types_max);
279 static int l_image_boxes(lua_State * L)
281 return lua_show_valid_keys(L, img_pageboxes, img_pageboxes_max);
284 static const struct luaL_Reg imglib_f[] = {
285 { "new", l_new_image },
286 { "copy", l_copy_image },
287 { "scan", l_scan_image },
288 { "write", l_write_image },
289 { "immediatewrite", l_immediatewrite_image },
290 { "node", l_image_node },
291 { "keys", l_image_keys },
292 { "types", l_image_types },
293 { "boxes", l_image_boxes },
294 { NULL, NULL }
297 void vf_out_image(PDF pdf, unsigned i)
299 image *a, **aa;
300 image_dict *ad;
301 lua_State *L = Luas;
302 lua_rawgeti(L, LUA_REGISTRYINDEX, (int) i);
303 aa = (image **) luaL_checkudata(L, -1, TYPE_IMG);
304 a = *aa;
305 ad = img_dict(a);
306 if (ad == NULL) {
307 luaL_error(L, "invalid image dictionary");
309 setup_image(pdf, a, WR_VF_IMG);
310 place_img(pdf, ad, img_dimen(a), img_transform(a));
311 lua_pop(L, 1);
314 /* metamethods for image */
316 static int m_img_get(lua_State * L)
318 int j;
319 const char *s;
320 image **a = (image **) luaL_checkudata(L, 1, TYPE_IMG); /* k u */
321 image_dict *d = img_dict(*a);
322 if (d == NULL) {
323 luaL_error(L, "invalid image dictionary");
325 s = lua_tostring(L, 2);
326 if (lua_key_eq(s,width)) {
327 if (is_wd_running(*a)) {
328 lua_pushnil(L);
329 } else {
330 lua_pushinteger(L, img_width(*a));
332 } else if (lua_key_eq(s,height)) {
333 if (is_ht_running(*a)) {
334 lua_pushnil(L);
335 } else {
336 lua_pushinteger(L, img_height(*a));
338 } else if (lua_key_eq(s,depth)) {
339 if (is_dp_running(*a)) {
340 lua_pushnil(L);
341 } else {
342 lua_pushinteger(L, img_depth(*a));
344 } else if (lua_key_eq(s,transform)) {
345 lua_pushinteger(L, img_transform(*a));
346 } else if (lua_key_eq(s,filename)) {
347 if (img_filename(d) == NULL || strlen(img_filename(d)) == 0) {
348 lua_pushnil(L);
349 } else {
350 lua_pushstring(L, img_filename(d));
352 } else if (lua_key_eq(s,visiblefilename)) {
353 if (img_visiblefilename(d) == NULL || strlen(img_visiblefilename(d)) == 0) {
354 lua_pushnil(L);
355 } else {
356 lua_pushstring(L, img_visiblefilename(d));
358 } else if (lua_key_eq(s,keepopen)) {
359 lua_pushboolean(L, img_keepopen(d));
360 } else if (lua_key_eq(s,filepath)) {
361 if (img_filepath(d) == NULL || strlen(img_filepath(d)) == 0) {
362 lua_pushnil(L);
363 } else {
364 lua_pushstring(L, img_filepath(d));
366 } else if (lua_key_eq(s,attr)) {
367 if (img_attr(d) == NULL || strlen(img_attr(d)) == 0) {
368 lua_pushnil(L);
369 } else {
370 lua_pushstring(L, img_attr(d));
372 } else if (lua_key_eq(s,page)) {
373 if (img_pagename(d) != NULL && strlen(img_pagename(d)) != 0) {
374 lua_pushstring(L, img_pagename(d));
375 } else {
376 lua_pushinteger(L, img_pagenum(d));
378 } else if (lua_key_eq(s,pages)) {
379 lua_pushinteger(L, img_totalpages(d));
380 } else if (lua_key_eq(s,xsize)) {
381 if ((img_rotation(d) & 1) == 0) {
382 lua_pushinteger(L, img_xsize(d));
383 } else {
384 lua_pushinteger(L, img_ysize(d));
386 } else if (lua_key_eq(s,ysize)) {
387 if ((img_rotation(d) & 1) == 0) {
388 lua_pushinteger(L, img_ysize(d));
389 } else {
390 lua_pushinteger(L, img_xsize(d));
392 } else if (lua_key_eq(s,xres)) {
393 lua_pushinteger(L, img_xres(d));
394 } else if (lua_key_eq(s,yres)) {
395 lua_pushinteger(L, img_yres(d));
396 } else if (lua_key_eq(s,rotation)) {
397 lua_pushinteger(L, img_rotation(d));
398 } else if (lua_key_eq(s,colorspace)) {
399 if (img_colorspace(d) == 0) {
400 lua_pushnil(L);
401 } else {
402 lua_pushinteger(L, img_colorspace(d));
404 } else if (lua_key_eq(s,colordepth)) {
405 if (img_colordepth(d) == 0) {
406 lua_pushnil(L);
407 } else {
408 lua_pushinteger(L, img_colordepth(d));
410 } else if (lua_key_eq(s,imagetype)) {
411 j = img_type(d);
412 if (j >= 0 && j <= img_types_max) {
413 if (j == IMG_TYPE_NONE) {
414 lua_pushnil(L);
415 } else {
416 lua_pushstring(L, img_types[j]);
418 } else {
419 lua_pushnil(L);
421 } else if (lua_key_eq(s,pagebox)) {
422 j = img_pagebox(d);
423 if (j < 0 || j >= img_pageboxes_max) {
424 j = 0;
426 lua_push_img_pagebox(L, j);
427 } else if (lua_key_eq(s,bbox)) {
428 if (!img_is_bbox(d)) {
429 img_bbox(d)[0] = img_xorig(d);
430 img_bbox(d)[1] = img_yorig(d);
431 img_bbox(d)[2] = img_xorig(d) + img_xsize(d);
432 img_bbox(d)[3] = img_yorig(d) + img_ysize(d);
434 lua_newtable(L);
435 lua_pushinteger(L, 1);
436 lua_pushinteger(L, img_bbox(d)[0]);
437 lua_settable(L, -3);
438 lua_pushinteger(L, 2);
439 lua_pushinteger(L, img_bbox(d)[1]);
440 lua_settable(L, -3);
441 lua_pushinteger(L, 3);
442 lua_pushinteger(L, img_bbox(d)[2]);
443 lua_settable(L, -3);
444 lua_pushinteger(L, 4);
445 lua_pushinteger(L, img_bbox(d)[3]);
446 lua_settable(L, -3);
447 } else if (lua_key_eq(s,objnum)) {
448 if (img_objnum(d) == 0) {
449 lua_pushnil(L);
450 } else {
451 lua_pushinteger(L, img_objnum(d));
453 } else if (lua_key_eq(s,index)) {
454 if (img_index(d) == 0) {
455 lua_pushnil(L);
456 } else {
457 lua_pushinteger(L, img_index(d));
459 } else if (lua_key_eq(s,stream)) {
460 if (img_type(d) != IMG_TYPE_PDFSTREAM
461 || img_pdfstream_ptr(d) == NULL
462 || img_pdfstream_stream(d) == NULL
463 || strlen(img_pdfstream_stream(d)) == 0) {
464 lua_pushnil(L);
465 } else {
466 lua_pushstring(L, img_pdfstream_stream(d));
468 } else if (lua_key_eq(s,ref_count)) {
469 lua_pushinteger(L, img_luaref(d));
470 } else {
471 lua_pushnil(L);
473 return 1;
476 static void lua_to_image(lua_State * L, image * a, image_dict * d)
478 int i, t;
479 const char *s;
480 s = lua_tostring(L,-2);
481 t = lua_type(L, -1);
482 if (lua_key_eq(s,width)) {
483 if (t == LUA_TNIL) {
484 set_wd_running(a);
485 } else if (t == LUA_TNUMBER) {
486 img_width(a) = (int) lua_tointeger(L, -1);
487 } else if (t == LUA_TSTRING) {
488 img_width(a) = dimen_to_number(L, lua_tostring(L, -1));
489 } else {
490 luaL_error(L, "image.width needs integer or nil value or dimension string");
492 } else if (lua_key_eq(s,height)) {
493 if (t == LUA_TNIL) {
494 set_ht_running(a);
495 } else if (t == LUA_TNUMBER) {
496 img_height(a) = (int) lua_tointeger(L, -1);
497 } else if (t == LUA_TSTRING) {
498 img_height(a) = dimen_to_number(L, lua_tostring(L, -1));
499 } else {
500 luaL_error(L, "image.height needs integer or nil value or dimension string");
502 } else if (lua_key_eq(s,depth)) {
503 if (t == LUA_TNIL) {
504 set_dp_running(a);
505 } else if (t == LUA_TNUMBER) {
506 img_depth(a) = (int) lua_tointeger(L, -1);
507 } else if (t == LUA_TSTRING) {
508 img_depth(a) = dimen_to_number(L, lua_tostring(L, -1));
509 } else {
510 luaL_error(L, "image.depth needs integer or nil value or dimension string");
512 } else if (lua_key_eq(s,transform)) {
513 if (t == LUA_TNUMBER) {
514 img_transform(a) = (int) lua_tointeger(L, -1);
515 } else {
516 luaL_error(L, "image.transform needs integer value");
518 } else if (lua_key_eq(s,filename)) {
519 if (img_state(d) >= DICT_FILESCANNED) {
520 luaL_error(L, "image.filename is now read-only");
521 } else if (img_type(d) == IMG_TYPE_PDFSTREAM) {
522 luaL_error(L, "image.filename can't be used with image.stream");
523 } else if (t == LUA_TSTRING) {
524 xfree(img_filename(d));
525 img_filename(d) = xstrdup(lua_tostring(L, -1));
526 } else {
527 luaL_error(L, "image.filename needs string value");
529 } else if (lua_key_eq(s,visiblefilename)) {
530 if (img_state(d) >= DICT_FILESCANNED) {
531 luaL_error(L, "image.visiblefilename is now read-only");
532 } else if (img_type(d) == IMG_TYPE_PDFSTREAM) {
533 luaL_error(L, "image.visiblefilename can't be used with image.stream");
534 } else if (t == LUA_TSTRING) {
535 xfree(img_visiblefilename(d));
536 img_visiblefilename(d) = xstrdup(lua_tostring(L, -1));
537 } else {
538 luaL_error(L, "image.visiblefilename needs string value");
540 } else if (lua_key_eq(s,attr)) {
541 if (img_state(d) >= DICT_FILESCANNED) {
542 luaL_error(L, "image.attr is now read-only");
543 } else if (t == LUA_TSTRING) {
544 xfree(img_attr(d));
545 img_attr(d) = xstrdup(lua_tostring(L, -1));
546 } else if (t == LUA_TNIL) {
547 xfree(img_attr(d));
548 } else {
549 luaL_error(L, "image.attr needs string or nil value");
551 } else if (lua_key_eq(s,page)) {
552 if (img_state(d) >= DICT_FILESCANNED) {
553 luaL_error(L, "image.page is now read-only");
554 } else if (t == LUA_TSTRING) {
555 xfree(img_pagename(d));
556 img_pagename(d) = xstrdup(lua_tostring(L, -1));
557 img_pagenum(d) = 0;
558 } else if (t == LUA_TNUMBER) {
559 img_pagenum(d) = (int) lua_tointeger(L, -1);
560 xfree(img_pagename(d));
561 } else {
562 luaL_error(L, "image.page needs integer or string value");
564 } else if (lua_key_eq(s,colorspace)) {
565 if (img_state(d) >= DICT_FILESCANNED) {
566 luaL_error(L, "image.colorspace is now read-only");
567 } else if (t == LUA_TNIL) {
568 img_colorspace(d) = 0;
569 } else if (t == LUA_TNUMBER) {
570 img_colorspace(d) = (int) lua_tointeger(L, -1);
571 } else {
572 luaL_error(L, "image.colorspace needs integer or nil value");
574 } else if (lua_key_eq(s,pagebox)) {
575 if (img_state(d) >= DICT_FILESCANNED) {
576 luaL_error(L, "image.pagebox is now read-only");
577 } else if (t == LUA_TNIL) {
578 img_pagebox(d) = PDF_BOX_SPEC_MEDIA;
579 } else if (t == LUA_TNUMBER) {
580 i = lua_tointeger(L,-1);
581 if (i < 0 || i >= img_pageboxes_max) {
582 img_pagebox(d) = PDF_BOX_SPEC_MEDIA;
583 } else {
584 img_pagebox(d) = i;
586 } else if (t == LUA_TSTRING) {
587 img_pagebox(d) = PDF_BOX_SPEC_MEDIA;
588 for (i = 0; i < img_pageboxes_max; i++) {
589 lua_rawgeti(L, LUA_REGISTRYINDEX, img_pageboxes[i]);
590 if (lua_rawequal(L,-1,-2)) {
591 img_pagebox(d) = i;
592 lua_pop(L, 1);
593 break;
594 } else {
595 lua_pop(L, 1);
598 } else {
599 luaL_error(L, "image.pagebox needs string, number or nil value");
601 } else if (lua_key_eq(s,keepopen)) {
602 if (img_state(d) >= DICT_FILESCANNED) {
603 luaL_error(L, "image.keepopen is now read-only");
604 } else if (t != LUA_TBOOLEAN) {
605 luaL_error(L, "image.bbox needs boolean value");
606 } else {
607 img_keepopen(d) = lua_toboolean(L, -1);
609 } else if (lua_key_eq(s,bbox)) {
610 if (img_state(d) >= DICT_FILESCANNED) {
611 luaL_error(L, "image.bbox is now read-only");
612 } else if (t != LUA_TTABLE) {
613 luaL_error(L, "image.bbox needs table value");
614 } else if (lua_rawlen(L, -1) != 4) {
615 luaL_error(L, "image.bbox table must have exactly 4 elements");
616 } else {
617 for (i = 1; i <= 4; i++) { /* v k t ... */
618 lua_pushinteger(L, i); /* idx v k t ... */
619 lua_gettable(L, -2); /* int v k t ... */
620 t = lua_type(L, -1);
621 if (t == LUA_TNUMBER) {
622 img_bbox(d)[i - 1] = (int) lua_tointeger(L, -1);
623 } else if (t == LUA_TSTRING) {
624 img_bbox(d)[i - 1] = dimen_to_number(L, lua_tostring(L, -1));
625 } else {
626 luaL_error(L, "image.bbox table needs integer value or dimension string elements");
628 lua_pop(L, 1); /* v k t ... */
630 img_set_bbox(d);
632 } else if (lua_key_eq(s,stream)) {
633 if (img_filename(d) != NULL) {
634 luaL_error(L, "image.stream can't be used with image.filename");
635 } else if (img_state(d) >= DICT_FILESCANNED) {
636 luaL_error(L, "image.stream is now read-only");
637 } else {
638 if (img_pdfstream_ptr(d) == NULL) {
639 new_img_pdfstream_struct(d);
641 xfree(img_pdfstream_stream(d));
642 img_pdfstream_stream(d) = xstrdup(lua_tostring(L, -1));
643 img_type(d) = IMG_TYPE_PDFSTREAM;
645 } else {
646 luaL_error(L, "image.%s can not be set", s);
650 static int m_img_set(lua_State * L)
652 image **a = (image **) luaL_checkudata(L, 1, TYPE_IMG); /* v k u */
653 image_dict *d = img_dict(*a);
654 if (d == NULL) {
655 luaL_error(L, "invalid image dictionary");
656 } else {
657 lua_to_image(L, *a, d);
659 return 0;
662 static int m_img_mul(lua_State * L)
664 lua_Number scale;
665 if (lua_type(L, 1) == LUA_TNUMBER) { /* u? n */
666 (void) luaL_checkudata(L, 2, TYPE_IMG); /* u n */
667 lua_insert(L, -2); /* n a */
668 } else if (lua_type(L, 2) != LUA_TNUMBER) { /* n u? */
669 (void) luaL_checkudata(L, 1, TYPE_IMG); /* n a */
670 } /* n a */
671 scale = lua_tonumber(L, 2); /* float */ /* n a */
672 lua_pop(L, 1); /* a */
673 copy_image(L, scale); /* b */
674 return 1;
677 static int m_img_print(lua_State * L)
679 image **aa;
680 image_dict *d;
681 aa = (image **) luaL_checkudata(L, 1, TYPE_IMG);
682 d = img_dict(*aa);
683 /* formatted a bit like a node */
684 if (img_filename(d) == NULL) {
685 if (img_pagename(d) != NULL && strlen(img_pagename(d)) != 0) {
686 lua_pushfstring(L, "<img unset : %d >", img_dictref(*aa));
687 } else {
688 lua_pushfstring(L, "<img unset : %d >", img_dictref(*aa));
690 } else {
691 if (img_pagename(d) != NULL && strlen(img_pagename(d)) != 0) {
692 lua_pushfstring(L, "<img %s : %s : %d >", img_filename(d), img_pagename(d), img_dictref(*aa));
693 } else {
694 lua_pushfstring(L, "<img %s : %d : %d >", img_filename(d), img_pagenum(d), img_dictref(*aa));
697 return 1;
700 /* this finalizes instance */
702 static int m_img_gc(lua_State * L)
704 image *a, **aa;
705 image_dict *d;
706 aa = (image **) luaL_checkudata(L, 1, TYPE_IMG);
707 a = *aa;
708 d = img_dict(*aa);
709 luaL_unref(L, LUA_REGISTRYINDEX, img_dictref(a));
710 img_luaref(d) -= 1;
711 /* we need to check this */
712 if (!img_is_refered(d)) {
713 xfree(a);
715 /* till here */
716 return 0;
719 /* the instance */
721 static const struct luaL_Reg img_m[] = {
722 {"__index", m_img_get},
723 {"__newindex", m_img_set},
724 {"__mul", m_img_mul},
725 {"__tostring", m_img_print},
726 {"__gc", m_img_gc},
727 {NULL, NULL}
730 /* this finalizes the dict */
732 static int m_img_dict_gc(lua_State * L)
734 image_dict *ad, **add;
735 add = (image_dict **) luaL_checkudata(L, 1, TYPE_IMG_DICT);
736 ad = *add;
737 if (img_luaref(ad) > 0) {
738 luaL_error(L, "disposing image dict that has references");
739 } else {
740 /* we need to check this */
741 if (img_state(ad) < DICT_REFERED) {
742 free_image_dict(ad);
744 /* till here */
746 return 0;
749 /* the (shared) dict */
751 static const struct luaL_Reg img_dict_m[] = {
752 {"__gc", m_img_dict_gc},
753 {NULL, NULL}
756 int luaopen_img(lua_State * L)
758 luaL_newmetatable(L, TYPE_IMG);
759 #ifdef LuajitTeX
760 luaL_register(L, NULL, img_m);
761 luaL_newmetatable(L, TYPE_IMG_DICT);
762 luaL_register(L, NULL, img_dict_m);
763 luaL_register(L, "img", imglib_f);
764 #else
765 luaL_setfuncs(L, img_m, 0);
766 luaL_newmetatable(L, TYPE_IMG_DICT);
767 luaL_setfuncs(L, img_dict_m, 0);
768 luaL_newlib(L, imglib_f);
769 #endif
770 return 1;