fix getsup (HH)
[luatex.git] / source / texk / web2c / luatexdir / lua / limglib.c
blobe82bf9d5184dde6abb6b7f72ef3a638e92f05f58
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_rawgeti(Luas, LUA_REGISTRYINDEX, (int) i);
302 aa = (image **) luaL_checkudata(Luas, -1, TYPE_IMG);
303 a = *aa;
304 ad = img_dict(a);
305 if (ad == NULL) {
306 luaL_error(Luas, "invalid image dictionary");
308 setup_image(pdf, a, WR_VF_IMG);
309 place_img(pdf, ad, img_dimen(a), img_transform(a));
310 lua_pop(Luas, 1);
313 /* metamethods for image */
315 static int m_img_get(lua_State * L)
317 int j;
318 const char *s;
319 image **a = (image **) luaL_checkudata(L, 1, TYPE_IMG); /* k u */
320 image_dict *d = img_dict(*a);
321 if (d == NULL) {
322 luaL_error(L, "invalid image dictionary");
324 s = lua_tostring(L, 2);
325 if (lua_key_eq(s,width)) {
326 if (is_wd_running(*a)) {
327 lua_pushnil(L);
328 } else {
329 lua_pushinteger(L, img_width(*a));
331 } else if (lua_key_eq(s,height)) {
332 if (is_ht_running(*a)) {
333 lua_pushnil(L);
334 } else {
335 lua_pushinteger(L, img_height(*a));
337 } else if (lua_key_eq(s,depth)) {
338 if (is_dp_running(*a)) {
339 lua_pushnil(L);
340 } else {
341 lua_pushinteger(L, img_depth(*a));
343 } else if (lua_key_eq(s,transform)) {
344 lua_pushinteger(L, img_transform(*a));
345 } else if (lua_key_eq(s,filename)) {
346 if (img_filename(d) == NULL || strlen(img_filename(d)) == 0) {
347 lua_pushnil(L);
348 } else {
349 lua_pushstring(L, img_filename(d));
351 } else if (lua_key_eq(s,visiblefilename)) {
352 if (img_visiblefilename(d) == NULL || strlen(img_visiblefilename(d)) == 0) {
353 lua_pushnil(L);
354 } else {
355 lua_pushstring(L, img_visiblefilename(d));
357 } else if (lua_key_eq(s,keepopen)) {
358 lua_pushboolean(L, img_keepopen(d));
359 } else if (lua_key_eq(s,filepath)) {
360 if (img_filepath(d) == NULL || strlen(img_filepath(d)) == 0) {
361 lua_pushnil(L);
362 } else {
363 lua_pushstring(L, img_filepath(d));
365 } else if (lua_key_eq(s,attr)) {
366 if (img_attr(d) == NULL || strlen(img_attr(d)) == 0) {
367 lua_pushnil(L);
368 } else {
369 lua_pushstring(L, img_attr(d));
371 } else if (lua_key_eq(s,page)) {
372 if (img_pagename(d) != NULL && strlen(img_pagename(d)) != 0) {
373 lua_pushstring(L, img_pagename(d));
374 } else {
375 lua_pushinteger(L, img_pagenum(d));
377 } else if (lua_key_eq(s,pages)) {
378 lua_pushinteger(L, img_totalpages(d));
379 } else if (lua_key_eq(s,xsize)) {
380 if ((img_rotation(d) & 1) == 0) {
381 lua_pushinteger(L, img_xsize(d));
382 } else {
383 lua_pushinteger(L, img_ysize(d));
385 } else if (lua_key_eq(s,ysize)) {
386 if ((img_rotation(d) & 1) == 0) {
387 lua_pushinteger(L, img_ysize(d));
388 } else {
389 lua_pushinteger(L, img_xsize(d));
391 } else if (lua_key_eq(s,xres)) {
392 lua_pushinteger(L, img_xres(d));
393 } else if (lua_key_eq(s,yres)) {
394 lua_pushinteger(L, img_yres(d));
395 } else if (lua_key_eq(s,rotation)) {
396 lua_pushinteger(L, img_rotation(d));
397 } else if (lua_key_eq(s,orientation)) {
398 lua_pushinteger(L, img_orientation(d));
399 } else if (lua_key_eq(s,colorspace)) {
400 if (img_colorspace(d) == 0) {
401 lua_pushnil(L);
402 } else {
403 lua_pushinteger(L, img_colorspace(d));
405 } else if (lua_key_eq(s,colordepth)) {
406 if (img_colordepth(d) == 0) {
407 lua_pushnil(L);
408 } else {
409 lua_pushinteger(L, img_colordepth(d));
411 } else if (lua_key_eq(s,imagetype)) {
412 j = img_type(d);
413 if (j >= 0 && j <= img_types_max) {
414 if (j == IMG_TYPE_NONE) {
415 lua_pushnil(L);
416 } else {
417 lua_pushstring(L, img_types[j]);
419 } else {
420 lua_pushnil(L);
422 } else if (lua_key_eq(s,pagebox)) {
423 j = img_pagebox(d);
424 if (j < 0 || j >= img_pageboxes_max) {
425 j = 0;
427 lua_push_img_pagebox(L, j);
428 } else if (lua_key_eq(s,bbox)) {
429 if (!img_is_bbox(d)) {
430 img_bbox(d)[0] = img_xorig(d);
431 img_bbox(d)[1] = img_yorig(d);
432 img_bbox(d)[2] = img_xorig(d) + img_xsize(d);
433 img_bbox(d)[3] = img_yorig(d) + img_ysize(d);
435 lua_newtable(L);
436 lua_pushinteger(L, 1);
437 lua_pushinteger(L, img_bbox(d)[0]);
438 lua_settable(L, -3);
439 lua_pushinteger(L, 2);
440 lua_pushinteger(L, img_bbox(d)[1]);
441 lua_settable(L, -3);
442 lua_pushinteger(L, 3);
443 lua_pushinteger(L, img_bbox(d)[2]);
444 lua_settable(L, -3);
445 lua_pushinteger(L, 4);
446 lua_pushinteger(L, img_bbox(d)[3]);
447 lua_settable(L, -3);
448 } else if (lua_key_eq(s,objnum)) {
449 if (img_objnum(d) == 0) {
450 lua_pushnil(L);
451 } else {
452 lua_pushinteger(L, img_objnum(d));
454 } else if (lua_key_eq(s,index)) {
455 if (img_index(d) == 0) {
456 lua_pushnil(L);
457 } else {
458 lua_pushinteger(L, img_index(d));
460 } else if (lua_key_eq(s,stream)) {
461 if (img_type(d) != IMG_TYPE_PDFSTREAM
462 || img_pdfstream_ptr(d) == NULL
463 || img_pdfstream_stream(d) == NULL
464 || strlen(img_pdfstream_stream(d)) == 0) {
465 lua_pushnil(L);
466 } else {
467 lua_pushstring(L, img_pdfstream_stream(d));
469 } else if (lua_key_eq(s,ref_count)) {
470 lua_pushinteger(L, img_luaref(d));
471 } else {
472 lua_pushnil(L);
474 return 1;
477 static void lua_to_image(lua_State * L, image * a, image_dict * d)
479 int i, t;
480 const char *s;
481 s = lua_tostring(L,-2);
482 t = lua_type(L, -1);
483 if (lua_key_eq(s,width)) {
484 if (t == LUA_TNIL) {
485 set_wd_running(a);
486 } else if (t == LUA_TNUMBER) {
487 img_width(a) = (int) lua_roundnumber(L, -1);
488 } else if (t == LUA_TSTRING) {
489 img_width(a) = dimen_to_number(L, lua_tostring(L, -1));
490 } else {
491 luaL_error(L, "image.width needs integer or nil value or dimension string");
493 } else if (lua_key_eq(s,height)) {
494 if (t == LUA_TNIL) {
495 set_ht_running(a);
496 } else if (t == LUA_TNUMBER) {
497 img_height(a) = (int) lua_roundnumber(L, -1);
498 } else if (t == LUA_TSTRING) {
499 img_height(a) = dimen_to_number(L, lua_tostring(L, -1));
500 } else {
501 luaL_error(L, "image.height needs integer or nil value or dimension string");
503 } else if (lua_key_eq(s,depth)) {
504 if (t == LUA_TNIL) {
505 set_dp_running(a);
506 } else if (t == LUA_TNUMBER) {
507 img_depth(a) = (int) lua_roundnumber(L, -1);
508 } else if (t == LUA_TSTRING) {
509 img_depth(a) = dimen_to_number(L, lua_tostring(L, -1));
510 } else {
511 luaL_error(L, "image.depth needs integer or nil value or dimension string");
513 } else if (lua_key_eq(s,transform)) {
514 if (t == LUA_TNUMBER) {
515 img_transform(a) = (int) lua_tointeger(L, -1);
516 } else {
517 luaL_error(L, "image.transform needs integer value");
519 } else if (lua_key_eq(s,filename)) {
520 if (img_state(d) >= DICT_FILESCANNED) {
521 luaL_error(L, "image.filename is now read-only");
522 } else if (img_type(d) == IMG_TYPE_PDFSTREAM) {
523 luaL_error(L, "image.filename can't be used with image.stream");
524 } else if (t == LUA_TSTRING) {
525 xfree(img_filename(d));
526 img_filename(d) = xstrdup(lua_tostring(L, -1));
527 } else {
528 luaL_error(L, "image.filename needs string value");
530 } else if (lua_key_eq(s,visiblefilename)) {
531 if (img_state(d) >= DICT_FILESCANNED) {
532 luaL_error(L, "image.visiblefilename is now read-only");
533 } else if (img_type(d) == IMG_TYPE_PDFSTREAM) {
534 luaL_error(L, "image.visiblefilename can't be used with image.stream");
535 } else if (t == LUA_TSTRING) {
536 xfree(img_visiblefilename(d));
537 img_visiblefilename(d) = xstrdup(lua_tostring(L, -1));
538 } else {
539 luaL_error(L, "image.visiblefilename needs string value");
541 } else if (lua_key_eq(s,attr)) {
542 if (img_state(d) >= DICT_FILESCANNED) {
543 luaL_error(L, "image.attr is now read-only");
544 } else if (t == LUA_TSTRING) {
545 xfree(img_attr(d));
546 img_attr(d) = xstrdup(lua_tostring(L, -1));
547 } else if (t == LUA_TNIL) {
548 xfree(img_attr(d));
549 } else {
550 luaL_error(L, "image.attr needs string or nil value");
552 } else if (lua_key_eq(s,page)) {
553 if (img_state(d) >= DICT_FILESCANNED) {
554 luaL_error(L, "image.page is now read-only");
555 } else if (t == LUA_TSTRING) {
556 xfree(img_pagename(d));
557 img_pagename(d) = xstrdup(lua_tostring(L, -1));
558 img_pagenum(d) = 0;
559 } else if (t == LUA_TNUMBER) {
560 img_pagenum(d) = (int) lua_tointeger(L, -1);
561 xfree(img_pagename(d));
562 } else {
563 luaL_error(L, "image.page needs integer or string value");
565 } else if (lua_key_eq(s,colorspace)) {
566 if (img_state(d) >= DICT_FILESCANNED) {
567 luaL_error(L, "image.colorspace is now read-only");
568 } else if (t == LUA_TNIL) {
569 img_colorspace(d) = 0;
570 } else if (t == LUA_TNUMBER) {
571 img_colorspace(d) = (int) lua_tointeger(L, -1);
572 } else {
573 luaL_error(L, "image.colorspace needs integer or nil value");
575 } else if (lua_key_eq(s,pagebox)) {
576 if (img_state(d) >= DICT_FILESCANNED) {
577 luaL_error(L, "image.pagebox is now read-only");
578 } else if (t == LUA_TNIL) {
579 img_pagebox(d) = PDF_BOX_SPEC_MEDIA;
580 } else if (t == LUA_TNUMBER) {
581 i = lua_tointeger(L,-1);
582 if (i < 0 || i >= img_pageboxes_max) {
583 img_pagebox(d) = PDF_BOX_SPEC_MEDIA;
584 } else {
585 img_pagebox(d) = i;
587 } else if (t == LUA_TSTRING) {
588 img_pagebox(d) = PDF_BOX_SPEC_MEDIA;
589 for (i = 0; i < img_pageboxes_max; i++) {
590 lua_rawgeti(L, LUA_REGISTRYINDEX, img_pageboxes[i]);
591 if (lua_rawequal(L,-1,-2)) {
592 img_pagebox(d) = i;
593 lua_pop(L, 1);
594 break;
595 } else {
596 lua_pop(L, 1);
599 } else {
600 luaL_error(L, "image.pagebox needs string, number or nil value");
602 } else if (lua_key_eq(s,keepopen)) {
603 if (img_state(d) >= DICT_FILESCANNED) {
604 luaL_error(L, "image.keepopen is now read-only");
605 } else if (t != LUA_TBOOLEAN) {
606 luaL_error(L, "image.bbox needs boolean value");
607 } else {
608 img_keepopen(d) = lua_toboolean(L, -1);
610 } else if (lua_key_eq(s,bbox)) {
611 if (img_state(d) >= DICT_FILESCANNED) {
612 luaL_error(L, "image.bbox is now read-only");
613 } else if (t != LUA_TTABLE) {
614 luaL_error(L, "image.bbox needs table value");
615 } else if (lua_rawlen(L, -1) != 4) {
616 luaL_error(L, "image.bbox table must have exactly 4 elements");
617 } else {
618 for (i = 1; i <= 4; i++) { /* v k t ... */
619 lua_pushinteger(L, i); /* idx v k t ... */
620 lua_gettable(L, -2); /* int v k t ... */
621 t = lua_type(L, -1);
622 if (t == LUA_TNUMBER) {
623 img_bbox(d)[i - 1] = (int) lua_roundnumber(L, -1);
624 } else if (t == LUA_TSTRING) {
625 img_bbox(d)[i - 1] = dimen_to_number(L, lua_tostring(L, -1));
626 } else {
627 luaL_error(L, "image.bbox table needs integer value or dimension string elements");
629 lua_pop(L, 1); /* v k t ... */
631 img_set_bbox(d);
633 } else if (lua_key_eq(s,stream)) {
634 if (img_filename(d) != NULL) {
635 luaL_error(L, "image.stream can't be used with image.filename");
636 } else if (img_state(d) >= DICT_FILESCANNED) {
637 luaL_error(L, "image.stream is now read-only");
638 } else {
639 if (img_pdfstream_ptr(d) == NULL) {
640 new_img_pdfstream_struct(d);
642 xfree(img_pdfstream_stream(d));
643 img_pdfstream_stream(d) = xstrdup(lua_tostring(L, -1));
644 img_type(d) = IMG_TYPE_PDFSTREAM;
646 } else {
647 luaL_error(L, "image.%s can not be set", s);
651 static int m_img_set(lua_State * L)
653 image **a = (image **) luaL_checkudata(L, 1, TYPE_IMG); /* v k u */
654 image_dict *d = img_dict(*a);
655 if (d == NULL) {
656 luaL_error(L, "invalid image dictionary");
657 } else {
658 lua_to_image(L, *a, d);
660 return 0;
663 static int m_img_mul(lua_State * L)
665 lua_Number scale;
666 if (lua_type(L, 1) == LUA_TNUMBER) { /* u? n */
667 (void) luaL_checkudata(L, 2, TYPE_IMG); /* u n */
668 lua_insert(L, -2); /* n a */
669 } else if (lua_type(L, 2) != LUA_TNUMBER) { /* n u? */
670 (void) luaL_checkudata(L, 1, TYPE_IMG); /* n a */
671 } /* n a */
672 scale = lua_tonumber(L, 2); /* float */ /* n a */
673 lua_pop(L, 1); /* a */
674 copy_image(L, scale); /* b */
675 return 1;
678 static int m_img_print(lua_State * L)
680 image **aa;
681 image_dict *d;
682 aa = (image **) luaL_checkudata(L, 1, TYPE_IMG);
683 d = img_dict(*aa);
684 /* formatted a bit like a node */
685 if (img_filename(d) == NULL) {
686 if (img_pagename(d) != NULL && strlen(img_pagename(d)) != 0) {
687 lua_pushfstring(L, "<img unset : %d >", img_dictref(*aa));
688 } else {
689 lua_pushfstring(L, "<img unset : %d >", img_dictref(*aa));
691 } else {
692 if (img_pagename(d) != NULL && strlen(img_pagename(d)) != 0) {
693 lua_pushfstring(L, "<img %s : %s : %d >", img_filename(d), img_pagename(d), img_dictref(*aa));
694 } else {
695 lua_pushfstring(L, "<img %s : %d : %d >", img_filename(d), img_pagenum(d), img_dictref(*aa));
698 return 1;
701 /* this finalizes instance */
703 static int m_img_gc(lua_State * L)
705 image *a, **aa;
706 image_dict *d;
707 aa = (image **) luaL_checkudata(L, 1, TYPE_IMG);
708 a = *aa;
709 d = img_dict(*aa);
710 luaL_unref(L, LUA_REGISTRYINDEX, img_dictref(a));
711 img_luaref(d) -= 1;
712 /* we need to check this */
713 if (!img_is_refered(d)) {
714 xfree(a);
716 /* till here */
717 return 0;
720 /* the instance */
722 static const struct luaL_Reg img_m[] = {
723 {"__index", m_img_get},
724 {"__newindex", m_img_set},
725 {"__mul", m_img_mul},
726 {"__tostring", m_img_print},
727 {"__gc", m_img_gc},
728 {NULL, NULL}
731 /* this finalizes the dict */
733 static int m_img_dict_gc(lua_State * L)
735 image_dict *ad, **add;
736 add = (image_dict **) luaL_checkudata(L, 1, TYPE_IMG_DICT);
737 ad = *add;
738 if (img_luaref(ad) > 0) {
739 luaL_error(L, "disposing image dict that has references");
740 } else {
741 /* we need to check this */
742 if (img_state(ad) < DICT_REFERED) {
743 free_image_dict(ad);
745 /* till here */
747 return 0;
750 /* the (shared) dict */
752 static const struct luaL_Reg img_dict_m[] = {
753 {"__gc", m_img_dict_gc},
754 {NULL, NULL}
757 int luaopen_img(lua_State * L)
759 luaL_newmetatable(L, TYPE_IMG);
760 #ifdef LuajitTeX
761 luaL_register(L, NULL, img_m);
762 luaL_newmetatable(L, TYPE_IMG_DICT);
763 luaL_register(L, NULL, img_dict_m);
764 luaL_register(L, "img", imglib_f);
765 #else
766 luaL_setfuncs(L, img_m, 0);
767 luaL_newmetatable(L, TYPE_IMG_DICT);
768 luaL_setfuncs(L, img_dict_m, 0);
769 luaL_newlib(L, imglib_f);
770 #endif
771 return 1;