12 #include <../lua51/lua.h>
13 #include <../lua51/lauxlib.h>
14 #include <../lua51/lualib.h>
19 #include "mppsout.h" /* for mp_edge_object */
21 #define MPLIB_METATABLE "MPlib"
22 #define MPLIB_FIG_METATABLE "MPlib.fig"
23 #define MPLIB_GR_METATABLE "MPlib.gr"
25 #define mplib_init_S(a) do { \
26 lua_pushliteral(L,#a); \
27 mplib_##a##_ptr = (char *)lua_tostring(L,-1); \
28 mplib_##a##_index = luaL_ref (L,LUA_REGISTRYINDEX); \
31 #define mplib_push_S(a) do { \
32 lua_rawgeti(L,LUA_REGISTRYINDEX,mplib_##a##_index); \
35 #define mplib_is_S(a,i) (mplib_##a##_ptr==(char *)lua_tostring(L,i))
37 #define mplib_make_S(a) \
38 static int mplib_##a##_index = 0; \
39 static char *mplib_##a##_ptr = NULL;
41 mplib_make_S(left_type);
42 mplib_make_S(right_type);
43 mplib_make_S(x_coord);
44 mplib_make_S(y_coord);
47 mplib_make_S(right_x);
48 mplib_make_S(right_y);
49 mplib_make_S(originator);
58 mplib_make_S(linecap);
59 mplib_make_S(linejoin);
60 mplib_make_S(miterlimit);
63 mplib_make_S(postscript);
64 mplib_make_S(prescript);
66 mplib_make_S(transform);
70 void mplib_init_Ses(lua_State *L) {
71 mplib_init_S(left_type);
72 mplib_init_S(right_type);
73 mplib_init_S(x_coord);
74 mplib_init_S(y_coord);
77 mplib_init_S(right_x);
78 mplib_init_S(right_y);
79 mplib_init_S(originator);
88 mplib_init_S(linecap);
89 mplib_init_S(linejoin);
90 mplib_init_S(miterlimit);
93 mplib_init_S(postscript);
94 mplib_init_S(prescript);
96 mplib_init_S(transform);
104 #define xfree(A) if ((A)!=NULL) { free((A)); A = NULL; }
106 #define is_mp(L,b) (MP *)luaL_checkudata(L,b,MPLIB_METATABLE)
107 #define is_fig(L,b) (struct mp_edge_object **)luaL_checkudata(L,b,MPLIB_FIG_METATABLE)
108 #define is_gr_object(L,b) (struct mp_graphic_object **)luaL_checkudata(L,b,MPLIB_GR_METATABLE)
110 /* Enumeration string arrays */
112 static const char *interaction_options[] =
113 { "unknown","batch","nonstop","scroll","errorstop", NULL};
115 static const char *mplib_filetype_names[] =
116 {"term", "error", "mp", "log", "ps", "mem", "tfm", "map", "pfb", "enc", NULL};
118 /* only "endpoint" and "explicit" actually happen in paths,
119 as well as "open" in elliptical pens */
121 static const char *knot_type_enum[] =
122 { "endpoint", "explicit", "given", "curl", "open", "end_cycle" };
124 static const char *knot_originator_enum[] =
125 { "program" ,"user" };
128 /* this looks a bit funny because of the holes */
130 static const char *color_model_enum[] =
131 { NULL, "none", NULL, "grey", NULL, "rgb", NULL, "cmyk", NULL, "uninitialized" };
135 #define FIELD(A) (mplib_is_S(A,field))
137 static const char *fill_fields[] =
138 { "type", "path", "htap", "pen", "color", "linejoin", "miterlimit",
139 "prescript", "postscript", NULL };
141 static const char *stroked_fields[] =
142 { "type", "path", "pen", "color", "linejoin", "miterlimit", "linecap", "dash",
143 "prescript", "postscript", NULL };
145 static const char *text_fields[] =
146 { "type", "text", "dsize", "font", "color", "width", "height", "depth", "transform",
147 "prescript", "postscript", NULL };
149 static const char *special_fields[] =
150 { "type", "prescript", NULL };
152 static const char *start_bounds_fields[] =
153 { "type", "path", NULL };
155 static const char *start_clip_fields[] =
156 { "type", "path", NULL };
158 static const char *stop_bounds_fields[] =
161 static const char *stop_clip_fields[] =
164 static const char *no_fields[] =
168 P_ERROR_LINE, P_HALF_LINE, P_MAX_LINE, P_MAIN_MEMORY,
169 P_HASH_SIZE, P_HASH_PRIME, P_PARAM_SIZE, P_IN_OPEN, P_RANDOM_SEED,
170 P_INTERACTION, P_INI_VERSION, P_TROFF_MODE, P_PRINT_NAMES, P_MEM_NAME,
171 P_JOB_NAME, P_FIND_FILE, P__SENTINEL,
175 const char *name; /* parameter name */
176 mplib_parm_idx idx; /* parameter index */
179 static mplib_parm_struct mplib_parms[] = {
180 {"error_line", P_ERROR_LINE },
181 {"half_error_line", P_HALF_LINE },
182 {"max_print_line", P_MAX_LINE },
183 {"main_memory", P_MAIN_MEMORY },
184 {"hash_size", P_HASH_SIZE },
185 {"hash_prime", P_HASH_PRIME },
186 {"param_size", P_PARAM_SIZE },
187 {"max_in_open", P_IN_OPEN },
188 {"random_seed", P_RANDOM_SEED },
189 {"interaction", P_INTERACTION },
190 {"ini_version", P_INI_VERSION },
191 {"troff_mode", P_TROFF_MODE },
192 {"print_found_names", P_PRINT_NAMES },
193 {"mem_name", P_MEM_NAME },
194 {"job_name", P_JOB_NAME },
195 {"find_file", P_FIND_FILE },
199 typedef struct _FILE_ITEM {
203 typedef struct _FILE_ITEM File;
205 #define make_stream_buf(A) char *A; size_t A##_size; size_t A##_used
207 #define free_stream_buf(A) xfree(mplib_data->A); mplib_data->A##_size = 0; mplib_data->A##_used = 0
209 typedef struct _MPLIB_INSTANCE_DATA {
214 make_stream_buf(term_out);
215 make_stream_buf(error_out);
216 make_stream_buf(log_out);
217 make_stream_buf(ps_out);
219 char *input_data_ptr;
220 size_t input_data_len;
221 struct mp_edge_object *edges ;
223 } _MPLIB_INSTANCE_DATA;
225 typedef struct _MPLIB_INSTANCE_DATA mplib_instance;
227 static mplib_instance *mplib_get_data (MP mp) {
228 return (mplib_instance *)mp->userdata;
231 static mplib_instance *mplib_make_data (void) {
232 mplib_instance *mplib_data = malloc(sizeof(mplib_instance));
233 memset(mplib_data,0,sizeof(mplib_instance));
238 /* Start by defining all the callback routines for the library
239 * except |run_make_mpx| and |run_editor|.
243 char *mplib_find_file (MP mp, char *fname, char *fmode, int ftype) {
244 mplib_instance *mplib_data = mplib_get_data(mp);
245 lua_State *L = mplib_data->LL;
247 lua_getfield(L,LUA_REGISTRYINDEX,"mplib_file_finder");
248 if (lua_isfunction(L,-1)) {
249 char *s = NULL, *x = NULL;
250 lua_pushstring(L, fname);
251 lua_pushstring(L, fmode);
252 if (ftype >= mp_filetype_text) {
253 lua_pushnumber(L, ftype-mp_filetype_text);
255 lua_pushstring(L, mplib_filetype_names[ftype]);
257 if(lua_pcall(L,3,1,0) != 0) {
258 fprintf(stdout,"Error in mp.find_file: %s\n", (char *)lua_tostring(L,-1));
261 x = (char *)lua_tostring(L,-1);
264 lua_pop(L,1); /* pop the string */
269 if (fmode[0] != 'r' || (! access (fname,R_OK)) || ftype) {
270 return strdup(fname);
276 mplib_find_file_function (lua_State *L) {
277 if (! (lua_isfunction(L,-1)|| lua_isnil(L,-1) )) {
278 return 1; /* error */
280 lua_pushstring(L, "mplib_file_finder");
282 lua_rawset(L,LUA_REGISTRYINDEX);
286 void *mplib_open_file(MP mp, char *fname, char *fmode, int ftype) {
287 File *ff = malloc(sizeof (File));
289 mplib_instance *mplib_data = mplib_get_data(mp);
291 if (ftype==mp_filetype_terminal) {
292 if (fmode[0] == 'r') {
295 xfree(mplib_data->term_file_ptr);
297 mplib_data->term_file_ptr = ff->f;
299 } else if (ftype==mp_filetype_error) {
300 xfree(mplib_data->err_file_ptr);
302 mplib_data->err_file_ptr = ff->f;
303 } else if (ftype == mp_filetype_log) {
304 xfree(mplib_data->log_file_ptr);
306 mplib_data->log_file_ptr = ff->f;
307 } else if (ftype == mp_filetype_postscript) {
308 xfree(mplib_data->ps_file_ptr);
310 mplib_data->ps_file_ptr = ff->f;
314 f = mplib_find_file(mp, fname,fmode,ftype);
317 realmode[0] = *fmode;
320 ff->f = fopen(f, realmode);
321 if ((fmode[0] == 'r') && (ff->f == NULL)) {
332 mplib_get_char (void *f, mplib_instance *mplib_data) {
334 if (f==stdin && mplib_data->input_data != NULL) {
335 if (mplib_data->input_data_len==0) {
336 if (mplib_data->input_data_ptr!=NULL)
337 mplib_data->input_data_ptr = NULL;
339 mplib_data->input_data = NULL;
342 mplib_data->input_data_len--;
343 c = *(mplib_data->input_data_ptr)++;
352 mplib_unget_char (void *f, mplib_instance *mplib_data, int c) {
353 if (f==stdin && mplib_data->input_data_ptr != NULL) {
354 mplib_data->input_data_len++;
355 mplib_data->input_data_ptr--;
362 char *mplib_read_ascii_file (MP mp, void *ff, size_t *size) {
366 size_t len = 0, lim = 128;
367 mplib_instance *mplib_data = mplib_get_data(mp);
368 FILE *f = ((File *)ff)->f;
372 c = mplib_get_char(f,mplib_data);
376 if (s==NULL) return NULL;
377 while (c!=EOF && c!='\n' && c!='\r') {
379 s =realloc(s, (lim+(lim>>2)));
380 if (s==NULL) return NULL;
384 c = mplib_get_char(f,mplib_data);
387 c = mplib_get_char(f,mplib_data);
388 if (c!=EOF && c!='\n')
389 mplib_unget_char(f,mplib_data,c);
397 #define APPEND_STRING(a,b) do { \
398 if ((mplib_data->a##_used+strlen(b))>=mplib_data->a##_size) { \
399 mplib_data->a##_size += 256+(mplib_data->a##_size)/5+strlen(b); \
400 mplib_data->a = realloc(mplib_data->a,mplib_data->a##_size); \
402 (void)strcpy(mplib_data->a+mplib_data->a##_used,b); \
403 mplib_data->a##_used += strlen(b); \
406 void mplib_write_ascii_file (MP mp, void *ff, char *s) {
408 void *f = ((File *)ff)->f;
409 mplib_instance *mplib_data = mplib_get_data(mp);
411 if (f==mplib_data->term_file_ptr) {
412 APPEND_STRING(term_out,s);
413 } else if (f==mplib_data->err_file_ptr) {
414 APPEND_STRING(error_out,s);
415 } else if (f==mplib_data->log_file_ptr) {
416 APPEND_STRING(log_out,s);
417 } else if (f==mplib_data->ps_file_ptr) {
418 APPEND_STRING(ps_out,s);
420 fprintf((FILE *)f,s);
426 void mplib_read_binary_file (MP mp, void *ff, void **data, size_t *size) {
430 FILE *f = ((File *)ff)->f;
432 len = fread(*data,1,*size,f);
437 void mplib_write_binary_file (MP mp, void *ff, void *s, size_t size) {
440 FILE *f = ((File *)ff)->f;
447 void mplib_close_file (MP mp, void *ff) {
449 mplib_instance *mplib_data = mplib_get_data(mp);
450 void *f = ((File *)ff)->f;
451 if (f != NULL && f != mplib_data->term_file_ptr && f != mplib_data->err_file_ptr
452 && f != mplib_data->log_file_ptr && f != mplib_data->ps_file_ptr) {
459 int mplib_eof_file (MP mp, void *ff) {
461 mplib_instance *mplib_data = mplib_get_data(mp);
462 FILE *f = ((File *)ff)->f;
465 if (f==stdin && mplib_data->input_data != NULL) {
466 return (mplib_data->input_data_len==0);
473 void mplib_flush_file (MP mp, void *ff) {
479 #define APPEND_TO_EDGES(a) do { \
480 if (mplib_data->edges==NULL) { \
481 mplib_data->edges = hh; \
483 struct mp_edge_object *p = mplib_data->edges; \
484 while (p->_next!=NULL) { p = p->_next; } \
489 void mplib_shipout_backend (MP mp, int h) {
490 struct mp_edge_object *hh = mp_gr_export(mp, h);
492 mplib_instance *mplib_data = mplib_get_data(mp);
499 mplib_setup_file_ops(struct MP_options * options) {
500 options->find_file = mplib_find_file;
501 options->open_file = mplib_open_file;
502 options->close_file = mplib_close_file;
503 options->eof_file = mplib_eof_file;
504 options->flush_file = mplib_flush_file;
505 options->write_ascii_file = mplib_write_ascii_file;
506 options->read_ascii_file = mplib_read_ascii_file;
507 options->write_binary_file = mplib_write_binary_file;
508 options->read_binary_file = mplib_read_binary_file;
509 options->shipout_backend = mplib_shipout_backend;
513 mplib_new (lua_State *L) {
515 mp_ptr = lua_newuserdata(L, sizeof(MP *));
518 mplib_instance *mplib_data;
519 struct MP_options * options; /* instance options */
520 options = mp_options();
521 mplib_setup_file_ops(options);
522 mplib_data = mplib_make_data();
524 options->userdata = (void *)mplib_data;
525 options->noninteractive = 1; /* required ! */
526 options->print_found_names = 0;
527 if (lua_type(L,1)==LUA_TTABLE) {
528 for (i=0;mplib_parms[i].name!=NULL;i++) {
529 lua_getfield(L,1,mplib_parms[i].name);
530 if (lua_isnil(L,-1)) {
532 continue; /* skip unset */
534 switch(mplib_parms[i].idx) {
536 options->error_line = lua_tointeger(L,-1);
539 options->half_error_line = lua_tointeger(L,-1);
542 options->max_print_line = lua_tointeger(L,-1);
545 options->main_memory = lua_tointeger(L,-1);
548 options->hash_size = lua_tointeger(L,-1);
551 options->hash_prime = lua_tointeger(L,-1);
554 options->param_size = lua_tointeger(L,-1);
557 options->max_in_open = lua_tointeger(L,-1);
560 options->random_seed = lua_tointeger(L,-1);
563 options->interaction = luaL_checkoption(L,-1,"errorstopmode", interaction_options);
566 options->ini_version = lua_toboolean(L,-1);
569 options->troff_mode = lua_toboolean(L,-1);
572 options->print_found_names = lua_toboolean(L,-1);
576 options->command_line = strdup((char *)lua_tostring(L,-1));
580 options->mem_name = strdup((char *)lua_tostring(L,-1));
583 options->job_name = strdup((char *)lua_tostring(L,-1));
586 if(mplib_find_file_function(L)) { /* error here */
587 fprintf(stdout,"Invalid arguments to mp.new({find_file=...})\n");
596 *mp_ptr = mp_new(options);
597 xfree(options->command_line);
598 xfree(options->mem_name);
599 xfree(options->job_name);
602 luaL_getmetatable(L,MPLIB_METATABLE);
603 lua_setmetatable(L,-2);
612 mplib_collect (lua_State *L) {
613 MP *mp_ptr = is_mp(L,1);
619 mplib_tostring (lua_State *L) {
620 MP *mp_ptr = is_mp(L,1);
622 lua_pushfstring(L,"<MP %p>",*mp_ptr);
629 mplib_wrapresults(lua_State *L, mplib_instance *mplib_data, int h) {
632 if (mplib_data->term_out != NULL) {
633 lua_pushstring(L,mplib_data->term_out);
634 lua_setfield(L,-2,"term");
635 free_stream_buf(term_out);
637 if (mplib_data->error_out != NULL) {
638 lua_pushstring(L,mplib_data->error_out);
639 lua_setfield(L,-2,"error");
640 free_stream_buf(error_out);
642 if (mplib_data->log_out != NULL ) {
643 lua_pushstring(L,mplib_data->log_out);
644 lua_setfield(L,-2,"log");
645 free_stream_buf(log_out);
647 if (mplib_data->edges != NULL ) {
648 struct mp_edge_object **v;
649 struct mp_edge_object *p = mplib_data->edges;
653 v = lua_newuserdata (L, sizeof(struct mp_edge_object *));
655 luaL_getmetatable(L,MPLIB_FIG_METATABLE);
656 lua_setmetatable(L,-2);
657 lua_rawseti(L,-2,i); i++;
660 lua_setfield(L,-2,"fig");
661 mplib_data->edges = NULL;
664 lua_setfield(L,-2,"status");
669 mplib_execute (lua_State *L) {
670 MP *mp_ptr = is_mp(L,1);
671 if (*mp_ptr!=NULL && lua_isstring(L,2)) {
673 mplib_instance *mplib_data = mplib_get_data(*mp_ptr);
674 mplib_data->input_data = (char *)lua_tolstring(L,2, &(mplib_data->input_data_len));
675 mplib_data->input_data_ptr = mplib_data->input_data;
676 if ((*mp_ptr)->run_state==0) {
677 h = mp_initialize(*mp_ptr);
679 h = mp_execute(*mp_ptr);
680 if (mplib_data->input_data_len!=0) {
681 mplib_data->input_data = NULL;
682 mplib_data->input_data_ptr = NULL;
683 mplib_data->input_data_len=0;
685 return mplib_wrapresults(L, mplib_data, h);
693 mplib_finish (lua_State *L) {
694 MP *mp_ptr = is_mp(L,1);
696 mplib_instance *mplib_data = mplib_get_data(*mp_ptr);
697 int h = mp_finish(*mp_ptr);
698 return mplib_wrapresults(L, mplib_data, h);
708 mplib_fig_collect (lua_State *L) {
709 struct mp_edge_object **hh = is_fig(L,1);
711 mp_gr_toss_objects (*hh);
718 mplib_fig_body (lua_State *L) {
720 struct mp_graphic_object **v;
721 struct mp_graphic_object *p;
722 struct mp_edge_object **hh = is_fig(L,1);
726 v = lua_newuserdata (L, sizeof(struct mp_graphic_object *));
728 luaL_getmetatable(L,MPLIB_GR_METATABLE);
729 lua_setmetatable(L,-2);
730 lua_rawseti(L,-2,i); i++;
733 (*hh)->body = NULL; /* prevent double free */
738 mplib_fig_copy_body (lua_State *L) {
740 struct mp_graphic_object **v;
741 struct mp_graphic_object *p;
742 struct mp_edge_object **hh = is_fig(L,1);
746 v = lua_newuserdata (L, sizeof(struct mp_graphic_object *));
747 *v = mp_gr_copy_object((*hh)->_parent,p);
748 luaL_getmetatable(L,MPLIB_GR_METATABLE);
749 lua_setmetatable(L,-2);
750 lua_rawseti(L,-2,i); i++;
758 mplib_fig_tostring (lua_State *L) {
759 struct mp_edge_object **hh = is_fig(L,1);
760 lua_pushfstring(L,"<figure %p>",*hh);
767 mp_wrapped_shipout (struct mp_edge_object *hh, int prologues, int procset) {
769 if (setjmp(mp->jump_buf)) {
772 mp_gr_ship_out(hh,prologues,procset);
777 mplib_fig_postscript (lua_State *L) {
778 struct mp_edge_object **hh = is_fig(L,1);
779 int prologues = luaL_optnumber(L,2,-1);
780 int procset = luaL_optnumber(L,3,-1);
781 mplib_instance *mplib_data = mplib_get_data((*hh)->_parent);
782 if (mplib_data->ps_out == NULL) {
783 if (mp_wrapped_shipout(*hh,prologues, procset)) {
784 if (mplib_data->ps_out!=NULL ) {
785 lua_pushstring(L, mplib_data->ps_out);
786 free_stream_buf(ps_out);
793 lua_pushstring(L,mplib_data->log_out);
794 xfree(mplib_data->ps_out);
803 mplib_fig_filename (lua_State *L) {
804 struct mp_edge_object **hh = is_fig(L,1);
806 char *s = (*hh)->_filename;
816 mplib_fig_bb (lua_State *L) {
817 struct mp_edge_object **hh = is_fig(L,1);
819 lua_pushnumber(L, (double)(*hh)->_minx/65536.0);
821 lua_pushnumber(L, (double)(*hh)->_miny/65536.0);
823 lua_pushnumber(L, (double)(*hh)->_maxx/65536.0);
825 lua_pushnumber(L, (double)(*hh)->_maxy/65536.0);
833 mplib_gr_collect (lua_State *L) {
834 struct mp_graphic_object **hh = is_gr_object(L,1);
836 mp_gr_toss_object(*hh);
843 mplib_gr_tostring (lua_State *L) {
844 struct mp_graphic_object **hh = is_gr_object(L,1);
845 lua_pushfstring(L,"<object %p>",*hh);
849 #define mplib_push_number(L,x) lua_pushnumber(L,(lua_Number)(x)/65536.0)
855 mplib_push_path (lua_State *L, struct mp_knot *h, int is_pen) {
856 struct mp_knot *p; /* for scanning the path */
862 lua_createtable(L,0,9);
863 mplib_push_S(originator);
864 lua_pushstring(L,knot_originator_enum[p->originator_field]);
866 mplib_push_S(left_type);
867 lua_pushstring(L,(is_pen ? "explicit" : knot_type_enum[p->left_type_field]));
869 mplib_push_S(right_type);
870 lua_pushstring(L,(is_pen ? "explicit" : knot_type_enum[p->right_type_field]));
872 mplib_push_S(x_coord);
873 mplib_push_number(L,p->x_coord_field);
875 mplib_push_S(y_coord);
876 mplib_push_number(L,p->y_coord_field);
878 mplib_push_S(left_x);
879 mplib_push_number(L,p->left_x_field);
881 mplib_push_S(left_y);
882 mplib_push_number(L,p->left_y_field);
884 mplib_push_S(right_x);
885 mplib_push_number(L,p->right_x_field);
887 mplib_push_S(right_y);
888 mplib_push_number(L,p->right_y_field);
890 lua_rawseti(L,-2,i); i++;
891 if ( p->right_type_field==mp_endpoint ) {
901 #define set_color_objects(pq) \
902 object_color_model = pq->color_model_field; \
903 object_color_a = pq->color_field._a_val; \
904 object_color_b = pq->color_field._b_val; \
905 object_color_c = pq->color_field._c_val; \
906 object_color_d = pq->color_field._d_val;
910 mplib_push_color (lua_State *L, struct mp_graphic_object *p ) {
911 int object_color_model;
912 int object_color_a, object_color_b, object_color_c, object_color_d ;
914 if (p->_type_field == mp_fill_code) {
915 mp_fill_object *h = (mp_fill_object *)p;
916 set_color_objects(h);
917 } else if (p->_type_field == mp_stroked_code) {
918 mp_stroked_object *h = (mp_stroked_object *)p;
919 set_color_objects(h);
921 mp_text_object *h = (mp_text_object *)p;
922 set_color_objects(h);
925 lua_pushstring(L,color_model_enum[object_color_model]);
926 lua_setfield(L,-2,"model");
927 if (object_color_model == mp_rgb_model ||
928 object_color_model == mp_uninitialized_model) {
930 mplib_push_number(L,object_color_a);
932 mplib_push_number(L,object_color_b);
934 mplib_push_number(L,object_color_c);
936 lua_setfield(L,-2,"rgb");
939 if (object_color_model == mp_cmyk_model ||
940 object_color_model == mp_uninitialized_model) {
942 mplib_push_number(L,object_color_a);
944 mplib_push_number(L,object_color_b);
946 mplib_push_number(L,object_color_c);
948 mplib_push_number(L,object_color_d);
950 lua_setfield(L,-2,"cmyk");
952 if (object_color_model == mp_grey_model ||
953 object_color_model == mp_uninitialized_model) {
955 mplib_push_number(L,object_color_a);
957 lua_setfield(L,-2,"grey");
965 /* the dash scale is not exported, the field has no external value */
967 mplib_push_dash (lua_State *L, struct mp_stroked_object *h ) {
969 if (h!=NULL && h->dash_p_field != NULL) {
972 mplib_push_number(L,d->offset_field);
973 lua_setfield(L,-2,"offset");
974 if (d->array_field!=NULL ) {
977 while (*(d->array_field+i) != -1) {
978 mplib_push_number(L, *(d->array_field+1));
982 lua_setfield(L,-2,"dashes");
990 mplib_push_transform (lua_State *L, struct mp_text_object *h ) {
993 lua_createtable(L,6,0);
994 mplib_push_number(L,h->tx_field);
995 lua_rawseti(L,-2,i); i++;
996 mplib_push_number(L,h->ty_field);
997 lua_rawseti(L,-2,i); i++;
998 mplib_push_number(L,h->txx_field);
999 lua_rawseti(L,-2,i); i++;
1000 mplib_push_number(L,h->tyx_field);
1001 lua_rawseti(L,-2,i); i++;
1002 mplib_push_number(L,h->txy_field);
1003 lua_rawseti(L,-2,i); i++;
1004 mplib_push_number(L,h->tyy_field);
1005 lua_rawseti(L,-2,i); i++;
1013 mplib_fill_field (lua_State *L, struct mp_fill_object *h, int field) {
1015 lua_pushstring(L,"fill");
1016 } else if (FIELD(path)) {
1017 mplib_push_path(L, h->path_p_field, MPLIB_PATH);
1018 } else if (FIELD(htap)) {
1019 mplib_push_path(L, h->htap_p_field, MPLIB_PATH);
1020 } else if (FIELD(pen)) {
1021 mplib_push_path(L, h->pen_p_field, MPLIB_PEN);
1022 } else if (FIELD(color)) {
1023 mplib_push_color(L,(mp_graphic_object *)h);
1024 } else if (FIELD(linejoin)) {
1025 lua_pushnumber(L,h->ljoin_field);
1026 } else if (FIELD(miterlimit)) {
1027 mplib_push_number(L,h->miterlim_field);
1028 } else if (FIELD(prescript)) {
1029 lua_pushstring(L,h->pre_script_field);
1030 } else if (FIELD(postscript)) {
1031 lua_pushstring(L,h->post_script_field);
1038 mplib_stroked_field (lua_State *L, struct mp_stroked_object *h, int field) {
1040 lua_pushstring(L,"outline");
1041 } else if (FIELD(path)) {
1042 mplib_push_path(L, h->path_p_field, MPLIB_PATH);
1043 } else if (FIELD(pen)) {
1044 mplib_push_path(L, h->pen_p_field, MPLIB_PEN);
1045 } else if (FIELD(color)) {
1046 mplib_push_color(L, (mp_graphic_object *)h);
1047 } else if (FIELD(dash)) {
1048 mplib_push_dash(L,h);
1049 } else if (FIELD(linecap)) {
1050 lua_pushnumber(L,h->lcap_field);
1051 } else if (FIELD(linejoin)) {
1052 lua_pushnumber(L,h->ljoin_field);
1053 } else if (FIELD(miterlimit)) {
1054 mplib_push_number(L,h->miterlim_field);
1055 } else if (FIELD(prescript)) {
1056 lua_pushstring(L,h->pre_script_field);
1057 } else if (FIELD(postscript)) {
1058 lua_pushstring(L,h->post_script_field);
1065 mplib_text_field (lua_State *L, struct mp_text_object *h, int field) {
1068 lua_pushstring(L,"text");
1069 } else if (FIELD(text)) {
1070 lua_pushstring(L,h->text_p_field);
1071 } else if (FIELD(dsize)) {
1072 mplib_push_number(L,(h->font_dsize_field/16));
1073 } else if (FIELD(font)) {
1074 lua_pushstring(L,h->font_name_field);
1075 } else if (FIELD(color)) {
1076 mplib_push_color(L,(mp_graphic_object *)h);
1077 } else if (FIELD(width)) {
1078 mplib_push_number(L,h->width_field);
1079 } else if (FIELD(height)) {
1080 mplib_push_number(L,h->height_field);
1081 } else if (FIELD(depth)) {
1082 mplib_push_number(L,h->depth_field);
1083 } else if (FIELD(transform)) {
1084 mplib_push_transform(L,h);
1085 } else if (FIELD(prescript)) {
1086 lua_pushstring(L,h->pre_script_field);
1087 } else if (FIELD(postscript)) {
1088 lua_pushstring(L,h->post_script_field);
1095 mplib_special_field (lua_State *L, struct mp_special_object *h, int field) {
1097 lua_pushstring(L,"special");
1098 } else if (FIELD(prescript)) {
1099 lua_pushstring(L,h->pre_script_field);
1106 mplib_start_bounds_field (lua_State *L, struct mp_bounds_object *h, int field) {
1108 lua_pushstring(L,"start_bounds");
1109 } else if (FIELD(path)) {
1110 mplib_push_path(L,h->path_p_field, MPLIB_PATH);
1117 mplib_start_clip_field (lua_State *L, struct mp_clip_object *h, int field) {
1119 lua_pushstring(L,"start_clip");
1120 } else if (FIELD(path)) {
1121 mplib_push_path(L,h->path_p_field, MPLIB_PATH);
1128 mplib_stop_bounds_field (lua_State *L, struct mp_graphic_object *h, int field) {
1129 if (h!=NULL && FIELD(type)) {
1130 lua_pushstring(L,"stop_bounds");
1137 mplib_stop_clip_field (lua_State *L, struct mp_graphic_object *h, int field) {
1138 if (h!=NULL && FIELD(type)) {
1139 lua_pushstring(L,"stop_clip");
1146 mplib_gr_fields (lua_State *L) {
1147 const char **fields;
1150 struct mp_graphic_object **hh = is_gr_object(L,1);
1152 switch ((*hh)->_type_field) {
1153 case mp_fill_code: fields = fill_fields; break;
1154 case mp_stroked_code: fields = stroked_fields; break;
1155 case mp_text_code: fields = text_fields; break;
1156 case mp_special_code: fields = special_fields; break;
1157 case mp_start_clip_code: fields = start_clip_fields; break;
1158 case mp_start_bounds_code: fields = start_bounds_fields; break;
1159 case mp_stop_clip_code: fields = stop_clip_fields; break;
1160 case mp_stop_bounds_code: fields = stop_bounds_fields; break;
1161 default: fields = no_fields;
1164 for (f = *fields; f != NULL; f++) {
1165 lua_pushstring(L,f);
1166 lua_rawseti(L,-2,i); i++;
1175 mplib_gr_index (lua_State *L) {
1176 struct mp_graphic_object **hh = is_gr_object(L,1);
1178 struct mp_graphic_object *h = *hh;
1179 switch (h->_type_field) {
1180 case mp_fill_code: mplib_fill_field(L,(mp_fill_object *)h,2); break;
1181 case mp_stroked_code: mplib_stroked_field(L,(mp_stroked_object *)h,2); break;
1182 case mp_text_code: mplib_text_field(L,(mp_text_object *)h,2); break;
1183 case mp_special_code: mplib_special_field(L,(mp_special_object *)h,2); break;
1184 case mp_start_clip_code: mplib_start_clip_field(L,(mp_clip_object *)h,2); break;
1185 case mp_start_bounds_code: mplib_start_bounds_field(L,(mp_bounds_object *)h,2); break;
1186 case mp_stop_clip_code: mplib_stop_clip_field(L,h,2); break;
1187 case mp_stop_bounds_code: mplib_stop_bounds_field(L,h,2); break;
1188 default: lua_pushnil(L);
1197 static const struct luaL_reg mplib_meta[] = {
1198 {"__gc", mplib_collect},
1199 {"__tostring", mplib_tostring},
1200 {NULL, NULL} /* sentinel */
1203 static const struct luaL_reg mplib_fig_meta[] = {
1204 {"__gc", mplib_fig_collect },
1205 {"__tostring", mplib_fig_tostring },
1206 {"objects", mplib_fig_body },
1207 {"copy_objects", mplib_fig_copy_body },
1208 {"filename", mplib_fig_filename },
1209 {"postscript", mplib_fig_postscript },
1210 {"boundingbox", mplib_fig_bb },
1211 {NULL, NULL} /* sentinel */
1214 static const struct luaL_reg mplib_gr_meta[] = {
1215 {"__gc", mplib_gr_collect },
1216 {"__tostring", mplib_gr_tostring },
1217 {"__index", mplib_gr_index },
1218 {"fields", mplib_gr_fields },
1219 {NULL, NULL} /* sentinel */
1223 static const struct luaL_reg mplib_d [] = {
1224 {"execute", mplib_execute },
1225 {"finish", mplib_finish },
1226 {NULL, NULL} /* sentinel */
1230 static const struct luaL_reg mplib_m[] = {
1232 {NULL, NULL} /* sentinel */
1237 luaopen_mp (lua_State *L) {
1239 luaL_newmetatable(L,MPLIB_GR_METATABLE);
1240 lua_pushvalue(L, -1); /* push metatable */
1241 lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
1242 luaL_register(L, NULL, mplib_gr_meta); /* object meta methods */
1245 luaL_newmetatable(L,MPLIB_FIG_METATABLE);
1246 lua_pushvalue(L, -1); /* push metatable */
1247 lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
1248 luaL_register(L, NULL, mplib_fig_meta); /* figure meta methods */
1251 luaL_newmetatable(L,MPLIB_METATABLE);
1252 lua_pushvalue(L, -1); /* push metatable */
1253 lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
1254 luaL_register(L, NULL, mplib_meta); /* meta methods */
1255 luaL_register(L, NULL, mplib_d); /* dict methods */
1256 luaL_register(L, "mplib", mplib_m); /* module functions */