beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / luafontloader / src / luafflib.c
blob91dcfeee02861ea0d3a7038d70871430b8f0c5b3
1 /* luafflib.c
3 Copyright 2007-2010 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 /**
21 * @desc Support interface for fontforge 20070607
22 * @version 1.0
23 * @author Taco Hoekwater
26 #include "pfaedit.h"
27 #include "ustring.h"
28 #include "lib/lib.h" /* web2c's lib, for recorder_record_input */
30 #include "ffdummies.h"
31 #include "splinefont.h"
33 #define FONT_METATABLE "fontloader.splinefont"
34 #define FONT_SUBFONT_METATABLE "fontloader.splinefont.subfont"
35 #define FONT_GLYPHS_METATABLE "fontloader.splinefont.glyphs"
36 #define FONT_GLYPH_METATABLE "fontloader.splinefont.glyph"
38 #define LUA_OTF_VERSION "0.4"
40 static const char *possub_type_enum[] = {
41 "null", "position", "pair", "substitution",
42 "alternate", "multiple", "ligature", "lcaret",
43 "kerning", "vkerning", "anchors", "contextpos",
44 "contextsub", "chainpos", "chainsub", "reversesub",
45 "max", "kernback", "vkernback", NULL
48 #define LAST_POSSUB_TYPE_ENUM 18
50 #define eight_nulls() NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
52 static const char *otf_lookup_type_enum[] = {
53 "gsub_start", "gsub_single", "gsub_multiple", "gsub_alternate",
54 "gsub_ligature", "gsub_context", "gsub_contextchain", NULL,
55 "gsub_reversecontextchain", NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*0x00F */
56 eight_nulls(), eight_nulls(),
57 eight_nulls(), eight_nulls(),
58 eight_nulls(), eight_nulls(),
59 eight_nulls(), eight_nulls(),
60 eight_nulls(), eight_nulls(),
61 eight_nulls(), eight_nulls(),
62 eight_nulls(), eight_nulls(),
63 eight_nulls(), eight_nulls(),
64 eight_nulls(), eight_nulls(),
65 eight_nulls(), eight_nulls(),
66 eight_nulls(), eight_nulls(),
67 eight_nulls(), eight_nulls(),
68 eight_nulls(), eight_nulls(),
69 eight_nulls(), eight_nulls(),
70 eight_nulls(), eight_nulls(),
71 "gpos_start", "gpos_single", "gpos_pair", "gpos_cursive",
72 "gpos_mark2base", "gpos_mark2ligature", "gpos_mark2mark", "gpos_context",
73 "gpos_contextchain", NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 0x10F */
74 eight_nulls(), eight_nulls(),
75 eight_nulls(), eight_nulls(),
76 eight_nulls(), eight_nulls(),
77 eight_nulls(), eight_nulls(),
78 eight_nulls(), eight_nulls(),
79 eight_nulls(), eight_nulls(),
80 eight_nulls(), eight_nulls(),
81 eight_nulls(), eight_nulls(),
82 eight_nulls(), eight_nulls(),
83 eight_nulls(), eight_nulls(),
84 eight_nulls(), eight_nulls(),
85 eight_nulls(), eight_nulls(),
86 eight_nulls(), eight_nulls(),
87 eight_nulls(), eight_nulls(),
88 eight_nulls(), eight_nulls(),
91 static const char *anchor_type_enum[] = {
92 "mark", "basechar", "baselig", "basemark", "centry", "cexit", "max", NULL
95 #define MAX_ANCHOR_TYPE 7
97 static const char *anchorclass_type_enum[] = {
98 "mark", "mkmk", "curs", "mklg", NULL
101 static const char *glyph_class_enum[] = {
102 "automatic", "none", "base", "ligature", "mark", "component", NULL
105 static const char *ttfnames_enum[ttf_namemax] = {
106 "copyright", "family", "subfamily", "uniqueid",
107 "fullname", "version", "postscriptname", "trademark",
108 "manufacturer", "designer", "descriptor", "venderurl",
109 "designerurl", "license", "licenseurl", "idontknow",
110 "preffamilyname", "prefmodifiers", "compatfull", "sampletext",
111 "cidfindfontname", "wwsfamily", "wwssubfamily"
114 static const char *fpossub_format_enum[] = {
115 "glyphs", "class", "coverage", "reversecoverage", NULL
118 static const char *tex_type_enum[4] = { "unset", "text", "math", "mathext" };
120 /* has an offset of 1, ui_none = 0. */
121 static const char *uni_interp_enum[9] = {
122 "unset", "none", "adobe", "greek", "japanese",
123 "trad_chinese", "simp_chinese", "korean", "ams"
126 #define check_isfont(L,b) (SplineFont **)luaL_checkudata(L,b,FONT_METATABLE)
127 #define check_isglyph(L,b) (struct splinechar **)luaL_checkudata(L,b,FONT_GLYPH_METATABLE)
129 /* forward declarations */
130 static void handle_generic_pst(lua_State * L, struct generic_pst *pst);
131 static void handle_generic_fpst(lua_State * L, struct generic_fpst *fpst);
132 static void handle_kernclass(lua_State * L, struct kernclass *kerns, const char *name);
133 static void handle_splinefont(lua_State * L, struct splinefont *sf);
134 static void handle_kernpair(lua_State * L, struct kernpair *kp);
135 static void handle_liglist(lua_State * L, struct liglist *ligofme);
136 static void handle_anchorpoint(lua_State * L, struct anchorpoint *anchor);
138 static int is_userdata(lua_State *L, int b, const char *utype)
140 if (lua_type(L,b) == LUA_TUSERDATA) {
141 lua_getmetatable(L, b);
142 luaL_getmetatable(L, utype);
143 if (lua_compare(L, -2, -1, LUA_OPEQ)) {
144 lua_pop(L,2);
145 return 1;
147 lua_pop(L,2);
149 return 0;
152 static void lua_ff_pushfont(lua_State * L, SplineFont * sf)
154 SplineFont **a;
155 if (sf == NULL) {
156 lua_pushnil(L);
157 } else {
158 a = lua_newuserdata(L, sizeof(SplineFont *));
159 *a = sf;
160 luaL_getmetatable(L, FONT_METATABLE);
161 lua_setmetatable(L, -2);
163 return;
166 static void lua_ff_pushsubfont(lua_State * L, SplineFont * sf)
168 SplineFont **a;
169 if (sf == NULL) {
170 lua_pushnil(L);
171 } else {
172 a = lua_newuserdata(L, sizeof(SplineFont *));
173 *a = sf;
174 luaL_getmetatable(L, FONT_SUBFONT_METATABLE);
175 lua_setmetatable(L, -2);
177 return;
180 static void lua_ff_pushglyph(lua_State * L, struct splinechar *sc)
182 struct splinechar **a;
183 if (sc == NULL) {
184 lua_pushnil(L);
185 } else {
186 a = lua_newuserdata(L, sizeof(struct splinechar *));
187 *a = sc;
188 luaL_getmetatable(L, FONT_GLYPH_METATABLE);
189 lua_setmetatable(L, -2);
191 return;
195 static int ff_open(lua_State * L)
197 SplineFont *sf;
198 const char *fontname;
199 FILE *l;
200 char s[511];
201 size_t len;
202 int args, i;
203 int openflags = 1 + 4;
204 fontname = luaL_checkstring(L, 1);
205 /* test fontname for existance */
206 if ((l = fopen(fontname, "r"))) {
207 recorder_record_input(fontname);
208 fclose(l);
209 } else {
210 lua_pushnil(L);
211 lua_pushfstring(L, "font loading failed for %s (read error)\n", fontname);
212 return 2;
214 args = lua_gettop(L);
215 if (args >= 2 && (lua_type(L, 2) == LUA_TSTRING)) {
216 len = strlen(fontname);
217 if (*(fontname + len) != ')') {
218 /* possibly fails for embedded parens in the font name */
219 if (len == 0) {
220 snprintf(s, 511, "%s", fontname);
221 } else {
222 snprintf(s, 511, "%s(%s)", fontname, lua_tolstring(L, 2, &len));
225 } else {
226 snprintf(s, 511, "%s", fontname);
228 if (strlen(s) > 0) {
229 gww_error_count = 0;
230 sf = ReadSplineFont((char *) s, openflags);
231 if (sf == NULL) {
232 lua_pushnil(L);
233 lua_pushfstring(L, "font loading failed for %s\n", s);
234 if (gww_error_count > 0) {
235 for (i = 0; i < gww_error_count; i++) {
236 lua_pushstring(L, gww_errors[i]);
237 lua_concat(L, 2);
239 gwwv_errors_free();
241 } else {
242 FVAppend(_FontViewCreate(sf));
243 lua_ff_pushfont(L, sf);
244 if (gww_error_count > 0) {
245 lua_newtable(L);
246 for (i = 0; i < gww_error_count; i++) {
247 lua_pushstring(L, gww_errors[i]);
248 lua_rawseti(L, -2, (i + 1));
250 gwwv_errors_free();
251 } else {
252 lua_pushnil(L);
255 } else {
256 lua_pushnil(L);
257 lua_pushfstring(L, "font loading failed: empty string given\n", fontname);
259 return 2;
262 static int ff_close(lua_State * L)
264 SplineFont **sf;
265 /*fputs("ff_close called",stderr); */
266 sf = check_isfont(L, 1);
267 if (*sf != NULL) {
268 if ((*sf)->fv) { /* condition might be improved */
269 FontViewClose((*sf)->fv);
270 } else {
271 EncMapFree((*sf)->map);
272 SplineFontFree(*sf);
274 *sf = NULL;
276 return 0;
279 static int notdef_loc(SplineFont * sf)
281 int k;
282 int l = -1;
283 for (k = 0; k < sf->glyphcnt; k++) {
284 if (sf->glyphs[k]) {
285 if (strcmp(sf->glyphs[k]->name, ".notdef") == 0) {
286 l = k;
290 if (l == -1)
291 l = sf->glyphcnt;
292 return l;
295 static int ff_apply_featurefile(lua_State * L)
297 SplineFont **sf;
298 char *fname;
299 sf = check_isfont(L, 1);
300 fname = xstrdup(luaL_checkstring(L, 2));
301 SFApplyFeatureFilename(*sf, fname);
302 recorder_record_input(fname);
303 free(fname);
304 if (gww_error_count > 0) {
305 int i;
306 lua_newtable(L);
307 for (i = 0; i < gww_error_count; i++) {
308 lua_pushstring(L, gww_errors[i]);
309 lua_rawseti(L, -2, (i + 1));
311 gwwv_errors_free();
312 } else {
313 lua_pushnil(L);
315 return 1;
318 static int ff_apply_afmfile(lua_State * L)
320 SplineFont **sf;
321 const char *fname;
322 sf = check_isfont(L, 1);
323 fname = luaL_checkstring(L, 2);
324 CheckAfmOfPostscript(*sf, fname, (*sf)->map);
325 if (gww_error_count > 0) {
326 int i;
327 lua_newtable(L);
328 for (i = 0; i < gww_error_count; i++) {
329 lua_pushstring(L, gww_errors[i]);
330 lua_rawseti(L, -2, (i + 1));
332 gwwv_errors_free();
333 } else {
334 lua_pushnil(L);
336 return 1;
339 static void dump_intfield(lua_State * L, const char *name, long int field)
341 lua_checkstack(L, 2);
342 lua_pushstring(L, name);
343 lua_pushnumber(L, field);
344 lua_rawset(L, -3);
347 static void dump_uintfield(lua_State * L, const char *name, unsigned int field)
349 lua_checkstack(L, 2);
350 lua_pushstring(L, name);
351 lua_pushnumber(L, field);
352 lua_rawset(L, -3);
355 static void dump_realfield(lua_State * L, const char *name, real field)
357 lua_checkstack(L, 2);
358 lua_pushstring(L, name);
359 lua_pushnumber(L, field);
360 lua_rawset(L, -3);
363 #define dump_cond_intfield(a,b,c) if ((c)!=0) { dump_intfield ((a),(b),(c)); }
365 static void dump_stringfield(lua_State * L, const char *name, const char *field)
367 lua_checkstack(L, 2);
368 lua_pushstring(L, name);
369 lua_pushstring(L, field);
370 lua_rawset(L, -3);
373 static void dump_char_ref(lua_State * L, struct splinechar *spchar)
375 lua_checkstack(L, 2);
376 lua_pushstring(L, "char");
377 lua_pushstring(L, spchar->name);
378 lua_rawset(L, -3);
381 static void dump_lstringfield(lua_State * L, const char *name, char *field, int len)
383 lua_checkstack(L, 2);
384 lua_pushstring(L, name);
385 lua_pushlstring(L, field, len);
386 lua_rawset(L, -3);
389 static void dump_enumfield(lua_State * L, const char *name, int fid, const char **fields)
391 lua_checkstack(L, 2);
392 lua_pushstring(L, name);
393 lua_pushstring(L, fields[fid]);
394 lua_rawset(L, -3);
397 static void dump_floatfield(lua_State * L, const char *name, double field)
399 lua_checkstack(L, 2);
400 lua_pushstring(L, name);
401 lua_pushnumber(L, field);
402 lua_rawset(L, -3);
405 static char tag_string[5] = { 0 };
407 static char *make_tag_string(unsigned int field)
409 tag_string[0] = (field & 0xFF000000) >> 24;
410 tag_string[1] = (field & 0x00FF0000) >> 16;
411 tag_string[2] = (field & 0x0000FF00) >> 8;
412 tag_string[3] = (field & 0x000000FF);
413 return (char *) tag_string;
416 static void dump_tag(lua_State * L, const char *name, unsigned int field)
418 lua_checkstack(L, 2);
419 lua_pushstring(L, name);
420 lua_pushlstring(L, make_tag_string(field), 4);
421 lua_rawset(L, -3);
424 static void dump_subtable_name(lua_State * L, const char *name, struct lookup_subtable *s)
426 /* this is likely a backref */
427 if (s == NULL)
428 return;
429 lua_checkstack(L, 2);
430 if (s->next == NULL) {
431 dump_stringfield(L, name, s->subtable_name);
432 } else {
433 /* can this really happen ? */
434 int i = 0;
435 lua_newtable(L);
436 while (s != NULL) {
437 lua_pushstring(L, s->subtable_name);
438 lua_rawseti(L, -2, ++i);
439 s = s->next;
441 lua_setfield(L, -2, name);
445 #define NESTED_TABLE(a,b,c) { \
446 int k = 1;\
447 next = b; \
448 while (next != NULL) { \
449 lua_checkstack(L,2); \
450 lua_pushnumber(L,k); k++; \
451 lua_createtable(L,0,c); \
452 a(L, next); \
453 lua_rawset(L,-3); \
454 next = next->next; \
458 #define NESTED_TABLE_SF(a,b,c,d) { \
459 int k = 1; \
460 next = b; \
461 while (next != NULL) { \
462 lua_checkstack(L,2); \
463 lua_pushnumber(L,k); k++; \
464 lua_createtable(L,0,d); \
465 if (a(L, next, c)) \
466 lua_rawset(L,-3); \
467 else { \
468 lua_pop(L,2); \
470 next = next->next; \
474 static void do_handle_scriptlanglist(lua_State * L, struct scriptlanglist *sl)
476 int k;
477 dump_tag(L, "script", sl->script);
479 lua_checkstack(L, 3);
480 lua_newtable(L);
481 for (k = 0; k < MAX_LANG; k++) {
482 if (sl->langs[k] != 0) {
483 lua_pushnumber(L, (k + 1));
484 lua_pushstring(L, make_tag_string(sl->langs[k]));
485 lua_rawset(L, -3);
489 if (sl->lang_cnt >= MAX_LANG) {
490 for (k = MAX_LANG; k < sl->lang_cnt; k++) {
491 lua_pushnumber(L, (k + 1));
492 lua_pushstring(L, make_tag_string(sl->morelangs[k - MAX_LANG]));
493 lua_rawset(L, -3);
496 lua_setfield(L, -2, "langs");
499 static void handle_scriptlanglist(lua_State * L, struct scriptlanglist *sll)
501 struct scriptlanglist *next;
502 NESTED_TABLE(do_handle_scriptlanglist, sll, 4);
505 static void
506 do_handle_featurescriptlanglist(lua_State * L,
507 struct featurescriptlanglist *features)
509 dump_tag(L, "tag", features->featuretag);
510 lua_newtable(L);
511 handle_scriptlanglist(L, features->scripts);
512 lua_setfield(L, -2, "scripts");
515 static void
516 handle_featurescriptlanglist(lua_State * L,
517 struct featurescriptlanglist *features)
519 struct featurescriptlanglist *next;
520 NESTED_TABLE(do_handle_featurescriptlanglist, features, 3);
523 static void do_handle_lookup_subtable(lua_State * L, struct lookup_subtable *subtable)
526 dump_stringfield(L, "name", subtable->subtable_name);
527 dump_stringfield(L, "suffix", subtable->suffix);
529 /* struct otlookup *lookup; *//* this is the parent */
531 /* dump_intfield (L,"unused", subtable->unused); */
532 /* The next one is true if there is no fpst, false otherwise */
534 dump_intfield (L,"per_glyph_pst_or_kern",subtable->per_glyph_pst_or_kern);
536 dump_cond_intfield(L, "anchor_classes", subtable->anchor_classes);
537 dump_cond_intfield(L, "vertical_kerning", subtable->vertical_kerning);
539 if (subtable->kc != NULL) {
540 lua_newtable(L);
541 handle_kernclass(L, subtable->kc, subtable->subtable_name);
542 lua_setfield(L, -2, "kernclass");
544 #if 0
545 if (subtable->fpst != NULL) {
546 /* lua_newtable(L); */
547 handle_generic_fpst(L, subtable->fpst);
548 /* lua_setfield(L,-2, "fpst"); */
550 #endif
552 /* int subtable_offset; *//* used by OTF file generation */
553 /* int32 *extra_subtables; *//* used by OTF file generation */
556 static void handle_lookup_subtable(lua_State * L, struct lookup_subtable *subtable)
558 struct lookup_subtable *next;
559 NESTED_TABLE(do_handle_lookup_subtable, subtable, 2);
562 static int do_handle_lookup(lua_State * L, struct otlookup *lookup, SplineFont * sf)
564 int mc;
566 dump_enumfield(L, "type", lookup->lookup_type, otf_lookup_type_enum);
568 lua_newtable(L);
569 if (lookup->lookup_flags & pst_r2l) {
570 lua_pushstring(L, "r2l");
571 lua_pushboolean(L, 1);
572 lua_rawset(L, -3);
574 if (lookup->lookup_flags & pst_ignorebaseglyphs) {
575 lua_pushstring(L, "ignorebaseglyphs");
576 lua_pushboolean(L, 1);
577 lua_rawset(L, -3);
579 if (lookup->lookup_flags & pst_ignoreligatures) {
580 lua_pushstring(L, "ignoreligatures");
581 lua_pushboolean(L, 1);
582 lua_rawset(L, -3);
584 if (lookup->lookup_flags & pst_ignorecombiningmarks) {
585 lua_pushstring(L, "ignorecombiningmarks");
586 lua_pushboolean(L, 1);
587 lua_rawset(L, -3);
589 mc = (lookup->lookup_flags >> 8);
590 if (mc > 0 && mc < sf->mark_class_cnt && sf->mark_class_names[mc] != NULL) {
591 lua_pushstring(L, "mark_class");
592 lua_pushstring(L, sf->mark_class_names[mc]);
593 lua_rawset(L, -3);
595 lua_setfield(L, -2, "flags");
599 dump_stringfield(L, "name", lookup->lookup_name);
601 if (lookup->features != NULL) {
602 lua_newtable(L);
603 handle_featurescriptlanglist(L, lookup->features);
604 lua_setfield(L, -2, "features");
607 if (lookup->subtables != NULL) {
608 lua_newtable(L);
609 handle_lookup_subtable(L, lookup->subtables);
610 lua_setfield(L, -2, "subtables");
613 /* dump_intfield (L,"unused", lookup->unused); */
614 /* dump_intfield (L,"empty", lookup->empty); */
615 /* dump_intfield (L,"store_in_afm", lookup->store_in_afm); */
616 /* dump_intfield (L,"needs_extension", lookup->needs_extension); */
617 /* dump_intfield (L,"temporary_kern", lookup->temporary_kern); */
618 /* dump_intfield (L,"def_lang_checked", lookup->def_lang_checked); */
619 /* dump_intfield (L,"def_lang_found", lookup->def_lang_found); */
620 /* dump_intfield (L,"ticked", lookup->ticked); */
621 /* dump_intfield (L,"subcnt", lookup->subcnt); */
622 /* dump_intfield (L,"lookup_index", lookup->lookup_index); *//* identical to array index */
623 /* dump_intfield (L,"lookup_offset", lookup->lookup_offset); */
624 /* dump_intfield (L,"lookup_length", lookup->lookup_length); */
625 /* dump_stringfield(L,"tempname", lookup->tempname); */
626 return 1;
629 static void handle_lookup(lua_State * L, struct otlookup *lookup, SplineFont * sf)
631 struct otlookup *next;
632 NESTED_TABLE_SF(do_handle_lookup, lookup, sf, 18); /* 18 is a guess */
635 static void do_handle_kernpair(lua_State * L, struct kernpair *kp)
638 if (kp->sc != NULL)
639 dump_char_ref(L, kp->sc);
640 dump_intfield(L, "off", kp->off);
641 /* uint16 kcid; *//* temporary value */
642 dump_subtable_name(L, "lookup", kp->subtable);
645 static void handle_kernpair(lua_State * L, struct kernpair *kp)
647 struct kernpair *next;
648 NESTED_TABLE(do_handle_kernpair, kp, 4);
651 static void handle_splinecharlist(lua_State * L, struct splinecharlist *scl)
654 struct splinecharlist *next = scl;
655 int k = 1;
656 lua_checkstack(L, 10);
657 while (next != NULL) {
658 if (next->sc != NULL) {
659 lua_pushnumber(L, k);
660 k++;
661 lua_pushstring(L, next->sc->name);
662 lua_rawset(L, -3);
664 next = next->next;
668 /* vs is the "variation selector" a unicode codepoint which modifieds */
669 /* the code point before it. If vs is -1 then unienc is just an */
670 /* alternate encoding (greek Alpha and latin A), but if vs is one */
671 /* of unicode's variation selectors then this glyph is somehow a */
672 /* variant shape. The specifics depend on the selector and script */
673 /* fid is currently unused, but may, someday, be used to do ttcs */
674 /* NOTE: GlyphInfo displays vs==-1 as vs==0, and fixes things up */
676 static int handle_altuni(lua_State * L, struct altuni *au)
678 struct altuni *next = au;
679 int i = 0;
680 int k = 1;
681 lua_checkstack(L, 3);
682 while (next != NULL) {
683 if (next->unienc<0x10FFFF) {
684 lua_newtable(L);
685 dump_intfield(L, "unicode", next->unienc);
686 i++;
687 if (next->vs != -1) {
688 dump_intfield(L, "variant", next->vs);
689 /* dump_intfield(L, "fid", next->fid); */
691 lua_rawseti(L, -2, k++);
692 } else {
693 printf("ignoring variant %i %i\n",next->unienc,next->vs);
695 next = next->next;
697 return i;
700 #define interesting_vr(a) (((a)->xoff!=0) || ((a)->yoff!=0) || ((a)->h_adv_off!=0) || ((a)->v_adv_off!=0))
702 static void handle_vr(lua_State * L, struct vr *pos)
705 dump_cond_intfield(L, "x", pos->xoff);
706 dump_cond_intfield(L, "y", pos->yoff);
707 dump_cond_intfield(L, "h", pos->h_adv_off);
708 dump_cond_intfield(L, "v", pos->v_adv_off);
712 static void do_handle_generic_pst(lua_State * L, struct generic_pst *pst)
714 int k;
715 if (pst->type > LAST_POSSUB_TYPE_ENUM) {
716 dump_tag(L, "type", pst->type);
717 } else {
718 dump_enumfield(L, "type", pst->type, possub_type_enum);
720 /* unsigned int ticked: 1; */
721 /* unsigned int temporary: 1; *//* Used in afm ligature closure */
722 /* struct lookup_subtable *subtable; *//* handled by caller */
724 lua_checkstack(L, 4);
725 lua_pushstring(L, "specification");
726 lua_createtable(L, 0, 4);
727 if (pst->type == pst_position) {
728 handle_vr(L, &pst->u.pos);
729 } else if (pst->type == pst_pair) {
730 dump_stringfield(L, "paired", pst->u.pair.paired);
731 if (pst->u.pair.vr != NULL) {
732 lua_pushstring(L, "offsets");
733 lua_createtable(L, 2, 0);
734 if (interesting_vr(pst->u.pair.vr)) {
735 lua_createtable(L, 0, 4);
736 handle_vr(L, pst->u.pair.vr);
737 lua_rawseti(L, -2, 1);
739 if (interesting_vr(pst->u.pair.vr + 1)) {
740 lua_createtable(L, 0, 4);
741 handle_vr(L, pst->u.pair.vr + 1);
742 lua_rawseti(L, -2, 2);
744 lua_rawset(L, -3);
746 } else if (pst->type == pst_substitution) {
747 dump_stringfield(L, "variant", pst->u.subs.variant);
748 } else if (pst->type == pst_alternate) {
749 dump_stringfield(L, "components", pst->u.mult.components);
750 } else if (pst->type == pst_multiple) {
751 dump_stringfield(L, "components", pst->u.alt.components);
752 } else if (pst->type == pst_ligature) {
753 dump_stringfield(L, "components", pst->u.lig.components);
754 if (pst->u.lig.lig != NULL) {
755 dump_char_ref(L, pst->u.lig.lig);
757 } else if (pst->type == pst_lcaret) {
758 for (k = 0; k < pst->u.lcaret.cnt; k++) {
759 lua_pushnumber(L, (k + 1));
760 lua_pushnumber(L, pst->u.lcaret.carets[k]);
761 lua_rawset(L, -3);
764 lua_rawset(L, -3);
767 static void handle_generic_pst(lua_State * L, struct generic_pst *pst)
769 struct generic_pst *next;
770 int k;
771 int l = 1;
772 next = pst;
773 /* most likely everything arrives in proper order. But to prevent
774 * surprises, better do this is the proper way
776 while (next != NULL) {
777 if (next->subtable != NULL && next->subtable->subtable_name != NULL) {
778 lua_checkstack(L, 3); /* just in case */
779 lua_getfield(L, -1, next->subtable->subtable_name);
780 if (!lua_istable(L, -1)) {
781 lua_pop(L, 1);
782 lua_newtable(L);
783 lua_setfield(L, -2, next->subtable->subtable_name);
784 lua_getfield(L, -1, next->subtable->subtable_name);
786 k = lua_rawlen(L, -1) + 1;
787 lua_pushnumber(L, k);
788 lua_createtable(L, 0, 4);
789 do_handle_generic_pst(L, next);
790 lua_rawset(L, -3);
791 next = next->next;
792 lua_pop(L, 1); /* pop the subtable */
793 } else {
794 /* Found a pst without subtable, or without subtable name */
795 lua_pushnumber(L, l);
796 l++;
797 lua_createtable(L, 0, 4);
798 do_handle_generic_pst(L, next);
799 lua_rawset(L, -3);
800 next = next->next;
805 static void do_handle_liglist(lua_State * L, struct liglist *ligofme)
807 lua_checkstack(L, 2);
808 if (ligofme->lig != NULL) {
809 lua_createtable(L, 0, 6);
810 handle_generic_pst(L, ligofme->lig);
811 lua_setfield(L, -2, "lig");
813 dump_char_ref(L, ligofme->first);
814 if (ligofme->components != NULL) {
815 lua_newtable(L);
816 handle_splinecharlist(L, ligofme->components);
817 lua_setfield(L, -2, "components");
819 dump_intfield(L, "ccnt", ligofme->ccnt);
823 static void handle_liglist(lua_State * L, struct liglist *ligofme)
825 struct liglist *next;
826 NESTED_TABLE(do_handle_liglist, ligofme, 3);
829 static void do_handle_anchorpoint(lua_State * L, struct anchorpoint *anchor)
832 if (anchor->anchor == NULL) {
833 return;
835 if (anchor->type >= 0 && anchor->type <= MAX_ANCHOR_TYPE) {
836 lua_pushstring(L, anchor_type_enum[anchor->type]);
837 } else {
838 lua_pushstring(L, "Anchorpoint has an unknown type!");
839 lua_error(L);
841 /* unsigned int selected: 1; */
842 /* unsigned int ticked: 1; */
844 lua_rawget(L, -2);
845 if (!lua_istable(L, -1)) {
846 /* create the table first */
847 lua_pop(L, 1);
848 lua_pushstring(L, anchor_type_enum[anchor->type]);
849 lua_pushvalue(L, -1);
850 lua_newtable(L);
851 lua_rawset(L, -4);
852 lua_rawget(L, -2);
854 /* now the 'type' table is top of stack */
855 if (anchor->type == at_baselig) {
856 lua_pushstring(L, anchor->anchor->name);
857 lua_rawget(L, -2);
858 if (!lua_istable(L, -1)) {
859 /* create the table first */
860 lua_pop(L, 1);
861 lua_pushstring(L, anchor->anchor->name);
862 lua_pushvalue(L, -1);
863 lua_newtable(L);
864 lua_rawset(L, -4);
865 lua_rawget(L, -2);
867 lua_newtable(L);
868 dump_intfield(L, "x", anchor->me.x);
869 dump_intfield(L, "y", anchor->me.y);
870 if (anchor->has_ttf_pt)
871 dump_intfield(L, "ttf_pt_index", anchor->ttf_pt_index);
872 dump_intfield(L, "lig_index", anchor->lig_index);
873 lua_rawseti(L, -2, (anchor->lig_index + 1));
874 lua_pop(L, 1);
875 } else {
876 lua_pushstring(L, anchor->anchor->name);
877 lua_newtable(L);
878 dump_intfield(L, "x", anchor->me.x);
879 dump_intfield(L, "y", anchor->me.y);
880 if (anchor->has_ttf_pt)
881 dump_intfield(L, "ttf_pt_index", anchor->ttf_pt_index);
882 dump_intfield(L, "lig_index", anchor->lig_index);
883 lua_rawset(L, -3);
885 lua_pop(L, 1);
888 static void handle_anchorpoint(lua_State * L, struct anchorpoint *anchor)
890 struct anchorpoint *next;
891 next = anchor;
892 while (next != NULL) {
893 do_handle_anchorpoint(L, next);
894 next = next->next;
898 static void handle_glyphvariants(lua_State * L, struct glyphvariants *vars)
900 int i;
901 dump_stringfield(L, "variants", vars->variants);
902 dump_intfield(L, "italic_correction", vars->italic_correction);
903 lua_newtable(L);
904 for (i = 0; i < vars->part_cnt; i++) {
905 lua_newtable(L);
906 dump_stringfield(L, "component", vars->parts[i].component);
907 dump_intfield(L, "extender", vars->parts[i].is_extender);
908 dump_intfield(L, "start", vars->parts[i].startConnectorLength);
909 dump_intfield(L, "end", vars->parts[i].endConnectorLength);
910 dump_intfield(L, "advance", vars->parts[i].fullAdvance);
911 lua_rawseti(L, -2, (i + 1));
913 lua_setfield(L, -2, "parts");
916 static void handle_mathkernvertex(lua_State * L, struct mathkernvertex *mkv)
918 int i;
919 for (i = 0; i < mkv->cnt; i++) {
920 lua_newtable(L);
921 dump_intfield(L, "height", mkv->mkd[i].height);
922 dump_intfield(L, "kern", mkv->mkd[i].kern);
923 lua_rawseti(L, -2, (i + 1));
927 static void handle_mathkern(lua_State * L, struct mathkern *mk)
929 lua_newtable(L);
930 handle_mathkernvertex(L, &(mk->top_right));
931 lua_setfield(L, -2, "top_right");
932 lua_newtable(L);
933 handle_mathkernvertex(L, &(mk->top_left));
934 lua_setfield(L, -2, "top_left");
935 lua_newtable(L);
936 handle_mathkernvertex(L, &(mk->bottom_right));
937 lua_setfield(L, -2, "bottom_right");
938 lua_newtable(L);
939 handle_mathkernvertex(L, &(mk->bottom_left));
940 lua_setfield(L, -2, "bottom_left");
943 static void handle_splinechar(lua_State * L, struct splinechar *glyph, int hasvmetrics)
945 DBounds bb;
946 if (glyph->xmax == 0 && glyph->ymax == 0 && glyph->xmin == 0
947 && glyph->ymin == 0) {
948 SplineCharFindBounds(glyph, &bb);
949 glyph->xmin = bb.minx;
950 glyph->ymin = bb.miny;
951 glyph->xmax = bb.maxx;
952 glyph->ymax = bb.maxy;
954 dump_stringfield(L, "name", glyph->name);
955 dump_intfield(L, "unicode", glyph->unicodeenc);
956 lua_createtable(L, 4, 0);
957 lua_pushnumber(L, 1);
958 lua_pushnumber(L, glyph->xmin);
959 lua_rawset(L, -3);
960 lua_pushnumber(L, 2);
961 lua_pushnumber(L, glyph->ymin);
962 lua_rawset(L, -3);
963 lua_pushnumber(L, 3);
964 lua_pushnumber(L, glyph->xmax);
965 lua_rawset(L, -3);
966 lua_pushnumber(L, 4);
967 lua_pushnumber(L, glyph->ymax);
968 lua_rawset(L, -3);
969 lua_setfield(L, -2, "boundingbox");
970 if (glyph->orig_pos>=0) {
971 dump_intfield(L,"orig_pos",glyph->orig_pos);
973 if (hasvmetrics) {
974 dump_intfield(L, "vwidth", glyph->vwidth);
975 if (glyph->tsb != 0)
976 dump_intfield(L, "tsidebearing", glyph->tsb);
978 dump_intfield(L, "width", glyph->width);
980 if (glyph->lsidebearing != glyph->xmin) {
981 dump_cond_intfield(L, "lsidebearing", glyph->lsidebearing);
983 /* dump_intfield(L,"ttf_glyph", glyph->ttf_glyph); */
985 /* Layer layers[2]; *//* TH Not used */
986 /* int layer_cnt; *//* TH Not used */
987 /* StemInfo *hstem; *//* TH Not used */
988 /* StemInfo *vstem; *//* TH Not used */
989 /* DStemInfo *dstem; *//* TH Not used */
991 /* MinimumDistance *md; *//* TH Not used */
992 /* struct charviewbase *views; *//* TH Not used */
993 /* struct charinfo *charinfo; *//* TH ? (charinfo.c) */
994 /* struct splinefont *parent; *//* TH Not used */
996 if (glyph->glyph_class > 0) {
997 dump_enumfield(L, "class", glyph->glyph_class, glyph_class_enum);
999 /* TH: internal fontforge stuff
1000 dump_intfield(L,"changed", glyph->changed);
1001 dump_intfield(L,"changedsincelasthinted", glyph->changedsincelasthinted);
1002 dump_intfield(L,"manualhints", glyph->manualhints);
1003 dump_intfield(L,"ticked", glyph->ticked);
1004 dump_intfield(L,"changed_since_autosave", glyph->changed_since_autosave);
1005 dump_intfield(L,"widthset", glyph->widthset);
1006 dump_intfield(L,"vconflicts", glyph->vconflicts);
1007 dump_intfield(L,"hconflicts", glyph->hconflicts);
1008 dump_intfield(L,"searcherdummy", glyph->searcherdummy);
1009 dump_intfield(L,"changed_since_search", glyph->changed_since_search);
1010 dump_intfield(L,"wasopen", glyph->wasopen);
1011 dump_intfield(L,"namechanged", glyph->namechanged);
1012 dump_intfield(L,"blended", glyph->blended);
1013 dump_intfield(L,"ticked2", glyph->ticked2);
1014 dump_intfield(L,"unused_so_far", glyph->unused_so_far);
1015 dump_intfield(L,"numberpointsbackards", glyph->numberpointsbackards);
1016 dump_intfield(L,"instructions_out_of_date", glyph->instructions_out_of_date);
1017 dump_intfield(L,"complained_about_ptnums", glyph->complained_about_ptnums);
1018 unsigned int vs_open: 1;
1019 unsigned int unlink_rm_ovrlp_save_undo: 1;
1020 unsigned int inspiro: 1;
1021 unsigned int lig_caret_cnt_fixed: 1;
1024 uint8 *ttf_instrs;
1025 int16 ttf_instrs_len;
1026 int16 countermask_cnt;
1027 HintMask *countermasks;
1030 if (glyph->kerns != NULL) {
1031 lua_newtable(L);
1032 handle_kernpair(L, glyph->kerns);
1033 lua_setfield(L, -2, "kerns");
1035 if (glyph->vkerns != NULL) {
1036 lua_newtable(L);
1037 handle_kernpair(L, glyph->vkerns);
1038 lua_setfield(L, -2, "vkerns");
1041 if (glyph->dependents != NULL) {
1042 lua_newtable(L);
1043 handle_splinecharlist(L, glyph->dependents);
1044 lua_setfield(L, -2, "dependents");
1047 if (glyph->possub != NULL) {
1048 lua_newtable(L);
1049 handle_generic_pst(L, glyph->possub);
1050 lua_setfield(L, -2, "lookups");
1053 if (glyph->ligofme != NULL) {
1054 lua_newtable(L);
1055 handle_liglist(L, glyph->ligofme);
1056 lua_setfield(L, -2, "ligatures");
1059 if (glyph->comment != NULL)
1060 dump_stringfield(L, "comment", glyph->comment);
1062 /* Color color; *//* dont care */
1064 if (glyph->anchor != NULL) {
1065 lua_newtable(L);
1066 handle_anchorpoint(L, glyph->anchor);
1067 lua_setfield(L, -2, "anchors");
1070 if (glyph->altuni != NULL) {
1071 int i;
1072 lua_newtable(L);
1073 i = handle_altuni(L, glyph->altuni);
1074 if (i>0) {
1075 lua_setfield(L, -2, "altuni");
1076 } else {
1077 lua_pop(L,1);
1081 if (glyph->tex_height != TEX_UNDEF)
1082 dump_intfield(L, "tex_height", glyph->tex_height);
1083 if (glyph->tex_depth != TEX_UNDEF)
1084 dump_intfield(L, "tex_depth", glyph->tex_depth);
1086 dump_cond_intfield(L, "is_extended_shape", glyph->is_extended_shape);
1087 if (glyph->italic_correction != TEX_UNDEF)
1088 dump_intfield(L, "italic_correction", glyph->italic_correction);
1089 if (glyph->top_accent_horiz != TEX_UNDEF)
1090 dump_intfield(L, "top_accent", glyph->top_accent_horiz);
1092 if (glyph->vert_variants != NULL) {
1093 lua_newtable(L);
1094 handle_glyphvariants(L, glyph->vert_variants);
1095 lua_setfield(L, -2, "vert_variants");
1097 if (glyph->horiz_variants != NULL) {
1098 lua_newtable(L);
1099 handle_glyphvariants(L, glyph->horiz_variants);
1100 lua_setfield(L, -2, "horiz_variants");
1102 if (glyph->mathkern != NULL) {
1103 lua_newtable(L);
1104 handle_mathkern(L, glyph->mathkern);
1105 lua_setfield(L, -2, "mathkern");
1109 const char *panose_values_0[] = {
1110 "Any", "No Fit", "Text and Display", "Script", "Decorative", "Pictorial"
1113 const char *panose_values_1[] = {
1114 "Any", "No Fit", "Cove", "Obtuse Cove", "Square Cove",
1115 "Obtuse Square Cove",
1116 "Square", "Thin", "Bone", "Exaggerated", "Triangle", "Normal Sans",
1117 "Obtuse Sans", "Perp Sans", "Flared", "Rounded"
1120 const char *panose_values_2[] = {
1121 "Any", "No Fit", "Very Light", "Light", "Thin", "Book",
1122 "Medium", "Demi", "Bold", "Heavy", "Black", "Nord"
1125 const char *panose_values_3[] = {
1126 "Any", "No Fit", "Old Style", "Modern", "Even Width",
1127 "Expanded", "Condensed", "Very Expanded", "Very Condensed", "Monospaced"
1130 const char *panose_values_4[] = {
1131 "Any", "No Fit", "None", "Very Low", "Low", "Medium Low",
1132 "Medium", "Medium High", "High", "Very High"
1135 const char *panose_values_5[] = {
1136 "Any", "No Fit", "Gradual/Diagonal", "Gradual/Transitional",
1137 "Gradual/Vertical",
1138 "Gradual/Horizontal", "Rapid/Vertical", "Rapid/Horizontal",
1139 "Instant/Vertical"
1142 const char *panose_values_6[] = {
1143 "Any", "No Fit", "Straight Arms/Horizontal", "Straight Arms/Wedge",
1144 "Straight Arms/Vertical",
1145 "Straight Arms/Single Serif", "Straight Arms/Double Serif",
1146 "Non-Straight Arms/Horizontal",
1147 "Non-Straight Arms/Wedge", "Non-Straight Arms/Vertical",
1148 "Non-Straight Arms/Single Serif",
1149 "Non-Straight Arms/Double Serif"
1152 const char *panose_values_7[] = {
1153 "Any", "No Fit", "Normal/Contact", "Normal/Weighted", "Normal/Boxed",
1154 "Normal/Flattened",
1155 "Normal/Rounded", "Normal/Off Center", "Normal/Square", "Oblique/Contact",
1156 "Oblique/Weighted",
1157 "Oblique/Boxed", "Oblique/Flattened", "Oblique/Rounded",
1158 "Oblique/Off Center", "Oblique/Square"
1161 const char *panose_values_8[] = {
1162 "Any", "No Fit", "Standard/Trimmed", "Standard/Pointed",
1163 "Standard/Serifed", "High/Trimmed",
1164 "High/Pointed", "High/Serifed", "Constant/Trimmed", "Constant/Pointed",
1165 "Constant/Serifed",
1166 "Low/Trimmed", "Low/Pointed", "Low/Serifed"
1169 const char *panose_values_9[] = {
1170 "Any", "No Fit", "Constant/Small", "Constant/Standard",
1171 "Constant/Large", "Ducking/Small", "Ducking/Standard", "Ducking/Large"
1174 #define panose_values_0_max 5
1175 #define panose_values_1_max 15
1176 #define panose_values_2_max 11
1177 #define panose_values_3_max 9
1178 #define panose_values_4_max 9
1179 #define panose_values_5_max 8
1180 #define panose_values_6_max 11
1181 #define panose_values_7_max 15
1182 #define panose_values_8_max 13
1183 #define panose_values_9_max 7
1185 #define fix_range(a,b) (b<0 ? 0 : (b>a ? 0 : b))
1187 static void handle_pfminfo(lua_State * L, struct pfminfo pfm)
1190 dump_intfield(L, "pfmset", pfm.pfmset);
1191 dump_intfield(L, "winascent_add", pfm.winascent_add);
1192 dump_intfield(L, "windescent_add", pfm.windescent_add);
1193 dump_intfield(L, "hheadascent_add", pfm.hheadascent_add);
1194 dump_intfield(L, "hheaddescent_add", pfm.hheaddescent_add);
1195 dump_intfield(L, "typoascent_add", pfm.typoascent_add);
1196 dump_intfield(L, "typodescent_add", pfm.typodescent_add);
1197 dump_intfield(L, "subsuper_set", pfm.subsuper_set);
1198 dump_intfield(L, "panose_set", pfm.panose_set);
1199 dump_intfield(L, "hheadset", pfm.hheadset);
1200 dump_intfield(L, "vheadset", pfm.vheadset);
1201 dump_intfield(L, "pfmfamily", pfm.pfmfamily);
1202 dump_intfield(L, "weight", pfm.weight);
1203 dump_intfield(L, "width", pfm.width);
1204 dump_intfield(L, "avgwidth", pfm.avgwidth);
1205 dump_intfield(L, "firstchar", pfm.firstchar);
1206 dump_intfield(L, "lastchar", pfm.lastchar);
1207 lua_createtable(L, 0, 10);
1208 dump_enumfield(L, "familytype",
1209 fix_range(panose_values_0_max, pfm.panose[0]),
1210 panose_values_0);
1211 dump_enumfield(L, "serifstyle",
1212 fix_range(panose_values_1_max, pfm.panose[1]),
1213 panose_values_1);
1214 dump_enumfield(L, "weight", fix_range(panose_values_2_max, pfm.panose[2]),
1215 panose_values_2);
1216 dump_enumfield(L, "proportion",
1217 fix_range(panose_values_3_max, pfm.panose[3]),
1218 panose_values_3);
1219 dump_enumfield(L, "contrast", fix_range(panose_values_4_max, pfm.panose[4]),
1220 panose_values_4);
1221 dump_enumfield(L, "strokevariation",
1222 fix_range(panose_values_5_max, pfm.panose[5]),
1223 panose_values_5);
1224 dump_enumfield(L, "armstyle", fix_range(panose_values_6_max, pfm.panose[6]),
1225 panose_values_6);
1226 dump_enumfield(L, "letterform",
1227 fix_range(panose_values_7_max, pfm.panose[7]),
1228 panose_values_7);
1229 dump_enumfield(L, "midline", fix_range(panose_values_8_max, pfm.panose[8]),
1230 panose_values_8);
1231 dump_enumfield(L, "xheight", fix_range(panose_values_9_max, pfm.panose[9]),
1232 panose_values_9);
1233 lua_setfield(L, -2, "panose");
1235 dump_intfield(L, "fstype", pfm.fstype);
1236 dump_intfield(L, "linegap", pfm.linegap);
1237 dump_intfield(L, "vlinegap", pfm.vlinegap);
1238 dump_intfield(L, "hhead_ascent", pfm.hhead_ascent);
1239 dump_intfield(L, "hhead_descent", pfm.hhead_descent);
1240 dump_intfield(L, "hhead_descent", pfm.hhead_descent);
1241 dump_intfield(L, "os2_typoascent", pfm.os2_typoascent);
1242 dump_intfield(L, "os2_typodescent", pfm.os2_typodescent);
1243 dump_intfield(L, "os2_typolinegap", pfm.os2_typolinegap);
1244 dump_intfield(L, "os2_winascent", pfm.os2_winascent);
1245 dump_intfield(L, "os2_windescent", pfm.os2_windescent);
1246 dump_intfield(L, "os2_subxsize", pfm.os2_subxsize);
1247 dump_intfield(L, "os2_subysize", pfm.os2_subysize);
1248 dump_intfield(L, "os2_subxoff", pfm.os2_subxoff);
1249 dump_intfield(L, "os2_subyoff", pfm.os2_subyoff);
1250 dump_intfield(L, "os2_supxsize", pfm.os2_supxsize);
1251 dump_intfield(L, "os2_supysize", pfm.os2_supysize);
1252 dump_intfield(L, "os2_supxoff", pfm.os2_supxoff);
1253 dump_intfield(L, "os2_supyoff", pfm.os2_supyoff);
1254 dump_intfield(L, "os2_strikeysize", pfm.os2_strikeysize);
1255 dump_intfield(L, "os2_strikeypos", pfm.os2_strikeypos);
1256 dump_lstringfield(L, "os2_vendor", pfm.os2_vendor, 4);
1257 dump_intfield(L, "os2_family_class", pfm.os2_family_class);
1258 dump_intfield(L, "os2_xheight", pfm.os2_xheight);
1259 dump_intfield(L, "os2_capheight", pfm.os2_capheight);
1260 dump_intfield(L, "os2_defaultchar", pfm.os2_defaultchar);
1261 dump_intfield(L, "os2_breakchar", pfm.os2_breakchar);
1262 if (pfm.hascodepages) {
1263 lua_newtable(L);
1264 lua_pushnumber(L, pfm.codepages[0]);
1265 lua_rawseti(L, -2, 1);
1266 lua_pushnumber(L, pfm.codepages[1]);
1267 lua_rawseti(L, -2, 2);
1268 lua_setfield(L, -2, "codepages");
1270 if (pfm.hasunicoderanges) {
1271 lua_newtable(L);
1272 lua_pushnumber(L, pfm.unicoderanges[0]);
1273 lua_rawseti(L, -2, 1);
1274 lua_pushnumber(L, pfm.unicoderanges[1]);
1275 lua_rawseti(L, -2, 2);
1276 lua_pushnumber(L, pfm.unicoderanges[2]);
1277 lua_rawseti(L, -2, 3);
1278 lua_pushnumber(L, pfm.unicoderanges[3]);
1279 lua_rawseti(L, -2, 4);
1280 lua_setfield(L, -2, "unicoderanges");
1285 static char *do_handle_enc(lua_State * L, struct enc *enc)
1287 int i;
1288 char *ret = enc->enc_name;
1289 dump_stringfield(L, "enc_name", enc->enc_name);
1290 dump_intfield(L, "char_cnt", enc->char_cnt);
1292 lua_checkstack(L, 4);
1293 if (enc->char_cnt && enc->unicode != NULL) {
1294 lua_createtable(L, enc->char_cnt, 1);
1295 for (i = 0; i < enc->char_cnt; i++) {
1296 lua_pushnumber(L, i);
1297 lua_pushnumber(L, enc->unicode[i]);
1298 lua_rawset(L, -3);
1300 lua_setfield(L, -2, "unicode");
1303 if (enc->char_cnt && enc->psnames != NULL) {
1304 lua_createtable(L, enc->char_cnt, 1);
1305 for (i = 0; i < enc->char_cnt; i++) {
1306 lua_pushnumber(L, i);
1307 lua_pushstring(L, enc->psnames[i]);
1308 lua_rawset(L, -3);
1310 lua_setfield(L, -2, "psnames");
1312 dump_intfield(L, "builtin", enc->builtin);
1313 dump_intfield(L, "hidden", enc->hidden);
1314 dump_intfield(L, "only_1byte", enc->only_1byte);
1315 dump_intfield(L, "has_1byte", enc->has_1byte);
1316 dump_intfield(L, "has_2byte", enc->has_2byte);
1317 dump_cond_intfield(L, "is_unicodebmp", enc->is_unicodebmp);
1318 dump_cond_intfield(L, "is_unicodefull", enc->is_unicodefull);
1319 dump_cond_intfield(L, "is_custom", enc->is_custom);
1320 dump_cond_intfield(L, "is_original", enc->is_original);
1321 dump_cond_intfield(L, "is_compact", enc->is_compact);
1322 dump_cond_intfield(L, "is_japanese", enc->is_japanese);
1323 dump_cond_intfield(L, "is_korean", enc->is_korean);
1324 dump_cond_intfield(L, "is_tradchinese", enc->is_tradchinese);
1325 dump_cond_intfield(L, "is_simplechinese", enc->is_simplechinese);
1327 if (enc->iso_2022_escape_len > 0) {
1328 dump_lstringfield(L, "iso_2022_escape", enc->iso_2022_escape,
1329 enc->iso_2022_escape_len);
1331 dump_intfield(L, "low_page", enc->low_page);
1332 dump_intfield(L, "high_page", enc->high_page);
1334 dump_stringfield(L, "iconv_name", enc->iconv_name);
1336 dump_intfield(L, "char_max", enc->char_max);
1337 return ret;
1340 #if 0 /* unused */
1341 static void handle_enc(lua_State * L, struct enc *enc)
1343 struct enc *next;
1344 NESTED_TABLE(do_handle_enc, enc, 24);
1346 #endif
1348 static void handle_encmap(lua_State * L, struct encmap *map, int notdef_loc)
1350 int i;
1351 dump_intfield(L, "enccount", map->enccount);
1352 dump_intfield(L, "encmax", map->encmax);
1353 dump_intfield(L, "backmax", map->backmax);
1354 /*dump_intfield(L,"ticked", map->ticked) ; */
1355 if (map->remap != NULL) {
1356 lua_newtable(L);
1357 dump_intfield(L, "firstenc", map->remap->firstenc);
1358 dump_intfield(L, "lastenc", map->remap->lastenc);
1359 dump_intfield(L, "infont", map->remap->infont);
1360 lua_setfield(L, -2, "remap");
1362 lua_checkstack(L, 4);
1363 if (map->encmax > 0 && map->map != NULL) {
1364 lua_createtable(L, map->encmax, 1);
1365 for (i = 0; i < map->encmax; i++) {
1366 if (map->map[i] != -1) {
1367 int l = map->map[i];
1368 lua_pushnumber(L, i);
1369 if (l < notdef_loc)
1370 lua_pushnumber(L, (l + 1));
1371 else
1372 lua_pushnumber(L, l);
1373 lua_rawset(L, -3);
1376 lua_setfield(L, -2, "map");
1379 if (map->backmax > 0 && map->backmap != NULL) {
1380 lua_newtable(L);
1381 for (i = 0; i < map->backmax; i++) {
1382 if (map->backmap[i] != -1) { /* TODO: check this, because valgrind sometimes says
1383 "Conditional jump or move depends on uninitialised value(s)"
1384 needs a test file.
1386 if (i < notdef_loc)
1387 lua_pushnumber(L, (i + 1));
1388 else
1389 lua_pushnumber(L, i);
1390 lua_pushnumber(L, map->backmap[i]);
1391 lua_rawset(L, -3);
1394 lua_setfield(L, -2, "backmap");
1397 if (map->enc != NULL) {
1398 char *encname;
1399 lua_newtable(L);
1400 encname = do_handle_enc(L, map->enc);
1401 lua_setfield(L, -2, "enc");
1402 lua_pushstring(L, encname);
1403 lua_setfield(L, -2, "enc_name");
1407 static void handle_psdict(lua_State * L, struct psdict *private)
1409 int k;
1410 if (private->keys != NULL && private->values != NULL) {
1411 for (k = 0; k < private->next; k++) {
1412 lua_pushstring(L, private->keys[k]);
1413 lua_pushstring(L, private->values[k]);
1414 lua_rawset(L, -3);
1419 static void do_handle_ttflangname(lua_State * L, struct ttflangname *names)
1421 int k;
1422 dump_stringfield(L, "lang", MSLangString(names->lang));
1423 lua_checkstack(L, 4);
1424 lua_createtable(L, 0, ttf_namemax);
1425 for (k = 0; k < ttf_namemax; k++) {
1426 lua_pushstring(L, ttfnames_enum[k]);
1427 lua_pushstring(L, names->names[k]);
1428 lua_rawset(L, -3);
1430 lua_setfield(L, -2, "names");
1433 static void handle_ttflangname(lua_State * L, struct ttflangname *names)
1435 struct ttflangname *next;
1436 NESTED_TABLE(do_handle_ttflangname, names, 2);
1439 static void do_handle_anchorclass(lua_State * L, struct anchorclass *anchor)
1442 dump_stringfield(L, "name", anchor->name);
1443 dump_subtable_name(L, "lookup", anchor->subtable);
1444 dump_enumfield(L, "type", anchor->type, anchorclass_type_enum);
1445 /* uint8 has_base; */
1446 /* uint8 processed, has_mark, matches, ac_num; */
1447 /* uint8 ticked; */
1450 static void handle_anchorclass(lua_State * L, struct anchorclass *anchor)
1452 struct anchorclass *next;
1453 NESTED_TABLE(do_handle_anchorclass, anchor, 10);
1456 static void do_handle_ttf_table(lua_State * L, struct ttf_table *ttf_tab)
1459 dump_tag(L, "tag", ttf_tab->tag);
1460 dump_intfield(L, "len", ttf_tab->len);
1461 dump_intfield(L, "maxlen", ttf_tab->maxlen);
1462 dump_lstringfield(L, "data", (char *) ttf_tab->data, ttf_tab->len);
1465 static void handle_ttf_table(lua_State * L, struct ttf_table *ttf_tab)
1467 struct ttf_table *next;
1468 NESTED_TABLE(do_handle_ttf_table, ttf_tab, 4);
1471 static int do_handle_kernclass(lua_State * L, struct kernclass *kerns, const char *name)
1473 int k;
1474 int match = 0;
1475 if (name) {
1476 struct lookup_subtable *s = kerns->subtable;
1477 while (s != NULL) {
1478 if (strcmp(s->subtable_name,name)==0) {
1479 match = 1;
1480 break;
1482 s = s->next;
1484 } else {
1485 match = 1;
1487 if (!match) {
1488 return 0;
1490 lua_checkstack(L, 4);
1491 lua_createtable(L, kerns->first_cnt, 1);
1492 for (k = 0; k < kerns->first_cnt; k++) {
1493 lua_pushnumber(L, (k + 1));
1494 lua_pushstring(L, kerns->firsts[k]);
1495 lua_rawset(L, -3);
1497 lua_setfield(L, -2, "firsts");
1499 lua_createtable(L, kerns->second_cnt, 1);
1500 for (k = 0; k < kerns->second_cnt; k++) {
1501 lua_pushnumber(L, (k + 1));
1502 lua_pushstring(L, kerns->seconds[k]);
1503 lua_rawset(L, -3);
1505 lua_setfield(L, -2, "seconds");
1507 if (!name) {
1508 dump_subtable_name(L, "lookup", kerns->subtable);
1511 lua_createtable(L, kerns->second_cnt * kerns->first_cnt, 1);
1512 for (k = 0; k < (kerns->second_cnt * kerns->first_cnt); k++) {
1513 if (kerns->offsets[k] != 0) {
1514 lua_pushnumber(L, (k + 1));
1515 lua_pushnumber(L, kerns->offsets[k]);
1516 lua_rawset(L, -3);
1519 lua_setfield(L, -2, "offsets");
1520 return 1;
1523 static void handle_kernclass(lua_State * L, struct kernclass *kerns, const char *name)
1525 struct kernclass *next;
1526 NESTED_TABLE_SF(do_handle_kernclass, kerns, name, 8);
1530 #define DUMP_NUMBER_ARRAY(s,cnt,item) { \
1531 if (cnt>0 && item != NULL) { \
1532 int kk; \
1533 lua_newtable(L); \
1534 for (kk=0;kk<cnt;kk++) { \
1535 lua_pushnumber(L,(kk+1)); \
1536 lua_pushnumber(L,item[kk]); \
1537 lua_rawset(L,-3); } \
1538 lua_setfield(L,-2,s); } }
1541 #define DUMP_STRING_ARRAY(s,cnt,item) { \
1542 if (cnt>0 && item!=NULL) { \
1543 int kk; \
1544 lua_newtable(L); \
1545 for (kk=0;kk<cnt;kk++) { \
1546 lua_pushnumber(L,(kk+1)); \
1547 lua_pushstring(L,item[kk]); \
1548 lua_rawset(L,-3); } \
1549 lua_setfield(L,-2,s); } }
1551 #define DUMP_EXACT_STRING_ARRAY(s,cnt,item) { \
1552 if (cnt>0 && item!=NULL) { \
1553 int kk; \
1554 lua_newtable(L); \
1555 for (kk=0;kk<cnt;kk++) { \
1556 lua_pushnumber(L,(kk)); \
1557 lua_pushstring(L,item[kk]); \
1558 lua_rawset(L,-3); } \
1559 lua_setfield(L,-2,s); } }
1561 static void handle_fpst_rule(lua_State * L, struct fpst_rule *rule, int format)
1563 int k;
1565 if (format == pst_glyphs) {
1567 lua_newtable(L);
1568 dump_stringfield(L, "names", rule->u.glyph.names);
1569 dump_stringfield(L, "back", rule->u.glyph.back);
1570 dump_stringfield(L, "fore", rule->u.glyph.fore);
1571 lua_setfield(L, -2, fpossub_format_enum[format]);
1573 } else if (format == pst_class) {
1575 lua_newtable(L);
1576 DUMP_NUMBER_ARRAY("current", rule->u.class.ncnt,
1577 rule->u.class.nclasses);
1578 DUMP_NUMBER_ARRAY("before", rule->u.class.bcnt, rule->u.class.bclasses);
1579 DUMP_NUMBER_ARRAY("after", rule->u.class.fcnt, rule->u.class.fclasses);
1580 #if 0
1581 DUMP_NUMBER_ARRAY("allclasses", 0, rule->u.class.allclasses);
1582 #endif
1583 lua_setfield(L, -2, fpossub_format_enum[format]);
1585 } else if (format == pst_coverage) {
1587 lua_newtable(L);
1588 DUMP_STRING_ARRAY("current", rule->u.coverage.ncnt,
1589 rule->u.coverage.ncovers);
1590 DUMP_STRING_ARRAY("before", rule->u.coverage.bcnt,
1591 rule->u.coverage.bcovers);
1592 DUMP_STRING_ARRAY("after", rule->u.coverage.fcnt,
1593 rule->u.coverage.fcovers);
1594 lua_setfield(L, -2, fpossub_format_enum[format]);
1596 } else if (format == pst_reversecoverage) {
1598 lua_newtable(L);
1599 DUMP_STRING_ARRAY("current", rule->u.rcoverage.always1,
1600 rule->u.rcoverage.ncovers);
1601 DUMP_STRING_ARRAY("before", rule->u.rcoverage.bcnt,
1602 rule->u.rcoverage.bcovers);
1603 DUMP_STRING_ARRAY("after", rule->u.rcoverage.fcnt,
1604 rule->u.rcoverage.fcovers);
1605 dump_stringfield(L, "replacements", rule->u.rcoverage.replacements);
1606 lua_setfield(L, -2, fpossub_format_enum[format]);
1607 } else {
1608 fprintf(stderr, "handle_fpst_rule(): Unknown rule format: %d\n",
1609 format);
1612 if (rule->lookup_cnt > 0) {
1613 lua_newtable(L);
1614 for (k = 0; k < rule->lookup_cnt; k++) {
1615 lua_pushnumber(L, (rule->lookups[k].seq + 1));
1616 if (rule->lookups[k].lookup != NULL) {
1617 lua_pushstring(L, rule->lookups[k].lookup->lookup_name);
1618 } else {
1619 lua_pushnil(L);
1621 lua_rawset(L, -3);
1623 lua_setfield(L, -2, "lookups");
1624 } else {
1625 /*fprintf(stderr,"handle_fpst_rule(): No lookups?\n"); */
1629 static void do_handle_generic_fpst(lua_State * L, struct generic_fpst *fpst)
1631 int k;
1633 if (fpst->type > LAST_POSSUB_TYPE_ENUM) {
1634 dump_intfield(L, "type", fpst->type);
1635 } else {
1636 dump_enumfield(L, "type", fpst->type, possub_type_enum);
1638 dump_enumfield(L, "format", fpst->format, fpossub_format_enum);
1640 if (fpst->format == pst_class) {
1641 DUMP_EXACT_STRING_ARRAY("current_class", fpst->nccnt, fpst->nclass);
1642 DUMP_EXACT_STRING_ARRAY("before_class", fpst->bccnt, fpst->bclass);
1643 DUMP_EXACT_STRING_ARRAY("after_class", fpst->fccnt, fpst->fclass);
1644 } else {
1645 DUMP_STRING_ARRAY("current_class", fpst->nccnt, fpst->nclass);
1646 DUMP_STRING_ARRAY("before_class", fpst->bccnt, fpst->bclass);
1647 DUMP_STRING_ARRAY("after_class", fpst->fccnt, fpst->fclass);
1650 lua_checkstack(L, 4);
1651 if (fpst->rule_cnt > 0) {
1652 lua_createtable(L, fpst->rule_cnt, 1);
1653 for (k = 0; k < fpst->rule_cnt; k++) {
1654 lua_pushnumber(L, (k + 1));
1655 lua_newtable(L);
1656 handle_fpst_rule(L, &(fpst->rules[k]), fpst->format);
1657 lua_rawset(L, -3);
1659 lua_setfield(L, -2, "rules");
1661 /*dump_intfield (L,"ticked", fpst->ticked); */
1664 static void handle_generic_fpst(lua_State * L, struct generic_fpst *fpst)
1666 struct generic_fpst *next;
1667 int k = 1;
1668 lua_checkstack(L, 3);
1669 if (fpst->subtable != NULL && fpst->subtable->subtable_name != NULL) {
1670 lua_pushstring(L, fpst->subtable->subtable_name);
1671 } else {
1672 lua_pushnumber(L, k);
1673 k++;
1675 lua_createtable(L, 0, 10);
1676 do_handle_generic_fpst(L, fpst);
1677 lua_rawset(L, -3);
1678 next = fpst->next;
1679 while (next != NULL) {
1680 lua_checkstack(L, 3);
1681 if (next->subtable != NULL && next->subtable->subtable_name != NULL) {
1682 lua_pushstring(L, next->subtable->subtable_name);
1683 } else {
1684 lua_pushnumber(L, k);
1685 k++;
1687 lua_createtable(L, 0, 10);
1688 do_handle_generic_fpst(L, next);
1689 lua_rawset(L, -3);
1690 next = next->next;
1694 static void do_handle_otfname(lua_State * L, struct otfname *oname)
1696 dump_intfield(L, "lang", oname->lang);
1697 dump_stringfield(L, "name", oname->name);
1700 static void handle_otfname(lua_State * L, struct otfname *oname)
1702 struct otfname *next;
1703 NESTED_TABLE(do_handle_otfname, oname, 2);
1706 static void handle_MATH(lua_State * L, struct MATH *MATH)
1708 dump_intfield(L, "ScriptPercentScaleDown", MATH->ScriptPercentScaleDown);
1709 dump_intfield(L, "ScriptScriptPercentScaleDown", MATH->ScriptScriptPercentScaleDown);
1710 dump_intfield(L, "DelimitedSubFormulaMinHeight", MATH->DelimitedSubFormulaMinHeight);
1711 dump_intfield(L, "DisplayOperatorMinHeight", MATH->DisplayOperatorMinHeight);
1712 dump_intfield(L, "MathLeading", MATH->MathLeading);
1713 dump_intfield(L, "AxisHeight", MATH->AxisHeight);
1714 dump_intfield(L, "AccentBaseHeight", MATH->AccentBaseHeight);
1715 dump_intfield(L, "FlattenedAccentBaseHeight", MATH->FlattenedAccentBaseHeight);
1716 dump_intfield(L, "SubscriptShiftDown", MATH->SubscriptShiftDown);
1717 dump_intfield(L, "SubscriptTopMax", MATH->SubscriptTopMax);
1718 dump_intfield(L, "SubscriptBaselineDropMin", MATH->SubscriptBaselineDropMin);
1719 dump_intfield(L, "SuperscriptShiftUp", MATH->SuperscriptShiftUp);
1720 dump_intfield(L, "SuperscriptShiftUpCramped", MATH->SuperscriptShiftUpCramped);
1721 dump_intfield(L, "SuperscriptBottomMin", MATH->SuperscriptBottomMin);
1722 dump_intfield(L, "SuperscriptBaselineDropMax", MATH->SuperscriptBaselineDropMax);
1723 dump_intfield(L, "SubSuperscriptGapMin", MATH->SubSuperscriptGapMin);
1724 dump_intfield(L, "SuperscriptBottomMaxWithSubscript", MATH->SuperscriptBottomMaxWithSubscript);
1725 dump_intfield(L, "SpaceAfterScript", MATH->SpaceAfterScript);
1726 dump_intfield(L, "UpperLimitGapMin", MATH->UpperLimitGapMin);
1727 dump_intfield(L, "UpperLimitBaselineRiseMin", MATH->UpperLimitBaselineRiseMin);
1728 dump_intfield(L, "LowerLimitGapMin", MATH->LowerLimitGapMin);
1729 dump_intfield(L, "LowerLimitBaselineDropMin", MATH->LowerLimitBaselineDropMin);
1730 dump_intfield(L, "StackTopShiftUp", MATH->StackTopShiftUp);
1731 dump_intfield(L, "StackTopDisplayStyleShiftUp", MATH->StackTopDisplayStyleShiftUp);
1732 dump_intfield(L, "StackBottomShiftDown", MATH->StackBottomShiftDown);
1733 dump_intfield(L, "StackBottomDisplayStyleShiftDown", MATH->StackBottomDisplayStyleShiftDown);
1734 dump_intfield(L, "StackGapMin", MATH->StackGapMin);
1735 dump_intfield(L, "StackDisplayStyleGapMin", MATH->StackDisplayStyleGapMin);
1736 dump_intfield(L, "StretchStackTopShiftUp", MATH->StretchStackTopShiftUp);
1737 dump_intfield(L, "StretchStackBottomShiftDown", MATH->StretchStackBottomShiftDown);
1738 dump_intfield(L, "StretchStackGapAboveMin", MATH->StretchStackGapAboveMin);
1739 dump_intfield(L, "StretchStackGapBelowMin", MATH->StretchStackGapBelowMin);
1740 dump_intfield(L, "FractionNumeratorShiftUp", MATH->FractionNumeratorShiftUp);
1741 dump_intfield(L, "FractionNumeratorDisplayStyleShiftUp", MATH->FractionNumeratorDisplayStyleShiftUp);
1742 dump_intfield(L, "FractionDenominatorShiftDown", MATH->FractionDenominatorShiftDown);
1743 dump_intfield(L, "FractionDenominatorDisplayStyleShiftDown", MATH->FractionDenominatorDisplayStyleShiftDown);
1744 dump_intfield(L, "FractionNumeratorGapMin", MATH->FractionNumeratorGapMin);
1745 dump_intfield(L, "FractionNumeratorDisplayStyleGapMin", MATH->FractionNumeratorDisplayStyleGapMin);
1746 dump_intfield(L, "FractionRuleThickness", MATH->FractionRuleThickness);
1747 dump_intfield(L, "FractionDenominatorGapMin", MATH->FractionDenominatorGapMin);
1748 dump_intfield(L, "FractionDenominatorDisplayStyleGapMin", MATH->FractionDenominatorDisplayStyleGapMin);
1749 dump_intfield(L, "SkewedFractionHorizontalGap", MATH->SkewedFractionHorizontalGap);
1750 dump_intfield(L, "SkewedFractionVerticalGap", MATH->SkewedFractionVerticalGap);
1751 dump_intfield(L, "OverbarVerticalGap", MATH->OverbarVerticalGap);
1752 dump_intfield(L, "OverbarRuleThickness", MATH->OverbarRuleThickness);
1753 dump_intfield(L, "OverbarExtraAscender", MATH->OverbarExtraAscender);
1754 dump_intfield(L, "UnderbarVerticalGap", MATH->UnderbarVerticalGap);
1755 dump_intfield(L, "UnderbarRuleThickness", MATH->UnderbarRuleThickness);
1756 dump_intfield(L, "UnderbarExtraDescender", MATH->UnderbarExtraDescender);
1757 dump_intfield(L, "RadicalVerticalGap", MATH->RadicalVerticalGap);
1758 dump_intfield(L, "RadicalDisplayStyleVerticalGap", MATH->RadicalDisplayStyleVerticalGap);
1759 dump_intfield(L, "RadicalRuleThickness", MATH->RadicalRuleThickness);
1760 dump_intfield(L, "RadicalExtraAscender", MATH->RadicalExtraAscender);
1761 dump_intfield(L, "RadicalKernBeforeDegree", MATH->RadicalKernBeforeDegree);
1762 dump_intfield(L, "RadicalKernAfterDegree", MATH->RadicalKernAfterDegree);
1763 dump_intfield(L, "RadicalDegreeBottomRaisePercent", MATH->RadicalDegreeBottomRaisePercent);
1764 dump_intfield(L, "MinConnectorOverlap", MATH->MinConnectorOverlap);
1767 /* the handling of BASE is untested, no font */
1768 static void handle_baselangextent(lua_State * L, struct baselangextent *ble);
1770 static void do_handle_baselangextent(lua_State * L, struct baselangextent *ble)
1772 dump_tag(L, "tag", ble->lang);
1773 dump_intfield(L, "ascent", ble->ascent);
1774 dump_intfield(L, "descent", ble->descent);
1775 lua_newtable(L);
1776 handle_baselangextent(L, ble->features);
1777 lua_setfield(L, -2, "features");
1780 static void handle_baselangextent(lua_State * L, struct baselangextent *ble)
1782 struct baselangextent *next;
1783 NESTED_TABLE(do_handle_baselangextent, ble, 4);
1786 static void handle_base(lua_State * L, struct Base *Base)
1788 int i;
1789 struct basescript *next = Base->scripts;
1790 lua_newtable(L);
1791 for (i = 0; i < Base->baseline_cnt; i++) {
1792 lua_pushstring(L, make_tag_string(Base->baseline_tags[i]));
1793 lua_rawseti(L, -2, (i + 1));
1795 lua_setfield(L, -2, "tags");
1796 if (next != NULL) {
1797 lua_newtable(L);
1798 while (next != NULL) {
1799 lua_pushstring(L, make_tag_string(next->script));
1800 lua_newtable(L);
1801 dump_intfield(L, "default_baseline", (next->def_baseline + 1));
1802 lua_newtable(L);
1803 for (i = 0; i < Base->baseline_cnt; i++) {
1804 if (next->baseline_pos != NULL) /* default omitted */
1805 lua_pushnumber(L, next->baseline_pos[i]);
1806 else
1807 lua_pushnumber(L, 0);
1808 lua_rawseti(L, -2, (i + 1));
1810 lua_setfield(L, -2, "baseline");
1811 lua_newtable(L);
1812 handle_baselangextent(L, next->langs);
1813 lua_setfield(L, -2, "lang");
1814 lua_rawset(L, -3);
1815 next = next->next;
1817 lua_setfield(L, -2, "scripts");
1821 static void handle_axismap(lua_State * L, struct axismap *am)
1823 int i;
1824 lua_checkstack(L, 3);
1825 lua_newtable(L);
1826 for (i = 0; i < am->points; i++) {
1827 lua_pushnumber(L, am->blends[i]);
1828 lua_rawseti(L, -2, (i + 1));
1830 lua_setfield(L, -2, "blends");
1831 lua_newtable(L);
1832 for (i = 0; i < am->points; i++) {
1833 lua_pushnumber(L, am->designs[i]);
1834 lua_rawseti(L, -2, (i + 1));
1836 lua_setfield(L, -2, "designs");
1837 dump_realfield(L, "min", am->min);
1838 dump_realfield(L, "def", am->def);
1839 dump_realfield(L, "max", am->max);
1842 static void handle_mmset(lua_State * L, struct mmset *mm)
1844 int i;
1845 lua_newtable(L);
1846 for (i = 0; i < mm->axis_count; i++) {
1847 lua_pushstring(L, mm->axes[i]);
1848 lua_rawseti(L, -2, (i + 1));
1850 lua_setfield(L, -2, "axes");
1852 dump_intfield(L, "instance_count", mm->instance_count);
1853 /* SplineFont *normal; *//* this is the parent */
1854 if (mm->instance_count > 0) {
1855 lua_newtable(L);
1856 for (i = 0; i < mm->instance_count * mm->axis_count; i++) {
1857 lua_pushnumber(L, mm->positions[i]);
1858 lua_rawseti(L, -2, (i + 1));
1860 lua_setfield(L, -2, "positions");
1862 /* better not to do this */
1863 #if 0
1865 struct mmset *mmsave;
1866 lua_newtable(L);
1867 for (i = 0; i < mm->instance_count; i++) {
1868 lua_checkstack(L, 20);
1869 lua_createtable(L, 0, 60);
1870 mmsave = mm->instances[i]->mm;
1871 mm->instances[i]->mm = NULL;
1872 handle_splinefont(L, mm->instances[i]);
1873 mm->instances[i]->mm = mmsave;
1874 lua_rawseti(L, -2, (i + 1));
1876 lua_setfield(L, -2, "instances");
1878 #endif
1880 lua_newtable(L);
1881 for (i = 0; i < mm->instance_count; i++) {
1882 lua_pushnumber(L, mm->defweights[i]);
1883 lua_rawseti(L, -2, (i + 1));
1885 lua_setfield(L, -2, "defweights");
1888 if (mm->axismaps != NULL) {
1889 lua_newtable(L);
1890 for (i = 0; i < mm->axis_count; i++) {
1891 lua_newtable(L);
1892 handle_axismap(L, &(mm->axismaps[i]));
1893 lua_rawseti(L, -2, (i + 1));
1895 lua_setfield(L, -2, "axismaps");
1897 dump_stringfield(L, "cdv", mm->cdv);
1898 dump_stringfield(L, "ndv", mm->ndv);
1901 static void handle_splinefont(lua_State * L, struct splinefont *sf)
1903 int k;
1904 int fix_notdef = 0;
1905 int l = -1;
1907 dump_stringfield(L, "table_version", LUA_OTF_VERSION);
1908 dump_stringfield(L, "fontname", sf->fontname);
1909 dump_stringfield(L, "fullname", sf->fullname);
1910 dump_stringfield(L, "familyname", sf->familyname);
1911 dump_stringfield(L, "weight", sf->weight);
1912 dump_stringfield(L, "copyright", sf->copyright);
1913 dump_stringfield(L, "filename", sf->filename);
1914 /* dump_stringfield(L,"defbasefilename", sf->defbasefilename); */
1915 dump_stringfield(L, "version", sf->version);
1916 dump_floatfield(L, "italicangle", sf->italicangle);
1917 dump_floatfield(L, "upos", sf->upos);
1918 dump_floatfield(L, "uwidth", sf->uwidth);
1919 dump_intfield(L, "ascent", sf->ascent);
1920 dump_intfield(L, "descent", sf->descent);
1921 if (sf->uniqueid!=0) {
1922 dump_intfield(L, "uniqueid", sf->uniqueid);
1925 if (sf->glyphcnt > 0) {
1926 dump_intfield(L, "glyphcnt", sf->glyphmax - sf->glyphmin + 1);
1927 } else {
1928 dump_intfield(L, "glyphcnt", 0);
1931 dump_intfield(L, "glyphmax", sf->glyphmax - 1);
1932 dump_intfield(L, "glyphmin", sf->glyphmin);
1933 dump_intfield(L, "units_per_em", sf->units_per_em);
1935 if (sf->possub != NULL) {
1936 lua_newtable(L);
1937 handle_generic_fpst(L, sf->possub);
1938 lua_setfield(L, -2, "lookups");
1941 lua_checkstack(L, 4);
1942 lua_createtable(L, sf->glyphcnt, 0);
1944 /* This after-the-fact type discovery is not brilliant,
1945 I should really add a 'format' key in the structure */
1946 if ((sf->origname != NULL) &&
1947 (strmatch(sf->origname + strlen(sf->origname) - 4, ".pfa") == 0 ||
1948 strmatch(sf->origname + strlen(sf->origname) - 4, ".pfb") == 0)) {
1949 fix_notdef = 1;
1952 if (fix_notdef) {
1953 /* some code to ensure that the .notdef ends up in slot 0
1954 (this will actually be enforced by the CFF writer) */
1955 for (k = 0; k < sf->glyphcnt; k++) {
1956 if (sf->glyphs[k]) {
1957 if (strcmp(sf->glyphs[k]->name, ".notdef") == 0) {
1958 l = k;
1962 if (l == -1) { /* fake a .notdef at the end */
1963 l = sf->glyphcnt;
1965 for (k = 0; k < l; k++) {
1966 if (sf->glyphs[k]) {
1967 lua_pushnumber(L, (k + 1));
1968 lua_createtable(L, 0, 12);
1969 handle_splinechar(L, sf->glyphs[k], sf->hasvmetrics);
1970 lua_rawset(L, -3);
1973 if (sf->glyphs != NULL && l < sf->glyphcnt) {
1974 lua_pushnumber(L, 0);
1975 if (sf->glyphs[l]) {
1976 lua_createtable(L, 0, 12);
1977 handle_splinechar(L, sf->glyphs[l], sf->hasvmetrics);
1978 } else {
1979 lua_createtable(L, 0, 0);
1981 lua_rawset(L, -3);
1984 if ((l + 1) < sf->glyphcnt) {
1985 for (k = (l + 1); k < sf->glyphcnt; k++) {
1986 if (sf->glyphs[k]) {
1987 lua_pushnumber(L, k);
1988 lua_createtable(L, 0, 12);
1989 handle_splinechar(L, sf->glyphs[k], sf->hasvmetrics);
1990 lua_rawset(L, -3);
1994 lua_setfield(L, -2, "glyphs");
1996 /* dump_intfield(L,"changed", sf->changed); */
1997 dump_intfield(L, "hasvmetrics", sf->hasvmetrics);
1998 dump_intfield(L, "onlybitmaps", sf->onlybitmaps);
1999 dump_intfield(L, "serifcheck", sf->serifcheck);
2000 dump_intfield(L, "isserif", sf->isserif);
2001 dump_intfield(L, "issans", sf->issans);
2002 dump_intfield(L, "encodingchanged", sf->encodingchanged);
2003 dump_intfield(L, "strokedfont", sf->strokedfont);
2004 dump_intfield(L, "use_typo_metrics", sf->use_typo_metrics);
2005 dump_intfield(L, "weight_width_slope_only", sf->weight_width_slope_only);
2006 dump_intfield(L, "head_optimized_for_cleartype",
2007 sf->head_optimized_for_cleartype);
2009 dump_enumfield(L, "uni_interp", (sf->uni_interp + 1), uni_interp_enum);
2011 if (sf->map != NULL) {
2012 lua_newtable(L);
2013 handle_encmap(L, sf->map, l);
2014 lua_setfield(L, -2, "map");
2017 dump_stringfield(L, "origname", sf->origname); /* new */
2019 if (sf->private != NULL) {
2020 lua_newtable(L);
2021 handle_psdict(L, sf->private);
2022 lua_setfield(L, -2, "private");
2025 dump_stringfield(L, "xuid", sf->xuid);
2027 lua_createtable(L, 0, 40);
2028 handle_pfminfo(L, sf->pfminfo);
2029 lua_setfield(L, -2, "pfminfo");
2031 if (sf->names != NULL) {
2032 lua_newtable(L);
2033 handle_ttflangname(L, sf->names);
2034 lua_setfield(L, -2, "names");
2037 lua_createtable(L, 0, 4);
2038 dump_stringfield(L, "registry", sf->cidregistry);
2039 dump_stringfield(L, "ordering", sf->ordering);
2040 dump_intfield(L, "version", sf->cidversion);
2041 dump_intfield(L, "supplement", sf->supplement);
2042 lua_setfield(L, -2, "cidinfo");
2044 /* SplineFont *cidmaster *//* parent in a subfont */
2045 if (sf->subfontcnt > 0) {
2046 lua_createtable(L, sf->subfontcnt, 0);
2047 for (k = 0; k < sf->subfontcnt; k++) {
2048 lua_checkstack(L, 10);
2049 lua_newtable(L);
2050 handle_splinefont(L, sf->subfonts[k]);
2051 lua_rawseti(L, -2, (k + 1));
2053 lua_setfield(L, -2, "subfonts");
2056 dump_stringfield(L, "comments", sf->comments);
2057 dump_stringfield(L, "fontlog", sf->fontlog);
2059 if (sf->cvt_names != NULL) {
2060 lua_newtable(L);
2061 for (k = 0; sf->cvt_names[k] != END_CVT_NAMES; ++k) {
2062 lua_pushstring(L, sf->cvt_names[k]);
2063 lua_rawseti(L, -2, (k + 1));
2065 lua_setfield(L, -2, "cvt_names");
2068 if (sf->ttf_tables != NULL) {
2069 lua_newtable(L);
2070 handle_ttf_table(L, sf->ttf_tables);
2071 lua_setfield(L, -2, "ttf_tables");
2074 if (sf->ttf_tab_saved != NULL) {
2075 lua_newtable(L);
2076 handle_ttf_table(L, sf->ttf_tab_saved);
2077 lua_setfield(L, -2, "ttf_tab_saved");
2080 if (sf->texdata.type != tex_unset) {
2081 lua_newtable(L);
2082 dump_enumfield(L, "type", sf->texdata.type, tex_type_enum);
2083 lua_newtable(L);
2084 for (k = 0; k < 22; k++) {
2085 lua_pushnumber(L, k);
2086 lua_pushnumber(L, sf->texdata.params[k]);
2087 lua_rawset(L, -3);
2089 lua_setfield(L, -2, "params");
2090 lua_setfield(L, -2, "texdata");
2092 if (sf->anchor != NULL) {
2093 lua_newtable(L);
2094 handle_anchorclass(L, sf->anchor);
2095 lua_setfield(L, -2, "anchor_classes");
2097 if (sf->kerns != NULL) {
2098 lua_newtable(L);
2099 handle_kernclass(L, sf->kerns, NULL);
2100 lua_setfield(L, -2, "kerns");
2102 if (sf->vkerns != NULL) {
2103 lua_newtable(L);
2104 handle_kernclass(L, sf->vkerns, NULL);
2105 lua_setfield(L, -2, "vkerns");
2107 if (sf->gsub_lookups != NULL) {
2108 lua_newtable(L);
2109 handle_lookup(L, sf->gsub_lookups, sf);
2110 lua_setfield(L, -2, "gsub");
2112 if (sf->gpos_lookups != NULL) {
2113 lua_newtable(L);
2114 handle_lookup(L, sf->gpos_lookups, sf);
2115 lua_setfield(L, -2, "gpos");
2118 if (sf->mm != NULL) {
2119 lua_newtable(L);
2120 handle_mmset(L, sf->mm);
2121 lua_setfield(L, -2, "mm");
2123 dump_stringfield(L, "chosenname", sf->chosenname);
2125 if (sf->macstyle!=-1) {
2126 dump_intfield(L, "macstyle", sf->macstyle);
2128 dump_stringfield(L, "fondname", sf->fondname);
2130 dump_intfield(L, "design_size", sf->design_size);
2131 dump_intfield(L, "fontstyle_id", sf->fontstyle_id);
2133 if (sf->fontstyle_name != NULL) {
2134 lua_newtable(L);
2135 handle_otfname(L, sf->fontstyle_name);
2136 lua_setfield(L, -2, "fontstyle_name");
2139 dump_intfield(L, "design_range_bottom", sf->design_range_bottom);
2140 dump_intfield(L, "design_range_top", sf->design_range_top);
2141 dump_floatfield(L, "strokewidth", sf->strokewidth);
2143 if (sf->mark_class_cnt > 0) {
2144 lua_newtable(L);
2145 for (k = 0; k < sf->mark_class_cnt; k++) {
2146 if (sf->mark_class_names[k] != NULL) {
2147 lua_pushstring(L, sf->mark_class_names[k]);
2148 lua_pushstring(L, sf->mark_classes[k]);
2149 lua_rawset(L, -3);
2152 lua_setfield(L, -2, "mark_classes");
2155 dump_uintfield(L, "creationtime", sf->creationtime);
2156 dump_uintfield(L, "modificationtime", sf->modificationtime);
2158 dump_intfield(L, "os2_version", sf->os2_version);
2159 dump_intfield(L, "sfd_version", sf->sfd_version);
2161 if (sf->MATH != NULL) {
2162 lua_newtable(L);
2163 handle_MATH(L, sf->MATH);
2164 lua_setfield(L, -2, "math");
2167 if (sf->loadvalidation_state != 0) {
2168 int val, st;
2169 lua_newtable(L);
2170 val = 1;
2171 st = sf->loadvalidation_state;
2172 if (st & lvs_bad_ps_fontname) {
2173 lua_pushliteral(L, "bad_ps_fontname");
2174 lua_rawseti(L, -2, val++);
2176 if (st & lvs_bad_glyph_table) {
2177 lua_pushliteral(L, "bad_glyph_table");
2178 lua_rawseti(L, -2, val++);
2180 if (st & lvs_bad_cff_table) {
2181 lua_pushliteral(L, "bad_cff_table");
2182 lua_rawseti(L, -2, val++);
2184 if (st & lvs_bad_metrics_table) {
2185 lua_pushliteral(L, "bad_metrics_table");
2186 lua_rawseti(L, -2, val++);
2188 if (st & lvs_bad_cmap_table) {
2189 lua_pushliteral(L, "bad_cmap_table");
2190 lua_rawseti(L, -2, val++);
2192 if (st & lvs_bad_bitmaps_table) {
2193 lua_pushliteral(L, "bad_bitmaps_table");
2194 lua_rawseti(L, -2, val++);
2196 if (st & lvs_bad_gx_table) {
2197 lua_pushliteral(L, "bad_gx_table");
2198 lua_rawseti(L, -2, val++);
2200 if (st & lvs_bad_ot_table) {
2201 lua_pushliteral(L, "bad_ot_table");
2202 lua_rawseti(L, -2, val++);
2204 if (st & lvs_bad_os2_version) {
2205 lua_pushliteral(L, "bad_os2_version");
2206 lua_rawseti(L, -2, val++);
2208 if (st & lvs_bad_sfnt_header) {
2209 lua_pushliteral(L, "bad_sfnt_header");
2210 lua_rawseti(L, -2, val++);
2212 lua_setfield(L, -2, "validation_state");
2215 if (sf->horiz_base != NULL) {
2216 lua_newtable(L);
2217 handle_base(L, sf->horiz_base);
2218 lua_setfield(L, -2, "horiz_base");
2220 if (sf->vert_base != NULL) {
2221 lua_newtable(L);
2222 handle_base(L, sf->vert_base);
2223 lua_setfield(L, -2, "vert_base");
2225 dump_intfield(L, "extrema_bound", sf->extrema_bound);
2228 static int ff_make_table(lua_State * L)
2230 SplineFont *sf;
2231 sf = *(check_isfont(L, 1));
2232 if (sf == NULL) {
2233 lua_pushboolean(L, 0);
2234 } else {
2235 lua_createtable(L, 0, 60);
2236 handle_splinefont(L, sf);
2238 return 1;
2241 static void do_ff_info(lua_State * L, SplineFont * sf)
2243 lua_newtable(L);
2244 dump_stringfield(L, "familyname", sf->familyname);
2245 dump_stringfield(L, "fontname", sf->fontname);
2246 dump_stringfield(L, "fullname", sf->fullname);
2247 dump_floatfield(L, "italicangle", sf->italicangle);
2248 dump_stringfield(L, "version", sf->version);
2249 dump_stringfield(L, "weight", sf->weight);
2251 dump_intfield(L, "units_per_em", sf->units_per_em);
2252 /* These are not assigned in info... */
2253 /*dump_intfield(L, "design_range_bottom", sf->design_range_bottom);*/
2254 /*dump_intfield(L, "design_range_top", sf->design_range_top);*/
2255 /*dump_intfield(L, "design_size", sf->design_size);*/
2257 lua_createtable(L, 0, 40);
2258 handle_pfminfo(L, sf->pfminfo);
2259 lua_setfield(L, -2, "pfminfo");
2261 /* Do we need this ? */
2262 if (sf->names != NULL) {
2263 lua_newtable(L);
2264 handle_ttflangname(L, sf->names);
2265 lua_setfield(L, -2, "names");
2269 typedef enum {
2270 FK_table_version = 0,
2271 FK_fontname,
2272 FK_fullname,
2273 FK_familyname,
2274 FK_weight,
2275 FK_copyright,
2276 FK_filename,
2277 FK_version,
2278 FK_italicangle,
2279 FK_upos,
2280 FK_uwidth,
2281 FK_ascent,
2282 FK_descent,
2283 FK_uniqueid,
2284 FK_glyphcnt,
2285 FK_glyphmax,
2286 FK_glyphmin,
2287 FK_units_per_em,
2288 FK_lookups,
2289 FK_glyphs,
2290 FK_hasvmetrics,
2291 FK_onlybitmaps,
2292 FK_serifcheck,
2293 FK_isserif,
2294 FK_issans,
2295 FK_encodingchanged,
2296 FK_strokedfont,
2297 FK_use_typo_metrics,
2298 FK_weight_width_slope_only,
2299 FK_head_optimized_for_cleartype,
2300 FK_uni_interp,
2301 FK_map,
2302 FK_origname,
2303 FK_private,
2304 FK_xuid,
2305 FK_pfminfo,
2306 FK_names,
2307 FK_cidinfo,
2308 FK_subfonts,
2309 FK_comments,
2310 FK_fontlog,
2311 FK_cvt_names,
2312 FK_ttf_tables,
2313 FK_ttf_tab_saved,
2314 FK_texdata,
2315 FK_anchor_classes,
2316 FK_kerns,
2317 FK_vkerns,
2318 FK_gsub,
2319 FK_gpos,
2320 /* FK_sm, */ /*this was removed because AAT is not supported anymore*/
2321 FK_features,
2322 FK_mm,
2323 FK_chosenname,
2324 FK_macstyle,
2325 FK_fondname,
2326 FK_design_size,
2327 FK_fontstyle_id,
2328 FK_fontstyle_name,
2329 FK_design_range_bottom,
2330 FK_design_range_top,
2331 FK_strokewidth,
2332 FK_mark_classes,
2333 FK_creationtime,
2334 FK_modificationtime,
2335 FK_os2_version,
2336 FK_sfd_version,
2337 FK_math,
2338 FK_validation_state,
2339 FK_horiz_base,
2340 FK_vert_base,
2341 FK_extrema_bound,
2342 } font_key_values;
2344 const char *font_keys[] = {
2345 "table_version",
2346 "fontname",
2347 "fullname",
2348 "familyname",
2349 "weight",
2350 "copyright",
2351 "filename",
2352 "version",
2353 "italicangle",
2354 "upos",
2355 "uwidth",
2356 "ascent",
2357 "descent",
2358 "uniqueid",
2359 "glyphcnt",
2360 "glyphmax",
2361 "glyphmin",
2362 "units_per_em",
2363 "lookups",
2364 "glyphs",
2365 "hasvmetrics",
2366 "onlybitmaps",
2367 "serifcheck",
2368 "isserif",
2369 "issans",
2370 "encodingchanged",
2371 "strokedfont",
2372 "use_typo_metrics",
2373 "weight_width_slope_only",
2374 "head_optimized_for_cleartype",
2375 "uni_interp",
2376 "map",
2377 "origname",
2378 "private",
2379 "xuid",
2380 "pfminfo",
2381 "names",
2382 "cidinfo",
2383 "subfonts",
2384 "comments",
2385 "fontlog",
2386 "cvt_names",
2387 "ttf_tables",
2388 "ttf_tab_saved",
2389 "texdata",
2390 "anchor_classes",
2391 "kerns",
2392 "vkerns",
2393 "gsub",
2394 "gpos",
2395 "features",
2396 "mm",
2397 "chosenname",
2398 "macstyle",
2399 "fondname",
2400 "design_size",
2401 "fontstyle_id",
2402 "fontstyle_name",
2403 "design_range_bottom",
2404 "design_range_top",
2405 "strokewidth",
2406 "mark_classes",
2407 "creationtime",
2408 "modificationtime",
2409 "os2_version",
2410 "sfd_version",
2411 "math",
2412 "validation_state",
2413 "horiz_base",
2414 "vert_base",
2415 "extrema_bound",
2416 NULL
2420 typedef enum {
2421 GK_name = 0,
2422 GK_unicode,
2423 GK_boundingbox,
2424 GK_vwidth,
2425 GK_width,
2426 GK_lsidebearing,
2427 GK_class,
2428 GK_kerns,
2429 GK_vkerns,
2430 GK_dependents,
2431 GK_lookups,
2432 GK_ligatures,
2433 GK_comment,
2434 GK_anchors,
2435 GK_altuni,
2436 GK_tex_height,
2437 GK_tex_depth,
2438 GK_is_extended_shape,
2439 GK_italic_correction,
2440 GK_top_accent,
2441 GK_vert_variants,
2442 GK_horiz_variants,
2443 GK_mathkern,
2444 GK_orig_pos,
2445 } font_glyph_key_values;
2447 const char *font_glyph_keys[] = {
2448 "name",
2449 "unicode",
2450 "boundingbox",
2451 "vwidth",
2452 "width",
2453 "lsidebearing",
2454 "class",
2455 "kerns",
2456 "vkerns",
2457 "dependents",
2458 "lookups",
2459 "ligatures",
2460 "comment",
2461 "anchors",
2462 "altuni",
2463 "tex_height",
2464 "tex_depth",
2465 "is_extended_shape",
2466 "italic_correction",
2467 "top_accent",
2468 "vert_variants",
2469 "horiz_variants",
2470 "mathkern",
2471 "orig_pos",
2472 NULL
2475 static int ff_fields(lua_State * L)
2477 int i;
2478 const char **fields = NULL;
2479 if (is_userdata(L, 1, FONT_METATABLE) ||
2480 is_userdata(L, 1, FONT_SUBFONT_METATABLE)) {
2481 fields = font_keys;
2482 } else if (is_userdata(L, 1, FONT_GLYPH_METATABLE)) {
2483 fields = font_glyph_keys;
2485 if (fields != NULL) {
2486 lua_newtable(L);
2487 for (i = 0; fields[i] != NULL; i++) {
2488 lua_pushstring(L, fields[i]);
2489 lua_rawseti(L, -2, (i + 1));
2491 } else {
2492 lua_pushnil(L);
2494 return 1;
2497 static int ff_glyphs_index(lua_State * L)
2500 SplineFont *sf;
2501 int gid = 0;
2502 int l = -1;
2503 int fix_notdef = 0;
2504 lua_pushstring(L, "__sf");
2505 lua_rawget(L, 1);
2506 /* sf = *check_isfont(L, -1); */
2507 if (!(is_userdata(L, -1, FONT_METATABLE) ||
2508 is_userdata(L, -1, FONT_SUBFONT_METATABLE))) {
2509 return luaL_error(L, "fontloader.__index: expected a (sub)font userdata object\n");
2511 sf = *((SplineFont **)lua_touserdata(L, -1));
2513 lua_pop(L, 1);
2514 gid = luaL_checkinteger(L, 2);
2515 /* if (gid < sf->glyphmin || gid >= sf->glyphmax) {*/
2516 if (gid < sf->glyphmin || gid > sf->glyphmax) {
2517 return luaL_error(L, "fontloader.glyphs.__index: index is invalid\n");
2519 /* This after-the-fact type discovery is not brilliant,
2520 I should really add a 'format' key in the structure */
2521 if ((sf->origname != NULL) &&
2522 (strmatch(sf->origname + strlen(sf->origname) - 4, ".pfa") == 0 ||
2523 strmatch(sf->origname + strlen(sf->origname) - 4, ".pfb") == 0)) {
2524 fix_notdef = 1;
2526 /* some code to ensure that the .notdef ends up in slot 0
2527 (this will actually be enforced by the CFF writer) */
2528 if (fix_notdef) {
2529 l = notdef_loc(sf);
2530 /* now l is the .notdef location, adjust gid if needed */
2531 if (l == sf->glyphcnt) { /* no .notdef at all, will be created at zero */
2532 if (gid == 0) {
2533 gid = l; /* .notdef was added at end */
2534 } else {
2535 gid--; /* f.glyphs[gid] == sf->glyphs[gid-1] */
2537 } else if (l != 0) {
2538 if (gid == 0) {
2539 gid = l;
2540 } else if (gid < l) {
2541 gid--;
2545 /* push the glyph */
2546 if (sf->glyphs[gid] && sf->glyphs[gid] != (struct splinechar *)-1) {
2547 lua_ff_pushglyph(L, sf->glyphs[gid]);
2548 } else {
2549 lua_pushnil(L);
2551 return 1;
2554 static int ff_glyph_index(lua_State * L)
2556 struct splinechar *glyph;
2557 int key;
2558 glyph = *check_isglyph(L, 1);
2559 if (glyph == NULL) {
2560 return luaL_error(L, "fontloader.glyph.__index: glyph is nonexistent\n");
2562 if (lua_type(L, 2) != LUA_TSTRING) { /* 1 == 'font' */
2563 return luaL_error(L, "fontloader.glyph.__index: can only be indexed by string\n");
2565 key = luaL_checkoption(L, 2, NULL, font_glyph_keys);
2566 switch (key) {
2567 case GK_name:
2568 lua_pushstring(L, glyph->name);
2569 break;
2570 case GK_unicode:
2571 lua_pushnumber(L, glyph->unicodeenc);
2572 break;
2573 case GK_boundingbox:
2574 if (glyph->xmax == 0 && glyph->ymax == 0 && glyph->xmin == 0
2575 && glyph->ymin == 0) {
2576 DBounds bb;
2577 SplineCharFindBounds(glyph, &bb);
2578 glyph->xmin = bb.minx;
2579 glyph->ymin = bb.miny;
2580 glyph->xmax = bb.maxx;
2581 glyph->ymax = bb.maxy;
2583 lua_createtable(L, 4, 0);
2584 lua_pushnumber(L, 1);
2585 lua_pushnumber(L, glyph->xmin);
2586 lua_rawset(L, -3);
2587 lua_pushnumber(L, 2);
2588 lua_pushnumber(L, glyph->ymin);
2589 lua_rawset(L, -3);
2590 lua_pushnumber(L, 3);
2591 lua_pushnumber(L, glyph->xmax);
2592 lua_rawset(L, -3);
2593 lua_pushnumber(L, 4);
2594 lua_pushnumber(L, glyph->ymax);
2595 lua_rawset(L, -3);
2596 break;
2597 case GK_vwidth:
2598 lua_pushnumber(L, glyph->vwidth);
2599 break;
2600 case GK_width:
2601 lua_pushnumber(L, glyph->width);
2602 break;
2603 case GK_lsidebearing:
2604 lua_pushnumber(L, glyph->lsidebearing);
2605 break;
2606 case GK_class:
2607 if (glyph->glyph_class > 0) {
2608 lua_pushstring(L, glyph_class_enum[glyph->glyph_class]);
2609 } else {
2610 lua_pushnil(L);
2612 break;
2613 case GK_kerns:
2614 if (glyph->kerns != NULL) {
2615 lua_newtable(L);
2616 handle_kernpair(L, glyph->kerns);
2617 } else {
2618 lua_pushnil(L);
2620 break;
2621 case GK_vkerns:
2622 if (glyph->vkerns != NULL) {
2623 lua_newtable(L);
2624 handle_kernpair(L, glyph->vkerns);
2625 } else {
2626 lua_pushnil(L);
2628 break;
2629 case GK_dependents:
2630 if (glyph->dependents != NULL) {
2631 lua_newtable(L);
2632 handle_splinecharlist(L, glyph->dependents);
2633 } else {
2634 lua_pushnil(L);
2636 break;
2637 case GK_lookups:
2638 if (glyph->possub != NULL) {
2639 lua_newtable(L);
2640 handle_generic_pst(L, glyph->possub);
2641 } else {
2642 lua_pushnil(L);
2644 break;
2645 case GK_ligatures:
2646 if (glyph->ligofme != NULL) {
2647 lua_newtable(L);
2648 handle_liglist(L, glyph->ligofme);
2649 } else {
2650 lua_pushnil(L);
2652 break;
2653 case GK_comment:
2654 lua_pushstring(L, glyph->comment);
2655 break;
2656 case GK_anchors:
2657 if (glyph->anchor != NULL) {
2658 lua_newtable(L);
2659 handle_anchorpoint(L, glyph->anchor);
2660 } else {
2661 lua_pushnil(L);
2663 break;
2664 case GK_altuni:
2665 if (glyph->altuni != NULL) {
2666 lua_newtable(L);
2667 handle_altuni(L, glyph->altuni);
2668 } else {
2669 lua_pushnil(L);
2671 break;
2672 case GK_tex_height:
2673 if (glyph->tex_height != TEX_UNDEF) {
2674 lua_pushnumber(L, glyph->tex_height);
2675 } else {
2676 lua_pushnil(L);
2678 break;
2679 case GK_tex_depth:
2680 if (glyph->tex_height != TEX_UNDEF) {
2681 lua_pushnumber(L, glyph->tex_depth);
2682 } else {
2683 lua_pushnil(L);
2685 break;
2686 case GK_is_extended_shape:
2687 lua_pushnumber(L, glyph->is_extended_shape);
2688 break;
2689 case GK_italic_correction:
2690 if (glyph->italic_correction != TEX_UNDEF) {
2691 lua_pushnumber(L, glyph->italic_correction);
2692 } else {
2693 lua_pushnil(L);
2695 break;
2696 case GK_top_accent:
2697 if (glyph->top_accent_horiz != TEX_UNDEF) {
2698 lua_pushnumber(L, glyph->top_accent_horiz);
2699 } else {
2700 lua_pushnil(L);
2702 break;
2703 case GK_vert_variants:
2704 if (glyph->vert_variants != NULL) {
2705 lua_newtable(L);
2706 handle_glyphvariants(L, glyph->vert_variants);
2707 } else {
2708 lua_pushnil(L);
2710 break;
2711 case GK_horiz_variants:
2712 if (glyph->horiz_variants != NULL) {
2713 lua_newtable(L);
2714 handle_glyphvariants(L, glyph->horiz_variants);
2715 } else {
2716 lua_pushnil(L);
2718 break;
2719 case GK_mathkern:
2720 if (glyph->mathkern != NULL) {
2721 lua_newtable(L);
2722 handle_mathkern(L, glyph->mathkern);
2723 } else {
2724 lua_pushnil(L);
2726 break;
2727 case GK_orig_pos:
2728 if (glyph->orig_pos>=0) {
2729 lua_pushnumber(L, glyph->orig_pos);
2730 } else {
2731 lua_pushnil(L);
2733 break;
2734 default:
2735 lua_pushnil(L);
2737 return 1;
2740 static int ff_index(lua_State * L)
2742 SplineFont *sf;
2743 int k, key;
2744 /* sf = *check_isfont(L, 1); */
2745 if (!(is_userdata(L, 1, FONT_METATABLE) ||
2746 is_userdata(L, 1, FONT_SUBFONT_METATABLE))) {
2747 return luaL_error(L, "fontloader.__index: expected a (sub)font userdata object\n");
2749 sf = *((SplineFont **)lua_touserdata(L, 1));
2751 if (sf == NULL) {
2752 lua_pushnil(L);
2753 return 1;
2755 if (lua_type(L, 2) != LUA_TSTRING) { /* 1 == 'font' */
2756 return luaL_error(L, "fontloader.__index: can only be indexed by string\n");
2758 key = luaL_checkoption(L, 2, NULL, font_keys);
2759 switch (key) {
2760 case FK_table_version:
2761 lua_pushstring(L, LUA_OTF_VERSION);
2762 break;
2763 case FK_fontname:
2764 lua_pushstring(L, sf->fontname);
2765 break;
2766 case FK_fullname:
2767 lua_pushstring(L, sf->fullname);
2768 break;
2769 case FK_familyname:
2770 lua_pushstring(L, sf->familyname);
2771 break;
2772 case FK_weight:
2773 lua_pushstring(L, sf->weight);
2774 break;
2775 case FK_copyright:
2776 lua_pushstring(L, sf->copyright);
2777 break;
2778 case FK_filename:
2779 lua_pushstring(L, sf->filename);
2780 break;
2781 case FK_version:
2782 lua_pushstring(L, sf->version);
2783 break;
2784 case FK_italicangle:
2785 lua_pushnumber(L, sf->italicangle);
2786 break;
2787 case FK_upos:
2788 lua_pushnumber(L, sf->upos);
2789 break;
2790 case FK_uwidth:
2791 lua_pushnumber(L, sf->uwidth);
2792 break;
2793 case FK_ascent:
2794 lua_pushnumber(L, sf->ascent);
2795 break;
2796 case FK_descent:
2797 lua_pushnumber(L, sf->descent);
2798 break;
2799 case FK_uniqueid:
2800 lua_pushnumber(L, sf->uniqueid);
2801 break;
2802 case FK_glyphcnt:
2803 if (sf->glyphcnt > 0) {
2804 lua_pushnumber(L, sf->glyphmax - sf->glyphmin + 1);
2805 } else {
2806 lua_pushnumber(L, 0);
2808 break;
2809 case FK_glyphmax:
2810 lua_pushnumber(L, sf->glyphmax - 1);
2811 break;
2812 case FK_glyphmin:
2813 lua_pushnumber(L, sf->glyphmin);
2814 break;
2815 case FK_units_per_em:
2816 lua_pushnumber(L, sf->units_per_em);
2817 break;
2818 case FK_lookups:
2819 if (sf->possub != NULL) {
2820 lua_newtable(L);
2821 handle_generic_fpst(L, sf->possub);
2822 } else {
2823 lua_pushnil(L);
2825 break;
2826 case FK_glyphs:
2827 lua_newtable(L); /* the virtual glyph table */
2828 lua_pushstring(L, "__sf");
2829 lua_pushvalue(L, 1); /* that is our font */
2830 lua_rawset(L, -3);
2831 luaL_getmetatable(L, FONT_GLYPHS_METATABLE);
2832 lua_setmetatable(L, -2); /* assign the metatable */
2833 break;
2834 case FK_hasvmetrics:
2835 lua_pushnumber(L, sf->hasvmetrics);
2836 break;
2837 case FK_onlybitmaps:
2838 lua_pushnumber(L, sf->onlybitmaps);
2839 break;
2840 case FK_serifcheck:
2841 lua_pushnumber(L, sf->serifcheck);
2842 break;
2843 case FK_isserif:
2844 lua_pushnumber(L, sf->isserif);
2845 break;
2846 case FK_issans:
2847 lua_pushnumber(L, sf->issans);
2848 break;
2849 case FK_encodingchanged:
2850 lua_pushnumber(L, sf->encodingchanged);
2851 break;
2852 case FK_strokedfont:
2853 lua_pushnumber(L, sf->strokedfont);
2854 break;
2855 case FK_use_typo_metrics:
2856 lua_pushnumber(L, sf->use_typo_metrics);
2857 break;
2858 case FK_weight_width_slope_only:
2859 lua_pushnumber(L, sf->weight_width_slope_only);
2860 break;
2861 case FK_head_optimized_for_cleartype:
2862 lua_pushnumber(L, sf->head_optimized_for_cleartype);
2863 break;
2864 case FK_uni_interp:
2865 lua_pushstring(L, uni_interp_enum[(sf->uni_interp + 1)]);
2866 break;
2867 case FK_map:
2868 if (sf->map != NULL) {
2869 lua_newtable(L);
2870 handle_encmap(L, sf->map, notdef_loc(sf));
2871 } else {
2872 lua_pushnil(L);
2874 break;
2875 case FK_origname:
2876 lua_pushstring(L, sf->origname);
2877 break;
2878 case FK_private:
2879 if (sf->private != NULL) {
2880 lua_newtable(L);
2881 handle_psdict(L, sf->private);
2882 } else {
2883 lua_pushnil(L);
2885 break;
2886 case FK_xuid:
2887 lua_pushstring(L, sf->xuid);
2888 break;
2889 case FK_pfminfo:
2890 lua_createtable(L, 0, 40);
2891 handle_pfminfo(L, sf->pfminfo);
2892 break;
2893 case FK_names:
2894 if (sf->names != NULL) {
2895 lua_newtable(L);
2896 handle_ttflangname(L, sf->names);
2897 } else {
2898 lua_pushnil(L);
2900 break;
2901 case FK_cidinfo:
2902 lua_createtable(L, 0, 4);
2903 dump_stringfield(L, "registry", sf->cidregistry);
2904 dump_stringfield(L, "ordering", sf->ordering);
2905 dump_intfield(L, "version", sf->cidversion);
2906 dump_intfield(L, "supplement", sf->supplement);
2907 break;
2908 case FK_subfonts:
2909 if (sf->subfontcnt > 0) {
2910 lua_createtable(L, sf->subfontcnt, 0);
2911 for (k = 0; k < sf->subfontcnt; k++) {
2912 lua_ff_pushsubfont(L, sf->subfonts[k]);
2913 lua_rawseti(L, -2, (k + 1));
2915 } else {
2916 lua_pushnil(L);
2918 break;
2919 case FK_comments:
2920 lua_pushstring(L, sf->comments);
2921 break;
2922 case FK_fontlog:
2923 lua_pushstring(L, sf->fontlog);
2924 break;
2925 case FK_cvt_names:
2926 if (sf->cvt_names != NULL) {
2927 lua_newtable(L);
2928 for (k = 0; sf->cvt_names[k] != END_CVT_NAMES; ++k) {
2929 lua_pushstring(L, sf->cvt_names[k]);
2930 lua_rawseti(L, -2, (k + 1));
2932 } else {
2933 lua_pushnil(L);
2935 break;
2936 case FK_ttf_tables:
2937 if (sf->ttf_tables != NULL) {
2938 lua_newtable(L);
2939 handle_ttf_table(L, sf->ttf_tables);
2940 } else {
2941 lua_pushnil(L);
2943 break;
2944 case FK_ttf_tab_saved:
2945 if (sf->ttf_tab_saved != NULL) {
2946 lua_newtable(L);
2947 handle_ttf_table(L, sf->ttf_tab_saved);
2948 } else {
2949 lua_pushnil(L);
2951 break;
2952 case FK_texdata:
2953 if (sf->texdata.type != tex_unset) {
2954 lua_newtable(L);
2955 dump_enumfield(L, "type", sf->texdata.type, tex_type_enum);
2956 lua_newtable(L);
2957 for (k = 0; k < 22; k++) {
2958 lua_pushnumber(L, k);
2959 lua_pushnumber(L, sf->texdata.params[k]);
2960 lua_rawset(L, -3);
2962 lua_setfield(L, -2, "params");
2963 } else {
2964 lua_pushnil(L);
2966 break;
2967 case FK_anchor_classes:
2968 if (sf->anchor != NULL) {
2969 lua_newtable(L);
2970 handle_anchorclass(L, sf->anchor);
2971 } else {
2972 lua_pushnil(L);
2974 break;
2975 case FK_kerns:
2976 if (sf->kerns != NULL) {
2977 lua_newtable(L);
2978 handle_kernclass(L, sf->kerns, NULL);
2979 } else {
2980 lua_pushnil(L);
2982 break;
2983 case FK_vkerns:
2984 if (sf->vkerns != NULL) {
2985 lua_newtable(L);
2986 handle_kernclass(L, sf->vkerns, NULL);
2987 } else {
2988 lua_pushnil(L);
2990 break;
2991 case FK_gsub:
2992 if (sf->gsub_lookups != NULL) {
2993 lua_newtable(L);
2994 handle_lookup(L, sf->gsub_lookups, sf);
2995 } else {
2996 lua_pushnil(L);
2998 break;
2999 case FK_gpos:
3000 if (sf->gpos_lookups != NULL) {
3001 lua_newtable(L);
3002 handle_lookup(L, sf->gpos_lookups, sf);
3003 } else {
3004 lua_pushnil(L);
3006 break;
3007 case FK_mm:
3008 if (sf->mm != NULL) {
3009 lua_newtable(L);
3010 handle_mmset(L, sf->mm);
3011 } else {
3012 lua_pushnil(L);
3014 break;
3015 case FK_chosenname:
3016 lua_pushstring(L, sf->chosenname);
3017 break;
3018 case FK_macstyle:
3019 lua_pushnumber(L, sf->macstyle);
3020 break;
3021 case FK_fondname:
3022 lua_pushstring(L, sf->fondname);
3023 break;
3024 case FK_design_size:
3025 lua_pushnumber(L, sf->design_size);
3026 break;
3027 case FK_fontstyle_id:
3028 lua_pushnumber(L, sf->fontstyle_id);
3029 break;
3030 case FK_fontstyle_name:
3031 if (sf->fontstyle_name != NULL) {
3032 lua_newtable(L);
3033 handle_otfname(L, sf->fontstyle_name);
3034 } else {
3035 lua_pushnil(L);
3037 break;
3038 case FK_design_range_bottom:
3039 lua_pushnumber(L, sf->design_range_bottom);
3040 break;
3041 case FK_design_range_top:
3042 lua_pushnumber(L, sf->design_range_top);
3043 break;
3044 case FK_strokewidth:
3045 lua_pushnumber(L, sf->strokewidth);
3046 break;
3047 case FK_mark_classes:
3048 if (sf->mark_class_cnt > 0) {
3049 lua_newtable(L);
3050 for (k = 0; k < sf->mark_class_cnt; k++) {
3051 if (sf->mark_class_names[k] != NULL) {
3052 lua_pushstring(L, sf->mark_class_names[k]);
3053 lua_pushstring(L, sf->mark_classes[k]);
3054 lua_rawset(L, -3);
3057 } else {
3058 lua_pushnil(L);
3060 break;
3061 case FK_creationtime:
3062 lua_pushnumber(L, sf->creationtime);
3063 break;
3064 case FK_modificationtime:
3065 lua_pushnumber(L, sf->modificationtime);
3066 break;
3067 case FK_os2_version:
3068 lua_pushnumber(L, sf->os2_version);
3069 break;
3070 case FK_sfd_version:
3071 lua_pushnumber(L, sf->sfd_version);
3072 break;
3073 case FK_math:
3074 if (sf->MATH != NULL) {
3075 lua_newtable(L);
3076 handle_MATH(L, sf->MATH);
3077 } else {
3078 lua_pushnil(L);
3080 break;
3081 case FK_validation_state:
3082 if (sf->loadvalidation_state != 0) {
3083 int val, st;
3084 lua_newtable(L);
3085 val = 1;
3086 st = sf->loadvalidation_state;
3087 if (st & lvs_bad_ps_fontname) {
3088 lua_pushliteral(L, "bad_ps_fontname");
3089 lua_rawseti(L, -2, val++);
3091 if (st & lvs_bad_glyph_table) {
3092 lua_pushliteral(L, "bad_glyph_table");
3093 lua_rawseti(L, -2, val++);
3095 if (st & lvs_bad_cff_table) {
3096 lua_pushliteral(L, "bad_cff_table");
3097 lua_rawseti(L, -2, val++);
3099 if (st & lvs_bad_metrics_table) {
3100 lua_pushliteral(L, "bad_metrics_table");
3101 lua_rawseti(L, -2, val++);
3103 if (st & lvs_bad_cmap_table) {
3104 lua_pushliteral(L, "bad_cmap_table");
3105 lua_rawseti(L, -2, val++);
3107 if (st & lvs_bad_bitmaps_table) {
3108 lua_pushliteral(L, "bad_bitmaps_table");
3109 lua_rawseti(L, -2, val++);
3111 if (st & lvs_bad_gx_table) {
3112 lua_pushliteral(L, "bad_gx_table");
3113 lua_rawseti(L, -2, val++);
3115 if (st & lvs_bad_ot_table) {
3116 lua_pushliteral(L, "bad_ot_table");
3117 lua_rawseti(L, -2, val++);
3119 if (st & lvs_bad_os2_version) {
3120 lua_pushliteral(L, "bad_os2_version");
3121 lua_rawseti(L, -2, val++);
3123 if (st & lvs_bad_sfnt_header) {
3124 lua_pushliteral(L, "bad_sfnt_header");
3125 lua_rawseti(L, -2, val++);
3127 } else {
3128 lua_pushnil(L);
3130 break;
3131 case FK_horiz_base:
3132 if (sf->horiz_base != NULL) {
3133 lua_newtable(L);
3134 handle_base(L, sf->horiz_base);
3135 } else {
3136 lua_pushnil(L);
3138 break;
3139 case FK_vert_base:
3140 if (sf->vert_base != NULL) {
3141 lua_newtable(L);
3142 handle_base(L, sf->vert_base);
3143 } else {
3144 lua_pushnil(L);
3146 break;
3147 case FK_extrema_bound:
3148 lua_pushnumber(L, sf->extrema_bound);
3149 break;
3150 default:
3151 /* can't actually happen, |luaL_checkoption| raises an error instead */
3152 lua_pushnil(L);
3153 break;
3155 return 1;
3158 static int ff_info(lua_State * L)
3160 SplineFont *sf;
3161 FILE *l;
3162 int i;
3163 const char *fontname;
3164 char *fontnamecopy;
3165 int openflags = 1;
3166 fontname = luaL_checkstring(L, 1);
3167 if (!strlen(fontname)) {
3168 lua_pushnil(L);
3169 lua_pushfstring(L, "font loading failed: empty string given\n", fontname);
3170 return 2;
3172 /* test fontname for existance */
3173 if ((l = fopen(fontname, "r"))) {
3174 recorder_record_input(fontname);
3175 fclose(l);
3176 } else {
3177 lua_pushnil(L);
3178 lua_pushfstring(L, "font loading failed for %s (read error)\n", fontname);
3179 return 2;
3181 gww_error_count = 0;
3182 fontnamecopy = xstrdup(fontname);
3183 sf = ReadSplineFontInfo(fontnamecopy, openflags);
3184 free(fontnamecopy);
3185 if (gww_error_count > 0)
3186 gwwv_errors_free();
3188 if (sf == NULL) {
3189 lua_pushnil(L);
3190 lua_pushfstring(L, "font loading failed for %s\n", fontname);
3191 return 2;
3192 } else {
3193 if (sf->next != NULL) {
3194 SplineFont *sf_next;
3195 i = 1;
3196 lua_newtable(L);
3197 while (sf) {
3198 do_ff_info(L, sf);
3199 lua_rawseti(L, -2, i);
3200 i++;
3201 sf_next = sf->next;
3202 EncMapFree(sf->map);
3203 SplineFontFree(sf);
3204 sf = sf_next;
3206 } else {
3207 do_ff_info(L, sf);
3208 EncMapFree(sf->map);
3209 SplineFontFree(sf);
3212 return 1;
3215 static void ff_do_cff(SplineFont * sf, char *filename, unsigned char **buf,
3216 int *bufsiz)
3218 FILE *f;
3219 int32 *bsizes = NULL;
3220 int flags = ps_flag_nocffsugar + ps_flag_nohints;
3221 EncMap *map;
3223 map = EncMap1to1(sf->glyphcnt);
3225 if (WriteTTFFont
3226 (filename, sf, ff_cff, bsizes, bf_none, flags, map, ly_fore)) {
3227 /* success */
3228 f = fopen(filename, "rb");
3229 recorder_record_input(filename);
3230 readbinfile(f, buf, bufsiz);
3231 /*fprintf(stdout,"\n%s => CFF, size: %d\n", sf->filename, *bufsiz); */
3232 fclose(f);
3233 return;
3235 /* snprintf(errmsg, 255, "%s => CFF, failed", sf->filename); */
3236 /* normal_error("fontloader",errmsg); */ /* TODO */
3237 fprintf(stdout,"%s => CFF, failed", sf->filename);
3238 exit(EXIT_FAILURE);
3241 /* exported for writecff.c */
3243 int ff_createcff(char *file, unsigned char **buf, int *bufsiz)
3245 SplineFont *sf;
3246 int k;
3247 char s[] = "tempfile.cff";
3248 int openflags = 1;
3249 int notdefpos = 0;
3250 sf = ReadSplineFont(file, openflags);
3251 if (sf) {
3252 /* this is not the best way. nicer to have no temp file at all */
3253 ff_do_cff(sf, s, buf, bufsiz);
3254 for (k = 0; k < sf->glyphcnt; k++) {
3255 if (sf->glyphs[k] && strcmp(sf->glyphs[k]->name, ".notdef") == 0) {
3256 notdefpos = k;
3257 break;
3260 remove(s);
3261 EncMapFree(sf->map);
3262 SplineFontFree(sf);
3264 return notdefpos;
3267 int ff_get_ttc_index(char *ffname, char *psname)
3269 SplineFont *sf;
3270 int i = 0;
3271 int openflags = 1;
3272 int index = -1;
3274 sf = ReadSplineFontInfo((char *) ffname, openflags);
3275 if (sf == NULL) {
3276 /* normal_error("fontloader","font loading failed unexpectedly"); */ /* TODO */
3277 fprintf(stdout,"font loading failed unexpectedly\n");
3278 exit(EXIT_FAILURE);
3280 while (sf != NULL) {
3281 if (strcmp(sf->fontname, psname) == 0) {
3282 index = i;
3284 i++;
3285 sf = sf->next;
3287 if (index>=0)
3288 return (i-index-1);
3289 return -1;
3292 static struct luaL_Reg fllib[] = {
3293 {"open", ff_open},
3294 {"info", ff_info},
3295 {"close", ff_close},
3296 {"fields", ff_fields},
3297 {"apply_afmfile", ff_apply_afmfile},
3298 {"apply_featurefile", ff_apply_featurefile},
3299 {"to_table", ff_make_table},
3300 {NULL, NULL}
3303 static const struct luaL_Reg fflib_m[] = {
3304 {"__gc", ff_close}, /* doesnt work yet! */
3305 {"__index", ff_index},
3306 {NULL, NULL} /* sentinel */
3309 int luaopen_ff(lua_State * L)
3311 static char coord_sep_string[] = ",";
3312 static char SaveTablesPref_string[] = "VORG,JSTF,acnt,bsln,fdsc,fmtx,hsty,just,trak,Zapf,LINO";
3313 InitSimpleStuff();
3314 setlocale(LC_ALL, "C"); /* undo whatever InitSimpleStuff has caused */
3315 coord_sep = coord_sep_string;
3316 FF_SetUiInterface(&luaui_interface);
3317 default_encoding = FindOrMakeEncoding("ISO8859-1");
3318 SaveTablesPref = SaveTablesPref_string;
3319 luaL_newmetatable(L, FONT_METATABLE);
3320 luaL_register(L, NULL, fflib_m);
3322 /* virtual subfont table */
3323 luaL_newmetatable(L, FONT_SUBFONT_METATABLE);
3324 lua_pushstring(L, "__index");
3325 lua_pushcfunction(L, ff_index);
3326 lua_rawset(L, -3);
3327 lua_pop(L, 1);
3328 /* virtual glyphs table */
3329 luaL_newmetatable(L, FONT_GLYPHS_METATABLE);
3330 lua_pushstring(L, "__index");
3331 lua_pushcfunction(L, ff_glyphs_index);
3332 lua_rawset(L, -3);
3333 lua_pop(L, 1);
3334 /* virtual glyph table */
3335 luaL_newmetatable(L, FONT_GLYPH_METATABLE);
3336 lua_pushstring(L, "__index");
3337 lua_pushcfunction(L, ff_glyph_index);
3338 lua_rawset(L, -3);
3339 lua_pop(L, 1);
3341 luaL_openlib(L, "fontloader", fllib, 0);
3343 return 1;