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 static int mplib_type_Ses[mp_special_code+1] = {0}; /* [0] is not used */
44 mplib_make_S(outline);
46 mplib_make_S(special);
47 mplib_make_S(start_bounds);
48 mplib_make_S(stop_bounds);
49 mplib_make_S(start_clip);
50 mplib_make_S(stop_clip);
52 mplib_make_S(left_type);
53 mplib_make_S(right_type);
54 mplib_make_S(x_coord);
55 mplib_make_S(y_coord);
58 mplib_make_S(right_x);
59 mplib_make_S(right_y);
68 mplib_make_S(linecap);
69 mplib_make_S(linejoin);
70 mplib_make_S(miterlimit);
73 mplib_make_S(postscript);
74 mplib_make_S(prescript);
75 mplib_make_S(transform);
79 void mplib_init_Ses(lua_State *L) {
81 mplib_init_S(outline);
83 mplib_init_S(start_bounds);
84 mplib_init_S(stop_bounds);
85 mplib_init_S(start_clip);
86 mplib_init_S(stop_clip);
87 mplib_init_S(special);
89 mplib_type_Ses[mp_fill_code] = mplib_fill_index;
90 mplib_type_Ses[mp_stroked_code] = mplib_outline_index;
91 mplib_type_Ses[mp_text_code] = mplib_text_index;
92 mplib_type_Ses[mp_start_bounds_code] = mplib_start_bounds_index;
93 mplib_type_Ses[mp_stop_bounds_code] = mplib_stop_bounds_index;
94 mplib_type_Ses[mp_start_clip_code] = mplib_start_clip_index;
95 mplib_type_Ses[mp_stop_clip_code] = mplib_stop_clip_index;
96 mplib_type_Ses[mp_special_code] = mplib_special_index;
98 mplib_init_S(left_type);
99 mplib_init_S(right_type);
100 mplib_init_S(x_coord);
101 mplib_init_S(y_coord);
102 mplib_init_S(left_x);
103 mplib_init_S(left_y);
104 mplib_init_S(right_x);
105 mplib_init_S(right_y);
112 mplib_init_S(height);
114 mplib_init_S(linecap);
115 mplib_init_S(linejoin);
116 mplib_init_S(miterlimit);
119 mplib_init_S(postscript);
120 mplib_init_S(prescript);
121 mplib_init_S(transform);
129 #define xfree(A) if ((A)!=NULL) { free((A)); A = NULL; }
131 #define is_mp(L,b) (MP *)luaL_checkudata(L,b,MPLIB_METATABLE)
132 #define is_fig(L,b) (struct mp_edge_object **)luaL_checkudata(L,b,MPLIB_FIG_METATABLE)
133 #define is_gr_object(L,b) (struct mp_graphic_object **)luaL_checkudata(L,b,MPLIB_GR_METATABLE)
135 /* Enumeration string arrays */
137 static const char *interaction_options[] =
138 { "unknown","batch","nonstop","scroll","errorstop", NULL};
140 static const char *mplib_filetype_names[] =
141 {"term", "error", "mp", "log", "ps", "mem", "tfm", "map", "pfb", "enc", NULL};
143 /* only "endpoint" and "explicit" actually happen in paths,
144 as well as "open" in elliptical pens */
146 static const char *knot_type_enum[] =
147 { "endpoint", "explicit", "given", "curl", "open", "end_cycle" };
151 static const char *fill_fields[] =
152 { "type", "path", "htap", "pen", "color", "linejoin", "miterlimit",
153 "prescript", "postscript", NULL };
155 static const char *stroked_fields[] =
156 { "type", "path", "pen", "color", "linejoin", "miterlimit", "linecap", "dash",
157 "prescript", "postscript", NULL };
159 static const char *text_fields[] =
160 { "type", "text", "dsize", "font", "color", "width", "height", "depth", "transform",
161 "prescript", "postscript", NULL };
163 static const char *special_fields[] =
164 { "type", "prescript", NULL };
166 static const char *start_bounds_fields[] =
167 { "type", "path", NULL };
169 static const char *start_clip_fields[] =
170 { "type", "path", NULL };
172 static const char *stop_bounds_fields[] =
175 static const char *stop_clip_fields[] =
178 static const char *no_fields[] =
182 P_ERROR_LINE, P_HALF_LINE, P_MAX_LINE, P_MAIN_MEMORY,
183 P_HASH_SIZE, P_HASH_PRIME, P_PARAM_SIZE, P_IN_OPEN, P_RANDOM_SEED,
184 P_INTERACTION, P_INI_VERSION, P_TROFF_MODE, P_PRINT_NAMES, P_MEM_NAME,
185 P_JOB_NAME, P_FIND_FILE, P__SENTINEL
189 const char *name; /* parameter name */
190 mplib_parm_idx idx; /* parameter index */
193 static mplib_parm_struct mplib_parms[] = {
194 {"error_line", P_ERROR_LINE },
195 {"half_error_line", P_HALF_LINE },
196 {"max_print_line", P_MAX_LINE },
197 {"main_memory", P_MAIN_MEMORY },
198 {"hash_size", P_HASH_SIZE },
199 {"hash_prime", P_HASH_PRIME },
200 {"param_size", P_PARAM_SIZE },
201 {"max_in_open", P_IN_OPEN },
202 {"random_seed", P_RANDOM_SEED },
203 {"interaction", P_INTERACTION },
204 {"ini_version", P_INI_VERSION },
205 {"troff_mode", P_TROFF_MODE },
206 {"print_found_names", P_PRINT_NAMES },
207 {"mem_name", P_MEM_NAME },
208 {"job_name", P_JOB_NAME },
209 {"find_file", P_FIND_FILE },
213 typedef struct _FILE_ITEM {
217 typedef struct _FILE_ITEM File;
219 #define make_stream_buf(A) char *A; size_t A##_size; size_t A##_used
221 #define free_stream_buf(A) xfree(mplib_data->A); mplib_data->A##_size = 0; mplib_data->A##_used = 0
223 typedef struct _MPLIB_INSTANCE_DATA {
228 make_stream_buf(term_out);
229 make_stream_buf(error_out);
230 make_stream_buf(log_out);
231 make_stream_buf(ps_out);
233 char *input_data_ptr;
234 size_t input_data_len;
235 struct mp_edge_object *edges ;
237 } _MPLIB_INSTANCE_DATA;
239 typedef struct _MPLIB_INSTANCE_DATA mplib_instance;
241 static mplib_instance *mplib_get_data (MP mp) {
242 return (mplib_instance *)mp->userdata;
245 static mplib_instance *mplib_make_data (void) {
246 mplib_instance *mplib_data = malloc(sizeof(mplib_instance));
247 memset(mplib_data,0,sizeof(mplib_instance));
252 /* Start by defining all the callback routines for the library
253 * except |run_make_mpx| and |run_editor|.
257 char *mplib_find_file (MP mp, const char *fname, const char *fmode, int ftype) {
258 mplib_instance *mplib_data = mplib_get_data(mp);
259 lua_State *L = mplib_data->LL;
261 lua_getfield(L,LUA_REGISTRYINDEX,"mplib_file_finder");
262 if (lua_isfunction(L,-1)) {
263 char *s = NULL, *x = NULL;
264 lua_pushstring(L, fname);
265 lua_pushstring(L, fmode);
266 if (ftype >= mp_filetype_text) {
267 lua_pushnumber(L, ftype-mp_filetype_text);
269 lua_pushstring(L, mplib_filetype_names[ftype]);
271 if(lua_pcall(L,3,1,0) != 0) {
272 fprintf(stdout,"Error in mp.find_file: %s\n", (char *)lua_tostring(L,-1));
275 x = (char *)lua_tostring(L,-1);
278 lua_pop(L,1); /* pop the string */
283 if (fmode[0] != 'r' || (! access (fname,R_OK)) || ftype) {
284 return strdup(fname);
290 mplib_find_file_function (lua_State *L) {
291 if (! (lua_isfunction(L,-1)|| lua_isnil(L,-1) )) {
292 return 1; /* error */
294 lua_pushstring(L, "mplib_file_finder");
296 lua_rawset(L,LUA_REGISTRYINDEX);
300 void *mplib_open_file(MP mp, const char *fname, const char *fmode, int ftype) {
301 File *ff = malloc(sizeof (File));
303 mplib_instance *mplib_data = mplib_get_data(mp);
305 if (ftype==mp_filetype_terminal) {
306 if (fmode[0] == 'r') {
309 xfree(mplib_data->term_file_ptr);
311 mplib_data->term_file_ptr = ff->f;
313 } else if (ftype==mp_filetype_error) {
314 xfree(mplib_data->err_file_ptr);
316 mplib_data->err_file_ptr = ff->f;
317 } else if (ftype == mp_filetype_log) {
318 xfree(mplib_data->log_file_ptr);
320 mplib_data->log_file_ptr = ff->f;
321 } else if (ftype == mp_filetype_postscript) {
322 xfree(mplib_data->ps_file_ptr);
324 mplib_data->ps_file_ptr = ff->f;
327 char *f = mplib_find_file(mp, fname,fmode,ftype);
330 realmode[0] = *fmode;
333 ff->f = fopen(f, realmode);
334 if ((fmode[0] == 'r') && (ff->f == NULL)) {
345 mplib_get_char (void *f, mplib_instance *mplib_data) {
347 if (f==stdin && mplib_data->input_data != NULL) {
348 if (mplib_data->input_data_len==0) {
349 if (mplib_data->input_data_ptr!=NULL)
350 mplib_data->input_data_ptr = NULL;
352 mplib_data->input_data = NULL;
355 mplib_data->input_data_len--;
356 c = *(mplib_data->input_data_ptr)++;
365 mplib_unget_char (void *f, mplib_instance *mplib_data, int c) {
366 if (f==stdin && mplib_data->input_data_ptr != NULL) {
367 mplib_data->input_data_len++;
368 mplib_data->input_data_ptr--;
375 char *mplib_read_ascii_file (MP mp, void *ff, size_t *size) {
379 size_t len = 0, lim = 128;
380 mplib_instance *mplib_data = mplib_get_data(mp);
381 FILE *f = ((File *)ff)->f;
385 c = mplib_get_char(f,mplib_data);
389 if (s==NULL) return NULL;
390 while (c!=EOF && c!='\n' && c!='\r') {
392 s =realloc(s, (lim+(lim>>2)));
393 if (s==NULL) return NULL;
397 c = mplib_get_char(f,mplib_data);
400 c = mplib_get_char(f,mplib_data);
401 if (c!=EOF && c!='\n')
402 mplib_unget_char(f,mplib_data,c);
410 #define APPEND_STRING(a,b) do { \
411 if ((mplib_data->a##_used+strlen(b))>=mplib_data->a##_size) { \
412 mplib_data->a##_size += 256+(mplib_data->a##_size)/5+strlen(b); \
413 mplib_data->a = realloc(mplib_data->a,mplib_data->a##_size); \
415 (void)strcpy(mplib_data->a+mplib_data->a##_used,b); \
416 mplib_data->a##_used += strlen(b); \
419 void mplib_write_ascii_file (MP mp, void *ff, const char *s) {
421 void *f = ((File *)ff)->f;
422 mplib_instance *mplib_data = mplib_get_data(mp);
424 if (f==mplib_data->term_file_ptr) {
425 APPEND_STRING(term_out,s);
426 } else if (f==mplib_data->err_file_ptr) {
427 APPEND_STRING(error_out,s);
428 } else if (f==mplib_data->log_file_ptr) {
429 APPEND_STRING(log_out,s);
430 } else if (f==mplib_data->ps_file_ptr) {
431 APPEND_STRING(ps_out,s);
433 fprintf((FILE *)f,s);
439 void mplib_read_binary_file (MP mp, void *ff, void **data, size_t *size) {
443 FILE *f = ((File *)ff)->f;
445 len = fread(*data,1,*size,f);
450 void mplib_write_binary_file (MP mp, void *ff, void *s, size_t size) {
453 FILE *f = ((File *)ff)->f;
460 void mplib_close_file (MP mp, void *ff) {
462 mplib_instance *mplib_data = mplib_get_data(mp);
463 void *f = ((File *)ff)->f;
464 if (f != NULL && f != mplib_data->term_file_ptr && f != mplib_data->err_file_ptr
465 && f != mplib_data->log_file_ptr && f != mplib_data->ps_file_ptr) {
472 int mplib_eof_file (MP mp, void *ff) {
474 mplib_instance *mplib_data = mplib_get_data(mp);
475 FILE *f = ((File *)ff)->f;
478 if (f==stdin && mplib_data->input_data != NULL) {
479 return (mplib_data->input_data_len==0);
486 void mplib_flush_file (MP mp, void *ff) {
492 #define APPEND_TO_EDGES(a) do { \
493 if (mplib_data->edges==NULL) { \
494 mplib_data->edges = hh; \
496 struct mp_edge_object *p = mplib_data->edges; \
497 while (p->_next!=NULL) { p = p->_next; } \
502 void mplib_shipout_backend (MP mp, int h) {
503 struct mp_edge_object *hh = mp_gr_export(mp, h);
505 mplib_instance *mplib_data = mplib_get_data(mp);
512 mplib_setup_file_ops(struct MP_options * options) {
513 options->find_file = mplib_find_file;
514 options->open_file = mplib_open_file;
515 options->close_file = mplib_close_file;
516 options->eof_file = mplib_eof_file;
517 options->flush_file = mplib_flush_file;
518 options->write_ascii_file = mplib_write_ascii_file;
519 options->read_ascii_file = mplib_read_ascii_file;
520 options->write_binary_file = mplib_write_binary_file;
521 options->read_binary_file = mplib_read_binary_file;
522 options->shipout_backend = mplib_shipout_backend;
526 mplib_new (lua_State *L) {
528 mp_ptr = lua_newuserdata(L, sizeof(MP *));
531 mplib_instance *mplib_data;
532 struct MP_options * options; /* instance options */
533 options = mp_options();
534 mplib_setup_file_ops(options);
535 mplib_data = mplib_make_data();
537 options->userdata = (void *)mplib_data;
538 options->noninteractive = 1; /* required ! */
539 options->print_found_names = 0;
540 if (lua_type(L,1)==LUA_TTABLE) {
541 for (i=0;mplib_parms[i].name!=NULL;i++) {
542 lua_getfield(L,1,mplib_parms[i].name);
543 if (lua_isnil(L,-1)) {
545 continue; /* skip unset */
547 switch(mplib_parms[i].idx) {
549 options->error_line = lua_tointeger(L,-1);
552 options->half_error_line = lua_tointeger(L,-1);
555 options->max_print_line = lua_tointeger(L,-1);
558 options->main_memory = lua_tointeger(L,-1);
561 options->hash_size = lua_tointeger(L,-1);
564 options->hash_prime = lua_tointeger(L,-1);
567 options->param_size = lua_tointeger(L,-1);
570 options->max_in_open = lua_tointeger(L,-1);
573 options->random_seed = lua_tointeger(L,-1);
576 options->interaction = luaL_checkoption(L,-1,"errorstopmode", interaction_options);
579 options->ini_version = lua_toboolean(L,-1);
582 options->troff_mode = lua_toboolean(L,-1);
585 options->print_found_names = lua_toboolean(L,-1);
589 options->command_line = strdup((char *)lua_tostring(L,-1));
593 options->mem_name = strdup((char *)lua_tostring(L,-1));
596 options->job_name = strdup((char *)lua_tostring(L,-1));
599 if(mplib_find_file_function(L)) { /* error here */
600 fprintf(stdout,"Invalid arguments to mp.new({find_file=...})\n");
609 *mp_ptr = mp_new(options);
610 xfree(options->command_line);
611 xfree(options->mem_name);
612 xfree(options->job_name);
615 luaL_getmetatable(L,MPLIB_METATABLE);
616 lua_setmetatable(L,-2);
625 mplib_collect (lua_State *L) {
626 MP *mp_ptr = is_mp(L,1);
632 mplib_tostring (lua_State *L) {
633 MP *mp_ptr = is_mp(L,1);
635 lua_pushfstring(L,"<MP %p>",*mp_ptr);
642 mplib_wrapresults(lua_State *L, mplib_instance *mplib_data, int h) {
645 if (mplib_data->term_out != NULL) {
646 lua_pushstring(L,mplib_data->term_out);
647 lua_setfield(L,-2,"term");
648 free_stream_buf(term_out);
650 if (mplib_data->error_out != NULL) {
651 lua_pushstring(L,mplib_data->error_out);
652 lua_setfield(L,-2,"error");
653 free_stream_buf(error_out);
655 if (mplib_data->log_out != NULL ) {
656 lua_pushstring(L,mplib_data->log_out);
657 lua_setfield(L,-2,"log");
658 free_stream_buf(log_out);
660 if (mplib_data->edges != NULL ) {
661 struct mp_edge_object **v;
662 struct mp_edge_object *p = mplib_data->edges;
666 v = lua_newuserdata (L, sizeof(struct mp_edge_object *));
668 luaL_getmetatable(L,MPLIB_FIG_METATABLE);
669 lua_setmetatable(L,-2);
670 lua_rawseti(L,-2,i); i++;
673 lua_setfield(L,-2,"fig");
674 mplib_data->edges = NULL;
677 lua_setfield(L,-2,"status");
682 mplib_execute (lua_State *L) {
683 MP *mp_ptr = is_mp(L,1);
684 if (*mp_ptr!=NULL && lua_isstring(L,2)) {
686 mplib_instance *mplib_data = mplib_get_data(*mp_ptr);
687 mplib_data->input_data = (char *)lua_tolstring(L,2, &(mplib_data->input_data_len));
688 mplib_data->input_data_ptr = mplib_data->input_data;
689 if ((*mp_ptr)->run_state==0) {
690 h = mp_initialize(*mp_ptr);
692 h = mp_execute(*mp_ptr);
693 if (mplib_data->input_data_len!=0) {
694 mplib_data->input_data = NULL;
695 mplib_data->input_data_ptr = NULL;
696 mplib_data->input_data_len=0;
698 return mplib_wrapresults(L, mplib_data, h);
706 mplib_finish (lua_State *L) {
707 MP *mp_ptr = is_mp(L,1);
709 mplib_instance *mplib_data = mplib_get_data(*mp_ptr);
710 int h = mp_finish(*mp_ptr);
711 return mplib_wrapresults(L, mplib_data, h);
719 mplib_statistics (lua_State *L) {
720 MP *mp_ptr = is_mp(L,1);
723 lua_pushnumber(L, mp_memory_usage (*mp_ptr));
724 lua_setfield(L,-2,"main_memory");
725 lua_pushnumber(L, mp_hash_usage (*mp_ptr));
726 lua_setfield(L,-2,"hash_size");
727 lua_pushnumber(L, mp_param_usage (*mp_ptr));
728 lua_setfield(L,-2,"param_size");
729 lua_pushnumber(L, mp_open_usage (*mp_ptr));
730 lua_setfield(L,-2,"max_in_open");
741 mplib_fig_collect (lua_State *L) {
742 struct mp_edge_object **hh = is_fig(L,1);
744 mp_gr_toss_objects (*hh);
751 mplib_fig_body (lua_State *L) {
753 struct mp_graphic_object **v;
754 struct mp_graphic_object *p;
755 struct mp_edge_object **hh = is_fig(L,1);
759 v = lua_newuserdata (L, sizeof(struct mp_graphic_object *));
761 luaL_getmetatable(L,MPLIB_GR_METATABLE);
762 lua_setmetatable(L,-2);
763 lua_rawseti(L,-2,i); i++;
766 (*hh)->body = NULL; /* prevent double free */
771 mplib_fig_copy_body (lua_State *L) {
773 struct mp_graphic_object **v;
774 struct mp_graphic_object *p;
775 struct mp_edge_object **hh = is_fig(L,1);
779 v = lua_newuserdata (L, sizeof(struct mp_graphic_object *));
780 *v = mp_gr_copy_object((*hh)->_parent,p);
781 luaL_getmetatable(L,MPLIB_GR_METATABLE);
782 lua_setmetatable(L,-2);
783 lua_rawseti(L,-2,i); i++;
791 mplib_fig_tostring (lua_State *L) {
792 struct mp_edge_object **hh = is_fig(L,1);
793 lua_pushfstring(L,"<figure %p>",*hh);
800 mp_wrapped_shipout (struct mp_edge_object *hh, int prologues, int procset) {
802 if (setjmp(mp->jump_buf)) {
805 mp_gr_ship_out(hh,prologues,procset);
810 mplib_fig_postscript (lua_State *L) {
811 struct mp_edge_object **hh = is_fig(L,1);
812 int prologues = luaL_optnumber(L,2,-1);
813 int procset = luaL_optnumber(L,3,-1);
814 mplib_instance *mplib_data = mplib_get_data((*hh)->_parent);
815 if (mplib_data->ps_out == NULL) {
816 if (mp_wrapped_shipout(*hh,prologues, procset)) {
817 if (mplib_data->ps_out!=NULL ) {
818 lua_pushstring(L, mplib_data->ps_out);
819 free_stream_buf(ps_out);
826 lua_pushstring(L,mplib_data->log_out);
827 xfree(mplib_data->ps_out);
836 mplib_fig_filename (lua_State *L) {
837 struct mp_edge_object **hh = is_fig(L,1);
839 char *s = (*hh)->_filename;
849 mplib_fig_bb (lua_State *L) {
850 struct mp_edge_object **hh = is_fig(L,1);
852 lua_pushnumber(L, (double)(*hh)->_minx/65536.0);
854 lua_pushnumber(L, (double)(*hh)->_miny/65536.0);
856 lua_pushnumber(L, (double)(*hh)->_maxx/65536.0);
858 lua_pushnumber(L, (double)(*hh)->_maxy/65536.0);
866 mplib_gr_collect (lua_State *L) {
867 struct mp_graphic_object **hh = is_gr_object(L,1);
869 mp_gr_toss_object(*hh);
876 mplib_gr_tostring (lua_State *L) {
877 struct mp_graphic_object **hh = is_gr_object(L,1);
878 lua_pushfstring(L,"<object %p>",*hh);
884 mplib_gr_fields (lua_State *L) {
888 struct mp_graphic_object **hh = is_gr_object(L,1);
890 switch ((*hh)->_type_field) {
891 case mp_fill_code: fields = fill_fields; break;
892 case mp_stroked_code: fields = stroked_fields; break;
893 case mp_text_code: fields = text_fields; break;
894 case mp_special_code: fields = special_fields; break;
895 case mp_start_clip_code: fields = start_clip_fields; break;
896 case mp_start_bounds_code: fields = start_bounds_fields; break;
897 case mp_stop_clip_code: fields = stop_clip_fields; break;
898 case mp_stop_bounds_code: fields = stop_bounds_fields; break;
899 default: fields = no_fields;
902 for (f = *fields; f != NULL; f++) {
904 lua_rawseti(L,-2,i); i++;
913 #define mplib_push_number(L,x) lua_pushnumber(L,(lua_Number)(x)/65536.0)
919 mplib_push_path (lua_State *L, struct mp_knot *h, int is_pen) {
920 struct mp_knot *p; /* for scanning the path */
926 lua_createtable(L,0,6);
928 if (p->left_type_field != mp_explicit) {
929 mplib_push_S(left_type);
930 lua_pushstring(L,knot_type_enum[p->left_type_field]);
933 if (p->right_type_field != mp_explicit) {
934 mplib_push_S(right_type);
935 lua_pushstring(L,knot_type_enum[p->right_type_field]);
939 mplib_push_S(x_coord);
940 mplib_push_number(L,p->x_coord_field);
942 mplib_push_S(y_coord);
943 mplib_push_number(L,p->y_coord_field);
945 mplib_push_S(left_x);
946 mplib_push_number(L,p->left_x_field);
948 mplib_push_S(left_y);
949 mplib_push_number(L,p->left_y_field);
951 mplib_push_S(right_x);
952 mplib_push_number(L,p->right_x_field);
954 mplib_push_S(right_y);
955 mplib_push_number(L,p->right_y_field);
957 lua_rawseti(L,-2,i); i++;
958 if ( p->right_type_field==mp_endpoint ) {
968 #define set_color_objects(pq) \
969 object_color_model = pq->color_model_field; \
970 object_color_a = pq->color_field._a_val; \
971 object_color_b = pq->color_field._b_val; \
972 object_color_c = pq->color_field._c_val; \
973 object_color_d = pq->color_field._d_val;
977 mplib_push_color (lua_State *L, struct mp_graphic_object *p ) {
978 int object_color_model;
979 int object_color_a, object_color_b, object_color_c, object_color_d ;
981 if (p->_type_field == mp_fill_code) {
982 mp_fill_object *h = (mp_fill_object *)p;
983 set_color_objects(h);
984 } else if (p->_type_field == mp_stroked_code) {
985 mp_stroked_object *h = (mp_stroked_object *)p;
986 set_color_objects(h);
988 mp_text_object *h = (mp_text_object *)p;
989 set_color_objects(h);
992 if (object_color_model >= mp_grey_model) {
993 mplib_push_number(L,object_color_a);
995 if (object_color_model >= mp_rgb_model) {
996 mplib_push_number(L,object_color_b);
998 mplib_push_number(L,object_color_c);
1000 if (object_color_model == mp_cmyk_model) {
1001 mplib_push_number(L,object_color_d);
1002 lua_rawseti(L,-2,4);
1011 /* the dash scale is not exported, the field has no external value */
1013 mplib_push_dash (lua_State *L, struct mp_stroked_object *h ) {
1015 if (h!=NULL && h->dash_p_field != NULL) {
1016 d = h->dash_p_field;
1018 mplib_push_number(L,d->offset_field);
1019 lua_setfield(L,-2,"offset");
1020 if (d->array_field!=NULL ) {
1023 while (*(d->array_field+i) != -1) {
1024 mplib_push_number(L, *(d->array_field+1));
1026 lua_rawseti(L,-2,i);
1028 lua_setfield(L,-2,"dashes");
1036 mplib_push_transform (lua_State *L, struct mp_text_object *h ) {
1039 lua_createtable(L,6,0);
1040 mplib_push_number(L,h->tx_field);
1041 lua_rawseti(L,-2,i); i++;
1042 mplib_push_number(L,h->ty_field);
1043 lua_rawseti(L,-2,i); i++;
1044 mplib_push_number(L,h->txx_field);
1045 lua_rawseti(L,-2,i); i++;
1046 mplib_push_number(L,h->tyx_field);
1047 lua_rawseti(L,-2,i); i++;
1048 mplib_push_number(L,h->txy_field);
1049 lua_rawseti(L,-2,i); i++;
1050 mplib_push_number(L,h->tyy_field);
1051 lua_rawseti(L,-2,i); i++;
1057 #define FIELD(A) (mplib_is_S(A,2))
1060 mplib_fill_field (lua_State *L, struct mp_fill_object *h) {
1062 mplib_push_path(L, h->path_p_field, MPLIB_PATH);
1063 } else if (FIELD(htap)) {
1064 mplib_push_path(L, h->htap_p_field, MPLIB_PATH);
1065 } else if (FIELD(pen)) {
1066 mplib_push_path(L, h->pen_p_field, MPLIB_PEN);
1067 } else if (FIELD(color)) {
1068 mplib_push_color(L,(mp_graphic_object *)h);
1069 } else if (FIELD(linejoin)) {
1070 lua_pushnumber(L,h->ljoin_field);
1071 } else if (FIELD(miterlimit)) {
1072 mplib_push_number(L,h->miterlim_field);
1073 } else if (FIELD(prescript)) {
1074 lua_pushstring(L,h->pre_script_field);
1075 } else if (FIELD(postscript)) {
1076 lua_pushstring(L,h->post_script_field);
1083 mplib_stroked_field (lua_State *L, struct mp_stroked_object *h) {
1085 mplib_push_path(L, h->path_p_field, MPLIB_PATH);
1086 } else if (FIELD(pen)) {
1087 mplib_push_path(L, h->pen_p_field, MPLIB_PEN);
1088 } else if (FIELD(color)) {
1089 mplib_push_color(L, (mp_graphic_object *)h);
1090 } else if (FIELD(dash)) {
1091 mplib_push_dash(L,h);
1092 } else if (FIELD(linecap)) {
1093 lua_pushnumber(L,h->lcap_field);
1094 } else if (FIELD(linejoin)) {
1095 lua_pushnumber(L,h->ljoin_field);
1096 } else if (FIELD(miterlimit)) {
1097 mplib_push_number(L,h->miterlim_field);
1098 } else if (FIELD(prescript)) {
1099 lua_pushstring(L,h->pre_script_field);
1100 } else if (FIELD(postscript)) {
1101 lua_pushstring(L,h->post_script_field);
1108 mplib_text_field (lua_State *L, struct mp_text_object *h) {
1110 lua_pushstring(L,h->text_p_field);
1111 } else if (FIELD(dsize)) {
1112 mplib_push_number(L,(h->font_dsize_field/16));
1113 } else if (FIELD(font)) {
1114 lua_pushstring(L,h->font_name_field);
1115 } else if (FIELD(color)) {
1116 mplib_push_color(L,(mp_graphic_object *)h);
1117 } else if (FIELD(width)) {
1118 mplib_push_number(L,h->width_field);
1119 } else if (FIELD(height)) {
1120 mplib_push_number(L,h->height_field);
1121 } else if (FIELD(depth)) {
1122 mplib_push_number(L,h->depth_field);
1123 } else if (FIELD(transform)) {
1124 mplib_push_transform(L,h);
1125 } else if (FIELD(prescript)) {
1126 lua_pushstring(L,h->pre_script_field);
1127 } else if (FIELD(postscript)) {
1128 lua_pushstring(L,h->post_script_field);
1135 mplib_special_field (lua_State *L, struct mp_special_object *h) {
1136 if (FIELD(prescript)) {
1137 lua_pushstring(L,h->pre_script_field);
1144 mplib_start_bounds_field (lua_State *L, struct mp_bounds_object *h) {
1146 mplib_push_path(L,h->path_p_field, MPLIB_PATH);
1153 mplib_start_clip_field (lua_State *L, struct mp_clip_object *h) {
1155 mplib_push_path(L,h->path_p_field, MPLIB_PATH);
1162 mplib_gr_index (lua_State *L) {
1163 struct mp_graphic_object **hh = is_gr_object(L,1);
1165 struct mp_graphic_object *h = *hh;
1166 if (mplib_is_S(type,2)) {
1167 lua_rawgeti(L,LUA_REGISTRYINDEX,mplib_type_Ses[h->_type_field]);
1169 switch (h->_type_field) {
1170 case mp_fill_code: mplib_fill_field(L,(mp_fill_object *)h); break;
1171 case mp_stroked_code: mplib_stroked_field(L,(mp_stroked_object *)h); break;
1172 case mp_text_code: mplib_text_field(L,(mp_text_object *)h); break;
1173 case mp_special_code: mplib_special_field(L,(mp_special_object *)h); break;
1174 case mp_start_clip_code: mplib_start_clip_field(L,(mp_clip_object *)h); break;
1175 case mp_start_bounds_code: mplib_start_bounds_field(L,(mp_bounds_object *)h); break;
1176 /* case mp_stop_clip_code: */
1177 /* case mp_stop_bounds_code: */
1178 default: lua_pushnil(L);
1188 static const struct luaL_reg mplib_meta[] = {
1189 {"__gc", mplib_collect},
1190 {"__tostring", mplib_tostring},
1191 {NULL, NULL} /* sentinel */
1194 static const struct luaL_reg mplib_fig_meta[] = {
1195 {"__gc", mplib_fig_collect },
1196 {"__tostring", mplib_fig_tostring },
1197 {"objects", mplib_fig_body },
1198 {"copy_objects", mplib_fig_copy_body },
1199 {"filename", mplib_fig_filename },
1200 {"postscript", mplib_fig_postscript },
1201 {"boundingbox", mplib_fig_bb },
1202 {NULL, NULL} /* sentinel */
1205 static const struct luaL_reg mplib_gr_meta[] = {
1206 {"__gc", mplib_gr_collect },
1207 {"__tostring", mplib_gr_tostring },
1208 {"__index", mplib_gr_index },
1209 {"fields", mplib_gr_fields },
1210 {NULL, NULL} /* sentinel */
1214 static const struct luaL_reg mplib_d [] = {
1215 {"execute", mplib_execute },
1216 {"finish", mplib_finish },
1217 {"statistics", mplib_statistics },
1218 {NULL, NULL} /* sentinel */
1222 static const struct luaL_reg mplib_m[] = {
1224 {NULL, NULL} /* sentinel */
1229 luaopen_mp (lua_State *L) {
1231 luaL_newmetatable(L,MPLIB_GR_METATABLE);
1232 lua_pushvalue(L, -1); /* push metatable */
1233 lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
1234 luaL_register(L, NULL, mplib_gr_meta); /* object meta methods */
1237 luaL_newmetatable(L,MPLIB_FIG_METATABLE);
1238 lua_pushvalue(L, -1); /* push metatable */
1239 lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
1240 luaL_register(L, NULL, mplib_fig_meta); /* figure meta methods */
1243 luaL_newmetatable(L,MPLIB_METATABLE);
1244 lua_pushvalue(L, -1); /* push metatable */
1245 lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
1246 luaL_register(L, NULL, mplib_meta); /* meta methods */
1247 luaL_register(L, NULL, mplib_d); /* dict methods */
1248 luaL_register(L, "mplib", mplib_m); /* module functions */