sinc with TL rev. 38618.
[luatex.git] / source / texk / web2c / luatexdir / luafontloader / src / luafflib.c
blobf932c3d9946ad5a14882f8af898fdba321751a39
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(),
92 static const char *anchor_type_enum[] = {
93 "mark", "basechar", "baselig", "basemark", "centry", "cexit", "max", NULL
96 #define MAX_ANCHOR_TYPE 7
98 static const char *anchorclass_type_enum[] = {
99 "mark", "mkmk", "curs", "mklg", NULL
102 static const char *glyph_class_enum[] = {
103 "automatic", "none", "base", "ligature", "mark", "component", NULL
106 static const char *ttfnames_enum[ttf_namemax] = {
107 "copyright", "family", "subfamily", "uniqueid",
108 "fullname", "version", "postscriptname", "trademark",
109 "manufacturer", "designer", "descriptor", "venderurl",
110 "designerurl", "license", "licenseurl", "idontknow",
111 "preffamilyname", "prefmodifiers", "compatfull", "sampletext",
112 "cidfindfontname", "wwsfamily", "wwssubfamily"
115 static const char *fpossub_format_enum[] = {
116 "glyphs", "class", "coverage", "reversecoverage", NULL
119 static const char *tex_type_enum[4] = { "unset", "text", "math", "mathext" };
121 /* has an offset of 1, ui_none = 0. */
122 static const char *uni_interp_enum[9] = {
123 "unset", "none", "adobe", "greek", "japanese",
124 "trad_chinese", "simp_chinese", "korean", "ams"
127 #define check_isfont(L,b) (SplineFont **)luaL_checkudata(L,b,FONT_METATABLE)
128 #define check_isglyph(L,b) (struct splinechar **)luaL_checkudata(L,b,FONT_GLYPH_METATABLE)
130 /* forward declarations */
131 static void handle_generic_pst(lua_State * L, struct generic_pst *pst);
132 static void handle_generic_fpst(lua_State * L, struct generic_fpst *fpst);
133 static void handle_kernclass(lua_State * L, struct kernclass *kerns, const char *name);
134 static void handle_splinefont(lua_State * L, struct splinefont *sf);
135 static void handle_kernpair(lua_State * L, struct kernpair *kp);
136 static void handle_liglist(lua_State * L, struct liglist *ligofme);
137 static void handle_anchorpoint(lua_State * L, struct anchorpoint *anchor);
139 static int is_userdata(lua_State *L, int b, const char *utype)
141 if (lua_type(L,b) == LUA_TUSERDATA) {
142 lua_getmetatable(L, b);
143 luaL_getmetatable(L, utype);
144 if (lua_compare(L, -2, -1, LUA_OPEQ)) {
145 lua_pop(L,2);
146 return 1;
148 lua_pop(L,2);
150 return 0;
155 static void lua_ff_pushfont(lua_State * L, SplineFont * sf)
157 SplineFont **a;
158 if (sf == NULL) {
159 lua_pushnil(L);
160 } else {
161 a = lua_newuserdata(L, sizeof(SplineFont *));
162 *a = sf;
163 luaL_getmetatable(L, FONT_METATABLE);
164 lua_setmetatable(L, -2);
166 return;
169 static void lua_ff_pushsubfont(lua_State * L, SplineFont * sf)
171 SplineFont **a;
172 if (sf == NULL) {
173 lua_pushnil(L);
174 } else {
175 a = lua_newuserdata(L, sizeof(SplineFont *));
176 *a = sf;
177 luaL_getmetatable(L, FONT_SUBFONT_METATABLE);
178 lua_setmetatable(L, -2);
180 return;
183 static void lua_ff_pushglyph(lua_State * L, struct splinechar *sc)
185 struct splinechar **a;
186 if (sc == NULL) {
187 lua_pushnil(L);
188 } else {
189 a = lua_newuserdata(L, sizeof(struct splinechar *));
190 *a = sc;
191 luaL_getmetatable(L, FONT_GLYPH_METATABLE);
192 lua_setmetatable(L, -2);
194 return;
198 static int ff_open(lua_State * L)
200 SplineFont *sf;
201 const char *fontname;
202 FILE *l;
203 char s[511];
204 size_t len;
205 int args, i;
206 int openflags = 1 + 4;
207 fontname = luaL_checkstring(L, 1);
208 /* test fontname for existance */
209 if ((l = fopen(fontname, "r"))) {
210 recorder_record_input(fontname);
211 fclose(l);
212 } else {
213 lua_pushnil(L);
214 lua_pushfstring(L, "font loading failed for %s (read error)\n",
215 fontname);
216 return 2;
218 args = lua_gettop(L);
219 if (args >= 2 && lua_isstring(L, 2)) {
220 if (*(fontname + strlen(fontname)) != ')') {
221 /* possibly fails for embedded parens in the font name */
222 snprintf(s, 511, "%s(%s)", fontname, lua_tolstring(L, 2, &len));
223 if (len == 0) {
224 snprintf(s, 511, "%s", fontname);
227 } else {
228 snprintf(s, 511, "%s", fontname);
230 if (strlen(s) > 0) {
231 gww_error_count = 0;
232 sf = ReadSplineFont((char *) s, openflags);
233 if (sf == NULL) {
234 lua_pushnil(L);
235 lua_pushfstring(L, "font loading failed for %s\n", s);
236 if (gww_error_count > 0) {
237 for (i = 0; i < gww_error_count; i++) {
238 lua_pushstring(L, gww_errors[i]);
239 lua_concat(L, 2);
241 gwwv_errors_free();
243 } else {
244 FVAppend(_FontViewCreate(sf));
245 lua_ff_pushfont(L, sf);
246 if (gww_error_count > 0) {
247 lua_newtable(L);
248 for (i = 0; i < gww_error_count; i++) {
249 lua_pushstring(L, gww_errors[i]);
250 lua_rawseti(L, -2, (i + 1));
252 gwwv_errors_free();
253 } else {
254 lua_pushnil(L);
257 } else {
258 lua_pushnil(L);
259 lua_pushfstring(L, "font loading failed: empty string given\n",
260 fontname);
262 return 2;
266 static int ff_close(lua_State * L)
268 SplineFont **sf;
269 /*fputs("ff_close called",stderr); */
270 sf = check_isfont(L, 1);
271 if (*sf != NULL) {
272 if ((*sf)->fv) { /* condition might be improved */
273 FontViewClose((*sf)->fv);
274 } else {
275 EncMapFree((*sf)->map);
276 SplineFontFree(*sf);
278 *sf = NULL;
280 return 0;
283 static int notdef_loc(SplineFont * sf)
285 int k;
286 int l = -1;
287 for (k = 0; k < sf->glyphcnt; k++) {
288 if (sf->glyphs[k]) {
289 if (strcmp(sf->glyphs[k]->name, ".notdef") == 0) {
290 l = k;
294 if (l == -1)
295 l = sf->glyphcnt;
296 return l;
299 static int ff_apply_featurefile(lua_State * L)
301 SplineFont **sf;
302 char *fname;
303 sf = check_isfont(L, 1);
304 fname = xstrdup(luaL_checkstring(L, 2));
305 SFApplyFeatureFilename(*sf, fname);
306 free(fname);
307 if (gww_error_count > 0) {
308 int i;
309 lua_newtable(L);
310 for (i = 0; i < gww_error_count; i++) {
311 lua_pushstring(L, gww_errors[i]);
312 lua_rawseti(L, -2, (i + 1));
314 gwwv_errors_free();
315 } else {
316 lua_pushnil(L);
318 return 1;
321 static int ff_apply_afmfile(lua_State * L)
323 SplineFont **sf;
324 const char *fname;
325 sf = check_isfont(L, 1);
326 fname = luaL_checkstring(L, 2);
327 CheckAfmOfPostscript(*sf, fname, (*sf)->map);
328 if (gww_error_count > 0) {
329 int i;
330 lua_newtable(L);
331 for (i = 0; i < gww_error_count; i++) {
332 lua_pushstring(L, gww_errors[i]);
333 lua_rawseti(L, -2, (i + 1));
335 gwwv_errors_free();
336 } else {
337 lua_pushnil(L);
339 return 1;
344 static void dump_intfield(lua_State * L, const char *name, long int field)
346 lua_checkstack(L, 2);
347 lua_pushstring(L, name);
348 lua_pushnumber(L, field);
349 lua_rawset(L, -3);
352 static void dump_uintfield(lua_State * L, const char *name, unsigned int field)
354 lua_checkstack(L, 2);
355 lua_pushstring(L, name);
356 lua_pushnumber(L, field);
357 lua_rawset(L, -3);
360 static void dump_realfield(lua_State * L, const char *name, real field)
362 lua_checkstack(L, 2);
363 lua_pushstring(L, name);
364 lua_pushnumber(L, field);
365 lua_rawset(L, -3);
369 #define dump_cond_intfield(a,b,c) if ((c)!=0) { dump_intfield ((a),(b),(c)); }
372 static void dump_stringfield(lua_State * L, const char *name, const char *field)
374 lua_checkstack(L, 2);
375 lua_pushstring(L, name);
376 lua_pushstring(L, field);
377 lua_rawset(L, -3);
380 static void dump_char_ref(lua_State * L, struct splinechar *spchar)
382 lua_checkstack(L, 2);
383 lua_pushstring(L, "char");
384 lua_pushstring(L, spchar->name);
385 lua_rawset(L, -3);
389 static void dump_lstringfield(lua_State * L, const char *name, char *field, int len)
391 lua_checkstack(L, 2);
392 lua_pushstring(L, name);
393 lua_pushlstring(L, field, len);
394 lua_rawset(L, -3);
397 static void dump_enumfield(lua_State * L, const char *name, int fid, const char **fields)
399 lua_checkstack(L, 2);
400 lua_pushstring(L, name);
401 lua_pushstring(L, fields[fid]);
402 lua_rawset(L, -3);
405 static void dump_floatfield(lua_State * L, const char *name, double field)
407 lua_checkstack(L, 2);
408 lua_pushstring(L, name);
409 lua_pushnumber(L, field);
410 lua_rawset(L, -3);
413 static char tag_string[5] = { 0 };
415 static char *make_tag_string(unsigned int field)
417 tag_string[0] = (field & 0xFF000000) >> 24;
418 tag_string[1] = (field & 0x00FF0000) >> 16;
419 tag_string[2] = (field & 0x0000FF00) >> 8;
420 tag_string[3] = (field & 0x000000FF);
421 return (char *) tag_string;
425 static void dump_tag(lua_State * L, const char *name, unsigned int field)
427 lua_checkstack(L, 2);
428 lua_pushstring(L, name);
429 lua_pushlstring(L, make_tag_string(field), 4);
430 lua_rawset(L, -3);
433 static void dump_subtable_name(lua_State * L, const char *name, struct lookup_subtable *s)
435 /* this is likely a backref */
436 if (s == NULL)
437 return;
438 lua_checkstack(L, 2);
439 if (s->next == NULL) {
440 dump_stringfield(L, name, s->subtable_name);
441 } else {
442 /* can this really happen ? */
443 int i = 0;
444 lua_newtable(L);
445 while (s != NULL) {
446 lua_pushstring(L, s->subtable_name);
447 lua_rawseti(L, -2, ++i);
448 s = s->next;
450 lua_setfield(L, -2, name);
456 #define NESTED_TABLE(a,b,c) { \
457 int k = 1; \
458 next = b; \
459 while (next != NULL) { \
460 lua_checkstack(L,2); \
461 lua_pushnumber(L,k); k++; \
462 lua_createtable(L,0,c); \
463 a(L, next); \
464 lua_rawset(L,-3); \
465 next = next->next; \
468 #define NESTED_TABLE_SF(a,b,c,d) { \
469 int k = 1; \
470 next = b; \
471 while (next != NULL) { \
472 lua_checkstack(L,2); \
473 lua_pushnumber(L,k); k++; \
474 lua_createtable(L,0,d); \
475 if (a(L, next, c)) \
476 lua_rawset(L,-3); \
477 else { \
478 lua_pop(L,2); \
480 next = next->next; \
484 static void do_handle_scriptlanglist(lua_State * L, struct scriptlanglist *sl)
486 int k;
487 dump_tag(L, "script", sl->script);
489 lua_checkstack(L, 3);
490 lua_newtable(L);
491 for (k = 0; k < MAX_LANG; k++) {
492 if (sl->langs[k] != 0) {
493 lua_pushnumber(L, (k + 1));
494 lua_pushstring(L, make_tag_string(sl->langs[k]));
495 lua_rawset(L, -3);
499 if (sl->lang_cnt >= MAX_LANG) {
500 for (k = MAX_LANG; k < sl->lang_cnt; k++) {
501 lua_pushnumber(L, (k + 1));
502 lua_pushstring(L, make_tag_string(sl->morelangs[k - MAX_LANG]));
503 lua_rawset(L, -3);
506 lua_setfield(L, -2, "langs");
509 static void handle_scriptlanglist(lua_State * L, struct scriptlanglist *sll)
511 struct scriptlanglist *next;
512 NESTED_TABLE(do_handle_scriptlanglist, sll, 4);
515 static void
516 do_handle_featurescriptlanglist(lua_State * L,
517 struct featurescriptlanglist *features)
519 dump_tag(L, "tag", features->featuretag);
520 lua_newtable(L);
521 handle_scriptlanglist(L, features->scripts);
522 lua_setfield(L, -2, "scripts");
525 static void
526 handle_featurescriptlanglist(lua_State * L,
527 struct featurescriptlanglist *features)
529 struct featurescriptlanglist *next;
530 NESTED_TABLE(do_handle_featurescriptlanglist, features, 3);
533 static void do_handle_lookup_subtable(lua_State * L, struct lookup_subtable *subtable)
536 dump_stringfield(L, "name", subtable->subtable_name);
537 dump_stringfield(L, "suffix", subtable->suffix);
539 /* struct otlookup *lookup; *//* this is the parent */
541 /* dump_intfield (L,"unused", subtable->unused); */
542 /* The next one is true if there is no fpst, false otherwise */
544 dump_intfield (L,"per_glyph_pst_or_kern",subtable->per_glyph_pst_or_kern);
546 dump_cond_intfield(L, "anchor_classes", subtable->anchor_classes);
547 dump_cond_intfield(L, "vertical_kerning", subtable->vertical_kerning);
549 if (subtable->kc != NULL) {
550 lua_newtable(L);
551 handle_kernclass(L, subtable->kc, subtable->subtable_name);
552 lua_setfield(L, -2, "kernclass");
554 #if 0
555 if (subtable->fpst != NULL) {
556 /* lua_newtable(L); */
557 handle_generic_fpst(L, subtable->fpst);
558 /* lua_setfield(L,-2, "fpst"); */
560 #endif
562 /* int subtable_offset; *//* used by OTF file generation */
563 /* int32 *extra_subtables; *//* used by OTF file generation */
566 static void handle_lookup_subtable(lua_State * L, struct lookup_subtable *subtable)
568 struct lookup_subtable *next;
569 NESTED_TABLE(do_handle_lookup_subtable, subtable, 2);
572 static int do_handle_lookup(lua_State * L, struct otlookup *lookup, SplineFont * sf)
574 int mc;
576 dump_enumfield(L, "type", lookup->lookup_type, otf_lookup_type_enum);
578 lua_newtable(L);
579 if (lookup->lookup_flags & pst_r2l) {
580 lua_pushstring(L, "r2l");
581 lua_pushboolean(L, 1);
582 lua_rawset(L, -3);
584 if (lookup->lookup_flags & pst_ignorebaseglyphs) {
585 lua_pushstring(L, "ignorebaseglyphs");
586 lua_pushboolean(L, 1);
587 lua_rawset(L, -3);
589 if (lookup->lookup_flags & pst_ignoreligatures) {
590 lua_pushstring(L, "ignoreligatures");
591 lua_pushboolean(L, 1);
592 lua_rawset(L, -3);
594 if (lookup->lookup_flags & pst_ignorecombiningmarks) {
595 lua_pushstring(L, "ignorecombiningmarks");
596 lua_pushboolean(L, 1);
597 lua_rawset(L, -3);
599 mc = (lookup->lookup_flags >> 8);
600 if (mc > 0 && mc < sf->mark_class_cnt && sf->mark_class_names[mc] != NULL) {
601 lua_pushstring(L, "mark_class");
602 lua_pushstring(L, sf->mark_class_names[mc]);
603 lua_rawset(L, -3);
605 lua_setfield(L, -2, "flags");
609 dump_stringfield(L, "name", lookup->lookup_name);
611 if (lookup->features != NULL) {
612 lua_newtable(L);
613 handle_featurescriptlanglist(L, lookup->features);
614 lua_setfield(L, -2, "features");
617 if (lookup->subtables != NULL) {
618 lua_newtable(L);
619 handle_lookup_subtable(L, lookup->subtables);
620 lua_setfield(L, -2, "subtables");
623 /* dump_intfield (L,"unused", lookup->unused); */
624 /* dump_intfield (L,"empty", lookup->empty); */
625 /* dump_intfield (L,"store_in_afm", lookup->store_in_afm); */
626 /* dump_intfield (L,"needs_extension", lookup->needs_extension); */
627 /* dump_intfield (L,"temporary_kern", lookup->temporary_kern); */
628 /* dump_intfield (L,"def_lang_checked", lookup->def_lang_checked); */
629 /* dump_intfield (L,"def_lang_found", lookup->def_lang_found); */
630 /* dump_intfield (L,"ticked", lookup->ticked); */
631 /* dump_intfield (L,"subcnt", lookup->subcnt); */
632 /* dump_intfield (L,"lookup_index", lookup->lookup_index); *//* identical to array index */
633 /* dump_intfield (L,"lookup_offset", lookup->lookup_offset); */
634 /* dump_intfield (L,"lookup_length", lookup->lookup_length); */
635 /* dump_stringfield(L,"tempname", lookup->tempname); */
636 return 1;
639 static void handle_lookup(lua_State * L, struct otlookup *lookup, SplineFont * sf)
641 struct otlookup *next;
642 NESTED_TABLE_SF(do_handle_lookup, lookup, sf, 18); /* 18 is a guess */
645 static void do_handle_kernpair(lua_State * L, struct kernpair *kp)
648 if (kp->sc != NULL)
649 dump_char_ref(L, kp->sc);
650 dump_intfield(L, "off", kp->off);
651 /* uint16 kcid; *//* temporary value */
652 dump_subtable_name(L, "lookup", kp->subtable);
655 static void handle_kernpair(lua_State * L, struct kernpair *kp)
657 struct kernpair *next;
658 NESTED_TABLE(do_handle_kernpair, kp, 4);
661 static void handle_splinecharlist(lua_State * L, struct splinecharlist *scl)
664 struct splinecharlist *next = scl;
665 int k = 1;
666 lua_checkstack(L, 10);
667 while (next != NULL) {
668 if (next->sc != NULL) {
669 lua_pushnumber(L, k);
670 k++;
671 lua_pushstring(L, next->sc->name);
672 lua_rawset(L, -3);
674 next = next->next;
680 /* vs is the "variation selector" a unicode codepoint which modifieds */
681 /* the code point before it. If vs is -1 then unienc is just an */
682 /* alternate encoding (greek Alpha and latin A), but if vs is one */
683 /* of unicode's variation selectors then this glyph is somehow a */
684 /* variant shape. The specifics depend on the selector and script */
685 /* fid is currently unused, but may, someday, be used to do ttcs */
686 /* NOTE: GlyphInfo displays vs==-1 as vs==0, and fixes things up */
689 static int handle_altuni(lua_State * L, struct altuni *au)
691 struct altuni *next = au;
692 int i = 0;
693 int k = 1;
694 lua_checkstack(L, 3);
695 while (next != NULL) {
696 if (next->unienc<0x10FFFF) {
697 lua_newtable(L);
698 dump_intfield(L, "unicode", next->unienc);
699 i++;
700 if (next->vs != -1)
701 dump_intfield(L, "variant", next->vs);
702 /* dump_intfield(L, "fid", next->fid); */
703 lua_rawseti(L, -2, k++);
704 } else {
705 printf("ignoring variant %i %i\n",next->unienc,next->vs);
707 next = next->next;
709 return i;
714 #define interesting_vr(a) (((a)->xoff!=0) || ((a)->yoff!=0) || ((a)->h_adv_off!=0) || ((a)->v_adv_off!=0))
716 static void handle_vr(lua_State * L, struct vr *pos)
719 dump_cond_intfield(L, "x", pos->xoff);
720 dump_cond_intfield(L, "y", pos->yoff);
721 dump_cond_intfield(L, "h", pos->h_adv_off);
722 dump_cond_intfield(L, "v", pos->v_adv_off);
726 static void do_handle_generic_pst(lua_State * L, struct generic_pst *pst)
728 int k;
729 if (pst->type > LAST_POSSUB_TYPE_ENUM) {
730 dump_tag(L, "type", pst->type);
731 } else {
732 dump_enumfield(L, "type", pst->type, possub_type_enum);
734 /* unsigned int ticked: 1; */
735 /* unsigned int temporary: 1; *//* Used in afm ligature closure */
736 /* struct lookup_subtable *subtable; *//* handled by caller */
738 lua_checkstack(L, 4);
739 lua_pushstring(L, "specification");
740 lua_createtable(L, 0, 4);
741 if (pst->type == pst_position) {
742 handle_vr(L, &pst->u.pos);
743 } else if (pst->type == pst_pair) {
744 dump_stringfield(L, "paired", pst->u.pair.paired);
745 if (pst->u.pair.vr != NULL) {
746 lua_pushstring(L, "offsets");
747 lua_createtable(L, 2, 0);
748 if (interesting_vr(pst->u.pair.vr)) {
749 lua_createtable(L, 0, 4);
750 handle_vr(L, pst->u.pair.vr);
751 lua_rawseti(L, -2, 1);
753 if (interesting_vr(pst->u.pair.vr + 1)) {
754 lua_createtable(L, 0, 4);
755 handle_vr(L, pst->u.pair.vr + 1);
756 lua_rawseti(L, -2, 2);
758 lua_rawset(L, -3);
760 } else if (pst->type == pst_substitution) {
761 dump_stringfield(L, "variant", pst->u.subs.variant);
762 } else if (pst->type == pst_alternate) {
763 dump_stringfield(L, "components", pst->u.mult.components);
764 } else if (pst->type == pst_multiple) {
765 dump_stringfield(L, "components", pst->u.alt.components);
766 } else if (pst->type == pst_ligature) {
767 dump_stringfield(L, "components", pst->u.lig.components);
768 if (pst->u.lig.lig != NULL) {
769 dump_char_ref(L, pst->u.lig.lig);
771 } else if (pst->type == pst_lcaret) {
772 for (k = 0; k < pst->u.lcaret.cnt; k++) {
773 lua_pushnumber(L, (k + 1));
774 lua_pushnumber(L, pst->u.lcaret.carets[k]);
775 lua_rawset(L, -3);
778 lua_rawset(L, -3);
782 static void handle_generic_pst(lua_State * L, struct generic_pst *pst)
784 struct generic_pst *next;
785 int k;
786 int l = 1;
787 next = pst;
788 /* most likely everything arrives in proper order. But to prevent
789 * surprises, better do this is the proper way
791 while (next != NULL) {
792 if (next->subtable != NULL && next->subtable->subtable_name != NULL) {
793 lua_checkstack(L, 3); /* just in case */
794 lua_getfield(L, -1, next->subtable->subtable_name);
795 if (!lua_istable(L, -1)) {
796 lua_pop(L, 1);
797 lua_newtable(L);
798 lua_setfield(L, -2, next->subtable->subtable_name);
799 lua_getfield(L, -1, next->subtable->subtable_name);
801 k = lua_rawlen(L, -1) + 1;
802 lua_pushnumber(L, k);
803 lua_createtable(L, 0, 4);
804 do_handle_generic_pst(L, next);
805 lua_rawset(L, -3);
806 next = next->next;
807 lua_pop(L, 1); /* pop the subtable */
808 } else {
809 /* Found a pst without subtable, or without subtable name */
810 lua_pushnumber(L, l);
811 l++;
812 lua_createtable(L, 0, 4);
813 do_handle_generic_pst(L, next);
814 lua_rawset(L, -3);
815 next = next->next;
820 static void do_handle_liglist(lua_State * L, struct liglist *ligofme)
822 lua_checkstack(L, 2);
823 if (ligofme->lig != NULL) {
824 lua_createtable(L, 0, 6);
825 handle_generic_pst(L, ligofme->lig);
826 lua_setfield(L, -2, "lig");
828 dump_char_ref(L, ligofme->first);
829 if (ligofme->components != NULL) {
830 lua_newtable(L);
831 handle_splinecharlist(L, ligofme->components);
832 lua_setfield(L, -2, "components");
834 dump_intfield(L, "ccnt", ligofme->ccnt);
838 static void handle_liglist(lua_State * L, struct liglist *ligofme)
840 struct liglist *next;
841 NESTED_TABLE(do_handle_liglist, ligofme, 3);
844 static void do_handle_anchorpoint(lua_State * L, struct anchorpoint *anchor)
847 if (anchor->anchor == NULL) {
848 return;
850 if (anchor->type >= 0 && anchor->type <= MAX_ANCHOR_TYPE) {
851 lua_pushstring(L, anchor_type_enum[anchor->type]);
852 } else {
853 lua_pushstring(L, "Anchorpoint has an unknown type!");
854 lua_error(L);
856 /* unsigned int selected: 1; */
857 /* unsigned int ticked: 1; */
859 lua_rawget(L, -2);
860 if (!lua_istable(L, -1)) {
861 /* create the table first */
862 lua_pop(L, 1);
863 lua_pushstring(L, anchor_type_enum[anchor->type]);
864 lua_pushvalue(L, -1);
865 lua_newtable(L);
866 lua_rawset(L, -4);
867 lua_rawget(L, -2);
869 /* now the 'type' table is top of stack */
870 if (anchor->type == at_baselig) {
871 lua_pushstring(L, anchor->anchor->name);
872 lua_rawget(L, -2);
873 if (!lua_istable(L, -1)) {
874 /* create the table first */
875 lua_pop(L, 1);
876 lua_pushstring(L, anchor->anchor->name);
877 lua_pushvalue(L, -1);
878 lua_newtable(L);
879 lua_rawset(L, -4);
880 lua_rawget(L, -2);
882 lua_newtable(L);
883 dump_intfield(L, "x", anchor->me.x);
884 dump_intfield(L, "y", anchor->me.y);
885 if (anchor->has_ttf_pt)
886 dump_intfield(L, "ttf_pt_index", anchor->ttf_pt_index);
887 dump_intfield(L, "lig_index", anchor->lig_index);
888 lua_rawseti(L, -2, (anchor->lig_index + 1));
889 lua_pop(L, 1);
890 } else {
891 lua_pushstring(L, anchor->anchor->name);
892 lua_newtable(L);
893 dump_intfield(L, "x", anchor->me.x);
894 dump_intfield(L, "y", anchor->me.y);
895 if (anchor->has_ttf_pt)
896 dump_intfield(L, "ttf_pt_index", anchor->ttf_pt_index);
897 dump_intfield(L, "lig_index", anchor->lig_index);
898 lua_rawset(L, -3);
900 lua_pop(L, 1);
904 static void handle_anchorpoint(lua_State * L, struct anchorpoint *anchor)
906 struct anchorpoint *next;
907 next = anchor;
908 while (next != NULL) {
909 do_handle_anchorpoint(L, next);
910 next = next->next;
914 static void handle_glyphvariants(lua_State * L, struct glyphvariants *vars)
916 int i;
917 dump_stringfield(L, "variants", vars->variants);
918 dump_intfield(L, "italic_correction", vars->italic_correction);
919 lua_newtable(L);
920 for (i = 0; i < vars->part_cnt; i++) {
921 lua_newtable(L);
922 dump_stringfield(L, "component", vars->parts[i].component);
923 dump_intfield(L, "extender", vars->parts[i].is_extender);
924 dump_intfield(L, "start", vars->parts[i].startConnectorLength);
925 dump_intfield(L, "end", vars->parts[i].endConnectorLength);
926 dump_intfield(L, "advance", vars->parts[i].fullAdvance);
927 lua_rawseti(L, -2, (i + 1));
929 lua_setfield(L, -2, "parts");
932 static void handle_mathkernvertex(lua_State * L, struct mathkernvertex *mkv)
934 int i;
935 for (i = 0; i < mkv->cnt; i++) {
936 lua_newtable(L);
937 dump_intfield(L, "height", mkv->mkd[i].height);
938 dump_intfield(L, "kern", mkv->mkd[i].kern);
939 lua_rawseti(L, -2, (i + 1));
943 static void handle_mathkern(lua_State * L, struct mathkern *mk)
945 lua_newtable(L);
946 handle_mathkernvertex(L, &(mk->top_right));
947 lua_setfield(L, -2, "top_right");
948 lua_newtable(L);
949 handle_mathkernvertex(L, &(mk->top_left));
950 lua_setfield(L, -2, "top_left");
951 lua_newtable(L);
952 handle_mathkernvertex(L, &(mk->bottom_right));
953 lua_setfield(L, -2, "bottom_right");
954 lua_newtable(L);
955 handle_mathkernvertex(L, &(mk->bottom_left));
956 lua_setfield(L, -2, "bottom_left");
961 static void handle_splinechar(lua_State * L, struct splinechar *glyph, int hasvmetrics)
963 DBounds bb;
964 if (glyph->xmax == 0 && glyph->ymax == 0 && glyph->xmin == 0
965 && glyph->ymin == 0) {
966 SplineCharFindBounds(glyph, &bb);
967 glyph->xmin = bb.minx;
968 glyph->ymin = bb.miny;
969 glyph->xmax = bb.maxx;
970 glyph->ymax = bb.maxy;
972 dump_stringfield(L, "name", glyph->name);
973 dump_intfield(L, "unicode", glyph->unicodeenc);
974 lua_createtable(L, 4, 0);
975 lua_pushnumber(L, 1);
976 lua_pushnumber(L, glyph->xmin);
977 lua_rawset(L, -3);
978 lua_pushnumber(L, 2);
979 lua_pushnumber(L, glyph->ymin);
980 lua_rawset(L, -3);
981 lua_pushnumber(L, 3);
982 lua_pushnumber(L, glyph->xmax);
983 lua_rawset(L, -3);
984 lua_pushnumber(L, 4);
985 lua_pushnumber(L, glyph->ymax);
986 lua_rawset(L, -3);
987 lua_setfield(L, -2, "boundingbox");
988 if (glyph->orig_pos>=0) {
989 dump_intfield(L,"orig_pos",glyph->orig_pos);
991 if (hasvmetrics) {
992 dump_intfield(L, "vwidth", glyph->vwidth);
993 if (glyph->tsb != 0)
994 dump_intfield(L, "tsidebearing", glyph->tsb);
996 dump_intfield(L, "width", glyph->width);
998 if (glyph->lsidebearing != glyph->xmin) {
999 dump_cond_intfield(L, "lsidebearing", glyph->lsidebearing);
1001 /* dump_intfield(L,"ttf_glyph", glyph->ttf_glyph); */
1003 /* Layer layers[2]; *//* TH Not used */
1004 /* int layer_cnt; *//* TH Not used */
1005 /* StemInfo *hstem; *//* TH Not used */
1006 /* StemInfo *vstem; *//* TH Not used */
1007 /* DStemInfo *dstem; *//* TH Not used */
1009 /* MinimumDistance *md; *//* TH Not used */
1010 /* struct charviewbase *views; *//* TH Not used */
1011 /* struct charinfo *charinfo; *//* TH ? (charinfo.c) */
1012 /* struct splinefont *parent; *//* TH Not used */
1014 if (glyph->glyph_class > 0) {
1015 dump_enumfield(L, "class", glyph->glyph_class, glyph_class_enum);
1017 /* TH: internal fontforge stuff
1018 dump_intfield(L,"changed", glyph->changed);
1019 dump_intfield(L,"changedsincelasthinted", glyph->changedsincelasthinted);
1020 dump_intfield(L,"manualhints", glyph->manualhints);
1021 dump_intfield(L,"ticked", glyph->ticked);
1022 dump_intfield(L,"changed_since_autosave", glyph->changed_since_autosave);
1023 dump_intfield(L,"widthset", glyph->widthset);
1024 dump_intfield(L,"vconflicts", glyph->vconflicts);
1025 dump_intfield(L,"hconflicts", glyph->hconflicts);
1026 dump_intfield(L,"searcherdummy", glyph->searcherdummy);
1027 dump_intfield(L,"changed_since_search", glyph->changed_since_search);
1028 dump_intfield(L,"wasopen", glyph->wasopen);
1029 dump_intfield(L,"namechanged", glyph->namechanged);
1030 dump_intfield(L,"blended", glyph->blended);
1031 dump_intfield(L,"ticked2", glyph->ticked2);
1032 dump_intfield(L,"unused_so_far", glyph->unused_so_far);
1033 dump_intfield(L,"numberpointsbackards", glyph->numberpointsbackards);
1034 dump_intfield(L,"instructions_out_of_date", glyph->instructions_out_of_date);
1035 dump_intfield(L,"complained_about_ptnums", glyph->complained_about_ptnums);
1036 unsigned int vs_open: 1;
1037 unsigned int unlink_rm_ovrlp_save_undo: 1;
1038 unsigned int inspiro: 1;
1039 unsigned int lig_caret_cnt_fixed: 1;
1042 uint8 *ttf_instrs;
1043 int16 ttf_instrs_len;
1044 int16 countermask_cnt;
1045 HintMask *countermasks;
1048 if (glyph->kerns != NULL) {
1049 lua_newtable(L);
1050 handle_kernpair(L, glyph->kerns);
1051 lua_setfield(L, -2, "kerns");
1053 if (glyph->vkerns != NULL) {
1054 lua_newtable(L);
1055 handle_kernpair(L, glyph->vkerns);
1056 lua_setfield(L, -2, "vkerns");
1059 if (glyph->dependents != NULL) {
1060 lua_newtable(L);
1061 handle_splinecharlist(L, glyph->dependents);
1062 lua_setfield(L, -2, "dependents");
1065 if (glyph->possub != NULL) {
1066 lua_newtable(L);
1067 handle_generic_pst(L, glyph->possub);
1068 lua_setfield(L, -2, "lookups");
1071 if (glyph->ligofme != NULL) {
1072 lua_newtable(L);
1073 handle_liglist(L, glyph->ligofme);
1074 lua_setfield(L, -2, "ligatures");
1077 if (glyph->comment != NULL)
1078 dump_stringfield(L, "comment", glyph->comment);
1080 /* Color color; *//* dont care */
1082 if (glyph->anchor != NULL) {
1083 lua_newtable(L);
1084 handle_anchorpoint(L, glyph->anchor);
1085 lua_setfield(L, -2, "anchors");
1088 if (glyph->altuni != NULL) {
1089 int i;
1090 lua_newtable(L);
1091 i = handle_altuni(L, glyph->altuni);
1092 if (i>0) {
1093 lua_setfield(L, -2, "altuni");
1094 } else {
1095 lua_pop(L,1);
1099 if (glyph->tex_height != TEX_UNDEF)
1100 dump_intfield(L, "tex_height", glyph->tex_height);
1101 if (glyph->tex_depth != TEX_UNDEF)
1102 dump_intfield(L, "tex_depth", glyph->tex_depth);
1104 dump_cond_intfield(L, "is_extended_shape", glyph->is_extended_shape);
1105 if (glyph->italic_correction != TEX_UNDEF)
1106 dump_intfield(L, "italic_correction", glyph->italic_correction);
1107 if (glyph->top_accent_horiz != TEX_UNDEF)
1108 dump_intfield(L, "top_accent", glyph->top_accent_horiz);
1110 if (glyph->vert_variants != NULL) {
1111 lua_newtable(L);
1112 handle_glyphvariants(L, glyph->vert_variants);
1113 lua_setfield(L, -2, "vert_variants");
1115 if (glyph->horiz_variants != NULL) {
1116 lua_newtable(L);
1117 handle_glyphvariants(L, glyph->horiz_variants);
1118 lua_setfield(L, -2, "horiz_variants");
1120 if (glyph->mathkern != NULL) {
1121 lua_newtable(L);
1122 handle_mathkern(L, glyph->mathkern);
1123 lua_setfield(L, -2, "mathkern");
1127 const char *panose_values_0[] =
1128 { "Any", "No Fit", "Text and Display", "Script", "Decorative",
1129 "Pictorial"
1132 const char *panose_values_1[] =
1133 { "Any", "No Fit", "Cove", "Obtuse Cove", "Square Cove",
1134 "Obtuse Square Cove",
1135 "Square", "Thin", "Bone", "Exaggerated", "Triangle", "Normal Sans",
1136 "Obtuse Sans", "Perp Sans", "Flared", "Rounded"
1139 const char *panose_values_2[] =
1140 { "Any", "No Fit", "Very Light", "Light", "Thin", "Book",
1141 "Medium", "Demi", "Bold", "Heavy", "Black", "Nord"
1144 const char *panose_values_3[] =
1145 { "Any", "No Fit", "Old Style", "Modern", "Even Width",
1146 "Expanded", "Condensed", "Very Expanded", "Very Condensed", "Monospaced"
1149 const char *panose_values_4[] =
1150 { "Any", "No Fit", "None", "Very Low", "Low", "Medium Low",
1151 "Medium", "Medium High", "High", "Very High"
1154 const char *panose_values_5[] =
1155 { "Any", "No Fit", "Gradual/Diagonal", "Gradual/Transitional",
1156 "Gradual/Vertical",
1157 "Gradual/Horizontal", "Rapid/Vertical", "Rapid/Horizontal",
1158 "Instant/Vertical"
1161 const char *panose_values_6[] =
1162 { "Any", "No Fit", "Straight Arms/Horizontal", "Straight Arms/Wedge",
1163 "Straight Arms/Vertical",
1164 "Straight Arms/Single Serif", "Straight Arms/Double Serif",
1165 "Non-Straight Arms/Horizontal",
1166 "Non-Straight Arms/Wedge", "Non-Straight Arms/Vertical",
1167 "Non-Straight Arms/Single Serif",
1168 "Non-Straight Arms/Double Serif"
1171 const char *panose_values_7[] =
1172 { "Any", "No Fit", "Normal/Contact", "Normal/Weighted", "Normal/Boxed",
1173 "Normal/Flattened",
1174 "Normal/Rounded", "Normal/Off Center", "Normal/Square", "Oblique/Contact",
1175 "Oblique/Weighted",
1176 "Oblique/Boxed", "Oblique/Flattened", "Oblique/Rounded",
1177 "Oblique/Off Center", "Oblique/Square"
1180 const char *panose_values_8[] =
1181 { "Any", "No Fit", "Standard/Trimmed", "Standard/Pointed",
1182 "Standard/Serifed", "High/Trimmed",
1183 "High/Pointed", "High/Serifed", "Constant/Trimmed", "Constant/Pointed",
1184 "Constant/Serifed",
1185 "Low/Trimmed", "Low/Pointed", "Low/Serifed"
1188 const char *panose_values_9[] =
1189 { "Any", "No Fit", "Constant/Small", "Constant/Standard",
1190 "Constant/Large", "Ducking/Small", "Ducking/Standard", "Ducking/Large"
1193 #define panose_values_0_max 5
1194 #define panose_values_1_max 15
1195 #define panose_values_2_max 11
1196 #define panose_values_3_max 9
1197 #define panose_values_4_max 9
1198 #define panose_values_5_max 8
1199 #define panose_values_6_max 11
1200 #define panose_values_7_max 15
1201 #define panose_values_8_max 13
1202 #define panose_values_9_max 7
1204 #define fix_range(a,b) (b<0 ? 0 : (b>a ? 0 : b))
1206 static void handle_pfminfo(lua_State * L, struct pfminfo pfm)
1209 dump_intfield(L, "pfmset", pfm.pfmset);
1210 dump_intfield(L, "winascent_add", pfm.winascent_add);
1211 dump_intfield(L, "windescent_add", pfm.windescent_add);
1212 dump_intfield(L, "hheadascent_add", pfm.hheadascent_add);
1213 dump_intfield(L, "hheaddescent_add", pfm.hheaddescent_add);
1214 dump_intfield(L, "typoascent_add", pfm.typoascent_add);
1215 dump_intfield(L, "typodescent_add", pfm.typodescent_add);
1216 dump_intfield(L, "subsuper_set", pfm.subsuper_set);
1217 dump_intfield(L, "panose_set", pfm.panose_set);
1218 dump_intfield(L, "hheadset", pfm.hheadset);
1219 dump_intfield(L, "vheadset", pfm.vheadset);
1220 dump_intfield(L, "pfmfamily", pfm.pfmfamily);
1221 dump_intfield(L, "weight", pfm.weight);
1222 dump_intfield(L, "width", pfm.width);
1223 dump_intfield(L, "avgwidth", pfm.avgwidth);
1224 dump_intfield(L, "firstchar", pfm.firstchar);
1225 dump_intfield(L, "lastchar", pfm.lastchar);
1226 lua_createtable(L, 0, 10);
1227 dump_enumfield(L, "familytype",
1228 fix_range(panose_values_0_max, pfm.panose[0]),
1229 panose_values_0);
1230 dump_enumfield(L, "serifstyle",
1231 fix_range(panose_values_1_max, pfm.panose[1]),
1232 panose_values_1);
1233 dump_enumfield(L, "weight", fix_range(panose_values_2_max, pfm.panose[2]),
1234 panose_values_2);
1235 dump_enumfield(L, "proportion",
1236 fix_range(panose_values_3_max, pfm.panose[3]),
1237 panose_values_3);
1238 dump_enumfield(L, "contrast", fix_range(panose_values_4_max, pfm.panose[4]),
1239 panose_values_4);
1240 dump_enumfield(L, "strokevariation",
1241 fix_range(panose_values_5_max, pfm.panose[5]),
1242 panose_values_5);
1243 dump_enumfield(L, "armstyle", fix_range(panose_values_6_max, pfm.panose[6]),
1244 panose_values_6);
1245 dump_enumfield(L, "letterform",
1246 fix_range(panose_values_7_max, pfm.panose[7]),
1247 panose_values_7);
1248 dump_enumfield(L, "midline", fix_range(panose_values_8_max, pfm.panose[8]),
1249 panose_values_8);
1250 dump_enumfield(L, "xheight", fix_range(panose_values_9_max, pfm.panose[9]),
1251 panose_values_9);
1252 lua_setfield(L, -2, "panose");
1254 dump_intfield(L, "fstype", pfm.fstype);
1255 dump_intfield(L, "linegap", pfm.linegap);
1256 dump_intfield(L, "vlinegap", pfm.vlinegap);
1257 dump_intfield(L, "hhead_ascent", pfm.hhead_ascent);
1258 dump_intfield(L, "hhead_descent", pfm.hhead_descent);
1259 dump_intfield(L, "hhead_descent", pfm.hhead_descent);
1260 dump_intfield(L, "os2_typoascent", pfm.os2_typoascent);
1261 dump_intfield(L, "os2_typodescent", pfm.os2_typodescent);
1262 dump_intfield(L, "os2_typolinegap", pfm.os2_typolinegap);
1263 dump_intfield(L, "os2_winascent", pfm.os2_winascent);
1264 dump_intfield(L, "os2_windescent", pfm.os2_windescent);
1265 dump_intfield(L, "os2_subxsize", pfm.os2_subxsize);
1266 dump_intfield(L, "os2_subysize", pfm.os2_subysize);
1267 dump_intfield(L, "os2_subxoff", pfm.os2_subxoff);
1268 dump_intfield(L, "os2_subyoff", pfm.os2_subyoff);
1269 dump_intfield(L, "os2_supxsize", pfm.os2_supxsize);
1270 dump_intfield(L, "os2_supysize", pfm.os2_supysize);
1271 dump_intfield(L, "os2_supxoff", pfm.os2_supxoff);
1272 dump_intfield(L, "os2_supyoff", pfm.os2_supyoff);
1273 dump_intfield(L, "os2_strikeysize", pfm.os2_strikeysize);
1274 dump_intfield(L, "os2_strikeypos", pfm.os2_strikeypos);
1275 dump_lstringfield(L, "os2_vendor", pfm.os2_vendor, 4);
1276 dump_intfield(L, "os2_family_class", pfm.os2_family_class);
1277 dump_intfield(L, "os2_xheight", pfm.os2_xheight);
1278 dump_intfield(L, "os2_capheight", pfm.os2_capheight);
1279 dump_intfield(L, "os2_defaultchar", pfm.os2_defaultchar);
1280 dump_intfield(L, "os2_breakchar", pfm.os2_breakchar);
1281 if (pfm.hascodepages) {
1282 lua_newtable(L);
1283 lua_pushnumber(L, pfm.codepages[0]);
1284 lua_rawseti(L, -2, 1);
1285 lua_pushnumber(L, pfm.codepages[1]);
1286 lua_rawseti(L, -2, 2);
1287 lua_setfield(L, -2, "codepages");
1289 if (pfm.hasunicoderanges) {
1290 lua_newtable(L);
1291 lua_pushnumber(L, pfm.unicoderanges[0]);
1292 lua_rawseti(L, -2, 1);
1293 lua_pushnumber(L, pfm.unicoderanges[1]);
1294 lua_rawseti(L, -2, 2);
1295 lua_pushnumber(L, pfm.unicoderanges[2]);
1296 lua_rawseti(L, -2, 3);
1297 lua_pushnumber(L, pfm.unicoderanges[3]);
1298 lua_rawseti(L, -2, 4);
1299 lua_setfield(L, -2, "unicoderanges");
1304 static char *do_handle_enc(lua_State * L, struct enc *enc)
1306 int i;
1307 char *ret = enc->enc_name;
1308 dump_stringfield(L, "enc_name", enc->enc_name);
1309 dump_intfield(L, "char_cnt", enc->char_cnt);
1311 lua_checkstack(L, 4);
1312 if (enc->char_cnt && enc->unicode != NULL) {
1313 lua_createtable(L, enc->char_cnt, 1);
1314 for (i = 0; i < enc->char_cnt; i++) {
1315 lua_pushnumber(L, i);
1316 lua_pushnumber(L, enc->unicode[i]);
1317 lua_rawset(L, -3);
1319 lua_setfield(L, -2, "unicode");
1322 if (enc->char_cnt && enc->psnames != NULL) {
1323 lua_createtable(L, enc->char_cnt, 1);
1324 for (i = 0; i < enc->char_cnt; i++) {
1325 lua_pushnumber(L, i);
1326 lua_pushstring(L, enc->psnames[i]);
1327 lua_rawset(L, -3);
1329 lua_setfield(L, -2, "psnames");
1331 dump_intfield(L, "builtin", enc->builtin);
1332 dump_intfield(L, "hidden", enc->hidden);
1333 dump_intfield(L, "only_1byte", enc->only_1byte);
1334 dump_intfield(L, "has_1byte", enc->has_1byte);
1335 dump_intfield(L, "has_2byte", enc->has_2byte);
1336 dump_cond_intfield(L, "is_unicodebmp", enc->is_unicodebmp);
1337 dump_cond_intfield(L, "is_unicodefull", enc->is_unicodefull);
1338 dump_cond_intfield(L, "is_custom", enc->is_custom);
1339 dump_cond_intfield(L, "is_original", enc->is_original);
1340 dump_cond_intfield(L, "is_compact", enc->is_compact);
1341 dump_cond_intfield(L, "is_japanese", enc->is_japanese);
1342 dump_cond_intfield(L, "is_korean", enc->is_korean);
1343 dump_cond_intfield(L, "is_tradchinese", enc->is_tradchinese);
1344 dump_cond_intfield(L, "is_simplechinese", enc->is_simplechinese);
1346 if (enc->iso_2022_escape_len > 0) {
1347 dump_lstringfield(L, "iso_2022_escape", enc->iso_2022_escape,
1348 enc->iso_2022_escape_len);
1350 dump_intfield(L, "low_page", enc->low_page);
1351 dump_intfield(L, "high_page", enc->high_page);
1353 dump_stringfield(L, "iconv_name", enc->iconv_name);
1355 dump_intfield(L, "char_max", enc->char_max);
1356 return ret;
1359 #if 0 /* unused */
1360 static void handle_enc(lua_State * L, struct enc *enc)
1362 struct enc *next;
1363 NESTED_TABLE(do_handle_enc, enc, 24);
1365 #endif
1367 static void handle_encmap(lua_State * L, struct encmap *map, int notdef_loc)
1369 int i;
1370 dump_intfield(L, "enccount", map->enccount);
1371 dump_intfield(L, "encmax", map->encmax);
1372 dump_intfield(L, "backmax", map->backmax);
1373 /*dump_intfield(L,"ticked", map->ticked) ; */
1374 if (map->remap != NULL) {
1375 lua_newtable(L);
1376 dump_intfield(L, "firstenc", map->remap->firstenc);
1377 dump_intfield(L, "lastenc", map->remap->lastenc);
1378 dump_intfield(L, "infont", map->remap->infont);
1379 lua_setfield(L, -2, "remap");
1381 lua_checkstack(L, 4);
1382 if (map->encmax > 0 && map->map != NULL) {
1383 lua_createtable(L, map->encmax, 1);
1384 for (i = 0; i < map->encmax; i++) {
1385 if (map->map[i] != -1) {
1386 int l = map->map[i];
1387 lua_pushnumber(L, i);
1388 if (l < notdef_loc)
1389 lua_pushnumber(L, (l + 1));
1390 else
1391 lua_pushnumber(L, l);
1392 lua_rawset(L, -3);
1395 lua_setfield(L, -2, "map");
1398 if (map->backmax > 0 && map->backmap != NULL) {
1399 lua_newtable(L);
1400 for (i = 0; i < map->backmax; i++) {
1401 if (map->backmap[i] != -1) { /* TODO: check this, because valgrind sometimes says
1402 "Conditional jump or move depends on uninitialised value(s)"
1403 needs a test file.
1405 if (i < notdef_loc)
1406 lua_pushnumber(L, (i + 1));
1407 else
1408 lua_pushnumber(L, i);
1409 lua_pushnumber(L, map->backmap[i]);
1410 lua_rawset(L, -3);
1413 lua_setfield(L, -2, "backmap");
1416 if (map->enc != NULL) {
1417 char *encname;
1418 lua_newtable(L);
1419 encname = do_handle_enc(L, map->enc);
1420 lua_setfield(L, -2, "enc");
1421 lua_pushstring(L, encname);
1422 lua_setfield(L, -2, "enc_name");
1426 static void handle_psdict(lua_State * L, struct psdict *private)
1428 int k;
1429 if (private->keys != NULL && private->values != NULL) {
1430 for (k = 0; k < private->next; k++) {
1431 lua_pushstring(L, private->keys[k]);
1432 lua_pushstring(L, private->values[k]);
1433 lua_rawset(L, -3);
1438 static void do_handle_ttflangname(lua_State * L, struct ttflangname *names)
1440 int k;
1441 dump_stringfield(L, "lang", MSLangString(names->lang));
1442 lua_checkstack(L, 4);
1443 lua_createtable(L, 0, ttf_namemax);
1444 for (k = 0; k < ttf_namemax; k++) {
1445 lua_pushstring(L, ttfnames_enum[k]);
1446 lua_pushstring(L, names->names[k]);
1447 lua_rawset(L, -3);
1449 lua_setfield(L, -2, "names");
1453 static void handle_ttflangname(lua_State * L, struct ttflangname *names)
1455 struct ttflangname *next;
1456 NESTED_TABLE(do_handle_ttflangname, names, 2);
1460 static void do_handle_anchorclass(lua_State * L, struct anchorclass *anchor)
1463 dump_stringfield(L, "name", anchor->name);
1464 dump_subtable_name(L, "lookup", anchor->subtable);
1465 dump_enumfield(L, "type", anchor->type, anchorclass_type_enum);
1466 /* uint8 has_base; */
1467 /* uint8 processed, has_mark, matches, ac_num; */
1468 /* uint8 ticked; */
1471 static void handle_anchorclass(lua_State * L, struct anchorclass *anchor)
1473 struct anchorclass *next;
1474 NESTED_TABLE(do_handle_anchorclass, anchor, 10);
1477 static void do_handle_ttf_table(lua_State * L, struct ttf_table *ttf_tab)
1480 dump_tag(L, "tag", ttf_tab->tag);
1481 dump_intfield(L, "len", ttf_tab->len);
1482 dump_intfield(L, "maxlen", ttf_tab->maxlen);
1483 dump_lstringfield(L, "data", (char *) ttf_tab->data, ttf_tab->len);
1486 static void handle_ttf_table(lua_State * L, struct ttf_table *ttf_tab)
1488 struct ttf_table *next;
1489 NESTED_TABLE(do_handle_ttf_table, ttf_tab, 4);
1492 static int do_handle_kernclass(lua_State * L, struct kernclass *kerns, const char *name)
1494 int k;
1495 int match = 0;
1496 if (name) {
1497 struct lookup_subtable *s = kerns->subtable;
1498 while (s != NULL) {
1499 if (strcmp(s->subtable_name,name)==0) {
1500 match = 1;
1501 break;
1503 s = s->next;
1505 } else {
1506 match = 1;
1508 if (!match) {
1509 return 0;
1511 lua_checkstack(L, 4);
1512 lua_createtable(L, kerns->first_cnt, 1);
1513 for (k = 0; k < kerns->first_cnt; k++) {
1514 lua_pushnumber(L, (k + 1));
1515 lua_pushstring(L, kerns->firsts[k]);
1516 lua_rawset(L, -3);
1518 lua_setfield(L, -2, "firsts");
1520 lua_createtable(L, kerns->second_cnt, 1);
1521 for (k = 0; k < kerns->second_cnt; k++) {
1522 lua_pushnumber(L, (k + 1));
1523 lua_pushstring(L, kerns->seconds[k]);
1524 lua_rawset(L, -3);
1526 lua_setfield(L, -2, "seconds");
1528 if (!name) {
1529 dump_subtable_name(L, "lookup", kerns->subtable);
1532 lua_createtable(L, kerns->second_cnt * kerns->first_cnt, 1);
1533 for (k = 0; k < (kerns->second_cnt * kerns->first_cnt); k++) {
1534 if (kerns->offsets[k] != 0) {
1535 lua_pushnumber(L, (k + 1));
1536 lua_pushnumber(L, kerns->offsets[k]);
1537 lua_rawset(L, -3);
1540 lua_setfield(L, -2, "offsets");
1541 return 1;
1544 static void handle_kernclass(lua_State * L, struct kernclass *kerns, const char *name)
1546 struct kernclass *next;
1547 NESTED_TABLE_SF(do_handle_kernclass, kerns, name, 8);
1551 #define DUMP_NUMBER_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+1)); \
1557 lua_pushnumber(L,item[kk]); \
1558 lua_rawset(L,-3); } \
1559 lua_setfield(L,-2,s); } }
1562 #define DUMP_STRING_ARRAY(s,cnt,item) { \
1563 if (cnt>0 && item!=NULL) { \
1564 int kk; \
1565 lua_newtable(L); \
1566 for (kk=0;kk<cnt;kk++) { \
1567 lua_pushnumber(L,(kk+1)); \
1568 lua_pushstring(L,item[kk]); \
1569 lua_rawset(L,-3); } \
1570 lua_setfield(L,-2,s); } }
1572 #define DUMP_EXACT_STRING_ARRAY(s,cnt,item) { \
1573 if (cnt>0 && item!=NULL) { \
1574 int kk; \
1575 lua_newtable(L); \
1576 for (kk=0;kk<cnt;kk++) { \
1577 lua_pushnumber(L,(kk)); \
1578 lua_pushstring(L,item[kk]); \
1579 lua_rawset(L,-3); } \
1580 lua_setfield(L,-2,s); } }
1583 static void handle_fpst_rule(lua_State * L, struct fpst_rule *rule, int format)
1585 int k;
1588 if (format == pst_glyphs) {
1590 lua_newtable(L);
1591 dump_stringfield(L, "names", rule->u.glyph.names);
1592 dump_stringfield(L, "back", rule->u.glyph.back);
1593 dump_stringfield(L, "fore", rule->u.glyph.fore);
1594 lua_setfield(L, -2, fpossub_format_enum[format]);
1596 } else if (format == pst_class) {
1598 lua_newtable(L);
1599 DUMP_NUMBER_ARRAY("current", rule->u.class.ncnt,
1600 rule->u.class.nclasses);
1601 DUMP_NUMBER_ARRAY("before", rule->u.class.bcnt, rule->u.class.bclasses);
1602 DUMP_NUMBER_ARRAY("after", rule->u.class.fcnt, rule->u.class.fclasses);
1603 #if 0
1604 DUMP_NUMBER_ARRAY("allclasses", 0, rule->u.class.allclasses);
1605 #endif
1606 lua_setfield(L, -2, fpossub_format_enum[format]);
1608 } else if (format == pst_coverage) {
1610 lua_newtable(L);
1611 DUMP_STRING_ARRAY("current", rule->u.coverage.ncnt,
1612 rule->u.coverage.ncovers);
1613 DUMP_STRING_ARRAY("before", rule->u.coverage.bcnt,
1614 rule->u.coverage.bcovers);
1615 DUMP_STRING_ARRAY("after", rule->u.coverage.fcnt,
1616 rule->u.coverage.fcovers);
1617 lua_setfield(L, -2, fpossub_format_enum[format]);
1619 } else if (format == pst_reversecoverage) {
1621 lua_newtable(L);
1622 DUMP_STRING_ARRAY("current", rule->u.rcoverage.always1,
1623 rule->u.rcoverage.ncovers);
1624 DUMP_STRING_ARRAY("before", rule->u.rcoverage.bcnt,
1625 rule->u.rcoverage.bcovers);
1626 DUMP_STRING_ARRAY("after", rule->u.rcoverage.fcnt,
1627 rule->u.rcoverage.fcovers);
1628 dump_stringfield(L, "replacements", rule->u.rcoverage.replacements);
1629 lua_setfield(L, -2, fpossub_format_enum[format]);
1630 } else {
1631 fprintf(stderr, "handle_fpst_rule(): Unknown rule format: %d\n",
1632 format);
1635 if (rule->lookup_cnt > 0) {
1636 lua_newtable(L);
1637 for (k = 0; k < rule->lookup_cnt; k++) {
1638 lua_pushnumber(L, (rule->lookups[k].seq + 1));
1639 if (rule->lookups[k].lookup != NULL) {
1640 lua_pushstring(L, rule->lookups[k].lookup->lookup_name);
1641 } else {
1642 lua_pushnil(L);
1644 lua_rawset(L, -3);
1646 lua_setfield(L, -2, "lookups");
1647 } else {
1648 /*fprintf(stderr,"handle_fpst_rule(): No lookups?\n"); */
1652 static void do_handle_generic_fpst(lua_State * L, struct generic_fpst *fpst)
1654 int k;
1656 if (fpst->type > LAST_POSSUB_TYPE_ENUM) {
1657 dump_intfield(L, "type", fpst->type);
1658 } else {
1659 dump_enumfield(L, "type", fpst->type, possub_type_enum);
1661 dump_enumfield(L, "format", fpst->format, fpossub_format_enum);
1663 if (fpst->format == pst_class) {
1664 DUMP_EXACT_STRING_ARRAY("current_class", fpst->nccnt, fpst->nclass);
1665 DUMP_EXACT_STRING_ARRAY("before_class", fpst->bccnt, fpst->bclass);
1666 DUMP_EXACT_STRING_ARRAY("after_class", fpst->fccnt, fpst->fclass);
1667 } else {
1668 DUMP_STRING_ARRAY("current_class", fpst->nccnt, fpst->nclass);
1669 DUMP_STRING_ARRAY("before_class", fpst->bccnt, fpst->bclass);
1670 DUMP_STRING_ARRAY("after_class", fpst->fccnt, fpst->fclass);
1673 lua_checkstack(L, 4);
1674 if (fpst->rule_cnt > 0) {
1675 lua_createtable(L, fpst->rule_cnt, 1);
1676 for (k = 0; k < fpst->rule_cnt; k++) {
1677 lua_pushnumber(L, (k + 1));
1678 lua_newtable(L);
1679 handle_fpst_rule(L, &(fpst->rules[k]), fpst->format);
1680 lua_rawset(L, -3);
1682 lua_setfield(L, -2, "rules");
1684 /*dump_intfield (L,"ticked", fpst->ticked); */
1687 static void handle_generic_fpst(lua_State * L, struct generic_fpst *fpst)
1689 struct generic_fpst *next;
1690 int k = 1;
1691 lua_checkstack(L, 3);
1692 if (fpst->subtable != NULL && fpst->subtable->subtable_name != NULL) {
1693 lua_pushstring(L, fpst->subtable->subtable_name);
1694 } else {
1695 lua_pushnumber(L, k);
1696 k++;
1698 lua_createtable(L, 0, 10);
1699 do_handle_generic_fpst(L, fpst);
1700 lua_rawset(L, -3);
1701 next = fpst->next;
1702 while (next != NULL) {
1703 lua_checkstack(L, 3);
1704 if (next->subtable != NULL && next->subtable->subtable_name != NULL) {
1705 lua_pushstring(L, next->subtable->subtable_name);
1706 } else {
1707 lua_pushnumber(L, k);
1708 k++;
1710 lua_createtable(L, 0, 10);
1711 do_handle_generic_fpst(L, next);
1712 lua_rawset(L, -3);
1713 next = next->next;
1717 static void do_handle_otfname(lua_State * L, struct otfname *oname)
1719 dump_intfield(L, "lang", oname->lang);
1720 dump_stringfield(L, "name", oname->name);
1723 static void handle_otfname(lua_State * L, struct otfname *oname)
1725 struct otfname *next;
1726 NESTED_TABLE(do_handle_otfname, oname, 2);
1732 static void handle_MATH(lua_State * L, struct MATH *MATH)
1734 dump_intfield(L, "ScriptPercentScaleDown", MATH->ScriptPercentScaleDown);
1735 dump_intfield(L, "ScriptScriptPercentScaleDown",
1736 MATH->ScriptScriptPercentScaleDown);
1737 dump_intfield(L, "DelimitedSubFormulaMinHeight",
1738 MATH->DelimitedSubFormulaMinHeight);
1739 dump_intfield(L, "DisplayOperatorMinHeight",
1740 MATH->DisplayOperatorMinHeight);
1741 dump_intfield(L, "MathLeading", MATH->MathLeading);
1742 dump_intfield(L, "AxisHeight", MATH->AxisHeight);
1743 dump_intfield(L, "AccentBaseHeight", MATH->AccentBaseHeight);
1744 dump_intfield(L, "FlattenedAccentBaseHeight",
1745 MATH->FlattenedAccentBaseHeight);
1746 dump_intfield(L, "SubscriptShiftDown", MATH->SubscriptShiftDown);
1747 dump_intfield(L, "SubscriptTopMax", MATH->SubscriptTopMax);
1748 dump_intfield(L, "SubscriptBaselineDropMin",
1749 MATH->SubscriptBaselineDropMin);
1750 dump_intfield(L, "SuperscriptShiftUp", MATH->SuperscriptShiftUp);
1751 dump_intfield(L, "SuperscriptShiftUpCramped",
1752 MATH->SuperscriptShiftUpCramped);
1753 dump_intfield(L, "SuperscriptBottomMin", MATH->SuperscriptBottomMin);
1754 dump_intfield(L, "SuperscriptBaselineDropMax",
1755 MATH->SuperscriptBaselineDropMax);
1756 dump_intfield(L, "SubSuperscriptGapMin", MATH->SubSuperscriptGapMin);
1757 dump_intfield(L, "SuperscriptBottomMaxWithSubscript",
1758 MATH->SuperscriptBottomMaxWithSubscript);
1759 dump_intfield(L, "SpaceAfterScript", MATH->SpaceAfterScript);
1760 dump_intfield(L, "UpperLimitGapMin", MATH->UpperLimitGapMin);
1761 dump_intfield(L, "UpperLimitBaselineRiseMin",
1762 MATH->UpperLimitBaselineRiseMin);
1763 dump_intfield(L, "LowerLimitGapMin", MATH->LowerLimitGapMin);
1764 dump_intfield(L, "LowerLimitBaselineDropMin",
1765 MATH->LowerLimitBaselineDropMin);
1766 dump_intfield(L, "StackTopShiftUp", MATH->StackTopShiftUp);
1767 dump_intfield(L, "StackTopDisplayStyleShiftUp",
1768 MATH->StackTopDisplayStyleShiftUp);
1769 dump_intfield(L, "StackBottomShiftDown", MATH->StackBottomShiftDown);
1770 dump_intfield(L, "StackBottomDisplayStyleShiftDown",
1771 MATH->StackBottomDisplayStyleShiftDown);
1772 dump_intfield(L, "StackGapMin", MATH->StackGapMin);
1773 dump_intfield(L, "StackDisplayStyleGapMin", MATH->StackDisplayStyleGapMin);
1774 dump_intfield(L, "StretchStackTopShiftUp", MATH->StretchStackTopShiftUp);
1775 dump_intfield(L, "StretchStackBottomShiftDown",
1776 MATH->StretchStackBottomShiftDown);
1777 dump_intfield(L, "StretchStackGapAboveMin", MATH->StretchStackGapAboveMin);
1778 dump_intfield(L, "StretchStackGapBelowMin", MATH->StretchStackGapBelowMin);
1779 dump_intfield(L, "FractionNumeratorShiftUp",
1780 MATH->FractionNumeratorShiftUp);
1781 dump_intfield(L, "FractionNumeratorDisplayStyleShiftUp",
1782 MATH->FractionNumeratorDisplayStyleShiftUp);
1783 dump_intfield(L, "FractionDenominatorShiftDown",
1784 MATH->FractionDenominatorShiftDown);
1785 dump_intfield(L, "FractionDenominatorDisplayStyleShiftDown",
1786 MATH->FractionDenominatorDisplayStyleShiftDown);
1787 dump_intfield(L, "FractionNumeratorGapMin", MATH->FractionNumeratorGapMin);
1788 dump_intfield(L, "FractionNumeratorDisplayStyleGapMin",
1789 MATH->FractionNumeratorDisplayStyleGapMin);
1790 dump_intfield(L, "FractionRuleThickness", MATH->FractionRuleThickness);
1791 dump_intfield(L, "FractionDenominatorGapMin",
1792 MATH->FractionDenominatorGapMin);
1793 dump_intfield(L, "FractionDenominatorDisplayStyleGapMin",
1794 MATH->FractionDenominatorDisplayStyleGapMin);
1795 dump_intfield(L, "SkewedFractionHorizontalGap",
1796 MATH->SkewedFractionHorizontalGap);
1797 dump_intfield(L, "SkewedFractionVerticalGap",
1798 MATH->SkewedFractionVerticalGap);
1799 dump_intfield(L, "OverbarVerticalGap", MATH->OverbarVerticalGap);
1800 dump_intfield(L, "OverbarRuleThickness", MATH->OverbarRuleThickness);
1801 dump_intfield(L, "OverbarExtraAscender", MATH->OverbarExtraAscender);
1802 dump_intfield(L, "UnderbarVerticalGap", MATH->UnderbarVerticalGap);
1803 dump_intfield(L, "UnderbarRuleThickness", MATH->UnderbarRuleThickness);
1804 dump_intfield(L, "UnderbarExtraDescender", MATH->UnderbarExtraDescender);
1805 dump_intfield(L, "RadicalVerticalGap", MATH->RadicalVerticalGap);
1806 dump_intfield(L, "RadicalDisplayStyleVerticalGap",
1807 MATH->RadicalDisplayStyleVerticalGap);
1808 dump_intfield(L, "RadicalRuleThickness", MATH->RadicalRuleThickness);
1809 dump_intfield(L, "RadicalExtraAscender", MATH->RadicalExtraAscender);
1810 dump_intfield(L, "RadicalKernBeforeDegree", MATH->RadicalKernBeforeDegree);
1811 dump_intfield(L, "RadicalKernAfterDegree", MATH->RadicalKernAfterDegree);
1812 dump_intfield(L, "RadicalDegreeBottomRaisePercent",
1813 MATH->RadicalDegreeBottomRaisePercent);
1814 dump_intfield(L, "MinConnectorOverlap", MATH->MinConnectorOverlap);
1817 /* the handling of BASE is untested, no font */
1818 static void handle_baselangextent(lua_State * L, struct baselangextent *ble);
1820 static void do_handle_baselangextent(lua_State * L, struct baselangextent *ble)
1822 dump_tag(L, "tag", ble->lang);
1823 dump_intfield(L, "ascent", ble->ascent);
1824 dump_intfield(L, "descent", ble->descent);
1825 lua_newtable(L);
1826 handle_baselangextent(L, ble->features);
1827 lua_setfield(L, -2, "features");
1831 static void handle_baselangextent(lua_State * L, struct baselangextent *ble)
1833 struct baselangextent *next;
1834 NESTED_TABLE(do_handle_baselangextent, ble, 4);
1838 static void handle_base(lua_State * L, struct Base *Base)
1840 int i;
1841 struct basescript *next = Base->scripts;
1842 lua_newtable(L);
1843 for (i = 0; i < Base->baseline_cnt; i++) {
1844 lua_pushstring(L, make_tag_string(Base->baseline_tags[i]));
1845 lua_rawseti(L, -2, (i + 1));
1847 lua_setfield(L, -2, "tags");
1848 if (next != NULL) {
1849 lua_newtable(L);
1850 while (next != NULL) {
1851 lua_pushstring(L, make_tag_string(next->script));
1852 lua_newtable(L);
1853 dump_intfield(L, "default_baseline", (next->def_baseline + 1));
1854 lua_newtable(L);
1855 for (i = 0; i < Base->baseline_cnt; i++) {
1856 if (next->baseline_pos != NULL) /* default omitted */
1857 lua_pushnumber(L, next->baseline_pos[i]);
1858 else
1859 lua_pushnumber(L, 0);
1860 lua_rawseti(L, -2, (i + 1));
1862 lua_setfield(L, -2, "baseline");
1863 lua_newtable(L);
1864 handle_baselangextent(L, next->langs);
1865 lua_setfield(L, -2, "lang");
1866 lua_rawset(L, -3);
1867 next = next->next;
1869 lua_setfield(L, -2, "scripts");
1874 static void handle_axismap(lua_State * L, struct axismap *am)
1876 int i;
1877 lua_checkstack(L, 3);
1878 lua_newtable(L);
1879 for (i = 0; i < am->points; i++) {
1880 lua_pushnumber(L, am->blends[i]);
1881 lua_rawseti(L, -2, (i + 1));
1883 lua_setfield(L, -2, "blends");
1884 lua_newtable(L);
1885 for (i = 0; i < am->points; i++) {
1886 lua_pushnumber(L, am->designs[i]);
1887 lua_rawseti(L, -2, (i + 1));
1889 lua_setfield(L, -2, "designs");
1890 dump_realfield(L, "min", am->min);
1891 dump_realfield(L, "def", am->def);
1892 dump_realfield(L, "max", am->max);
1896 static void handle_mmset(lua_State * L, struct mmset *mm)
1898 int i;
1899 lua_newtable(L);
1900 for (i = 0; i < mm->axis_count; i++) {
1901 lua_pushstring(L, mm->axes[i]);
1902 lua_rawseti(L, -2, (i + 1));
1904 lua_setfield(L, -2, "axes");
1906 dump_intfield(L, "instance_count", mm->instance_count);
1907 /* SplineFont *normal; *//* this is the parent */
1908 if (mm->instance_count > 0) {
1909 lua_newtable(L);
1910 for (i = 0; i < mm->instance_count * mm->axis_count; i++) {
1911 lua_pushnumber(L, mm->positions[i]);
1912 lua_rawseti(L, -2, (i + 1));
1914 lua_setfield(L, -2, "positions");
1916 /* better not to do this */
1917 #if 0
1919 struct mmset *mmsave;
1920 lua_newtable(L);
1921 for (i = 0; i < mm->instance_count; i++) {
1922 lua_checkstack(L, 20);
1923 lua_createtable(L, 0, 60);
1924 mmsave = mm->instances[i]->mm;
1925 mm->instances[i]->mm = NULL;
1926 handle_splinefont(L, mm->instances[i]);
1927 mm->instances[i]->mm = mmsave;
1928 lua_rawseti(L, -2, (i + 1));
1930 lua_setfield(L, -2, "instances");
1932 #endif
1934 lua_newtable(L);
1935 for (i = 0; i < mm->instance_count; i++) {
1936 lua_pushnumber(L, mm->defweights[i]);
1937 lua_rawseti(L, -2, (i + 1));
1939 lua_setfield(L, -2, "defweights");
1942 if (mm->axismaps != NULL) {
1943 lua_newtable(L);
1944 for (i = 0; i < mm->axis_count; i++) {
1945 lua_newtable(L);
1946 handle_axismap(L, &(mm->axismaps[i]));
1947 lua_rawseti(L, -2, (i + 1));
1949 lua_setfield(L, -2, "axismaps");
1951 dump_stringfield(L, "cdv", mm->cdv);
1952 dump_stringfield(L, "ndv", mm->ndv);
1957 static void handle_splinefont(lua_State * L, struct splinefont *sf)
1959 int k;
1960 int fix_notdef = 0;
1961 int l = -1;
1963 dump_stringfield(L, "table_version", LUA_OTF_VERSION);
1964 dump_stringfield(L, "fontname", sf->fontname);
1965 dump_stringfield(L, "fullname", sf->fullname);
1966 dump_stringfield(L, "familyname", sf->familyname);
1967 dump_stringfield(L, "weight", sf->weight);
1968 dump_stringfield(L, "copyright", sf->copyright);
1969 dump_stringfield(L, "filename", sf->filename);
1970 /* dump_stringfield(L,"defbasefilename", sf->defbasefilename); */
1971 dump_stringfield(L, "version", sf->version);
1972 dump_floatfield(L, "italicangle", sf->italicangle);
1973 dump_floatfield(L, "upos", sf->upos);
1974 dump_floatfield(L, "uwidth", sf->uwidth);
1975 dump_intfield(L, "ascent", sf->ascent);
1976 dump_intfield(L, "descent", sf->descent);
1977 if (sf->uniqueid!=0) {
1978 dump_intfield(L, "uniqueid", sf->uniqueid);
1981 if (sf->glyphcnt > 0) {
1982 dump_intfield(L, "glyphcnt", sf->glyphmax - sf->glyphmin + 1);
1983 } else {
1984 dump_intfield(L, "glyphcnt", 0);
1987 dump_intfield(L, "glyphmax", sf->glyphmax - 1);
1988 dump_intfield(L, "glyphmin", sf->glyphmin);
1989 dump_intfield(L, "units_per_em", sf->units_per_em);
1991 if (sf->possub != NULL) {
1992 lua_newtable(L);
1993 handle_generic_fpst(L, sf->possub);
1994 lua_setfield(L, -2, "lookups");
1997 lua_checkstack(L, 4);
1998 lua_createtable(L, sf->glyphcnt, 0);
2000 /* This after-the-fact type discovery is not brilliant,
2001 I should really add a 'format' key in the structure */
2002 if ((sf->origname != NULL) &&
2003 (strmatch(sf->origname + strlen(sf->origname) - 4, ".pfa") == 0 ||
2004 strmatch(sf->origname + strlen(sf->origname) - 4, ".pfb") == 0)) {
2005 fix_notdef = 1;
2008 if (fix_notdef) {
2009 /* some code to ensure that the .notdef ends up in slot 0
2010 (this will actually be enforced by the CFF writer) */
2011 for (k = 0; k < sf->glyphcnt; k++) {
2012 if (sf->glyphs[k]) {
2013 if (strcmp(sf->glyphs[k]->name, ".notdef") == 0) {
2014 l = k;
2018 if (l == -1) { /* fake a .notdef at the end */
2019 l = sf->glyphcnt;
2021 for (k = 0; k < l; k++) {
2022 if (sf->glyphs[k]) {
2023 lua_pushnumber(L, (k + 1));
2024 lua_createtable(L, 0, 12);
2025 handle_splinechar(L, sf->glyphs[k], sf->hasvmetrics);
2026 lua_rawset(L, -3);
2029 if (sf->glyphs != NULL && l < sf->glyphcnt) {
2030 lua_pushnumber(L, 0);
2031 if (sf->glyphs[l]) {
2032 lua_createtable(L, 0, 12);
2033 handle_splinechar(L, sf->glyphs[l], sf->hasvmetrics);
2034 } else {
2035 lua_createtable(L, 0, 0);
2037 lua_rawset(L, -3);
2040 if ((l + 1) < sf->glyphcnt) {
2041 for (k = (l + 1); k < sf->glyphcnt; k++) {
2042 if (sf->glyphs[k]) {
2043 lua_pushnumber(L, k);
2044 lua_createtable(L, 0, 12);
2045 handle_splinechar(L, sf->glyphs[k], sf->hasvmetrics);
2046 lua_rawset(L, -3);
2050 lua_setfield(L, -2, "glyphs");
2052 /* dump_intfield(L,"changed", sf->changed); */
2053 dump_intfield(L, "hasvmetrics", sf->hasvmetrics);
2054 dump_intfield(L, "onlybitmaps", sf->onlybitmaps);
2055 dump_intfield(L, "serifcheck", sf->serifcheck);
2056 dump_intfield(L, "isserif", sf->isserif);
2057 dump_intfield(L, "issans", sf->issans);
2058 dump_intfield(L, "encodingchanged", sf->encodingchanged);
2059 dump_intfield(L, "strokedfont", sf->strokedfont);
2060 dump_intfield(L, "use_typo_metrics", sf->use_typo_metrics);
2061 dump_intfield(L, "weight_width_slope_only", sf->weight_width_slope_only);
2062 dump_intfield(L, "head_optimized_for_cleartype",
2063 sf->head_optimized_for_cleartype);
2065 dump_enumfield(L, "uni_interp", (sf->uni_interp + 1), uni_interp_enum);
2067 if (sf->map != NULL) {
2068 lua_newtable(L);
2069 handle_encmap(L, sf->map, l);
2070 lua_setfield(L, -2, "map");
2073 dump_stringfield(L, "origname", sf->origname); /* new */
2075 if (sf->private != NULL) {
2076 lua_newtable(L);
2077 handle_psdict(L, sf->private);
2078 lua_setfield(L, -2, "private");
2081 dump_stringfield(L, "xuid", sf->xuid);
2083 lua_createtable(L, 0, 40);
2084 handle_pfminfo(L, sf->pfminfo);
2085 lua_setfield(L, -2, "pfminfo");
2087 if (sf->names != NULL) {
2088 lua_newtable(L);
2089 handle_ttflangname(L, sf->names);
2090 lua_setfield(L, -2, "names");
2093 lua_createtable(L, 0, 4);
2094 dump_stringfield(L, "registry", sf->cidregistry);
2095 dump_stringfield(L, "ordering", sf->ordering);
2096 dump_intfield(L, "version", sf->cidversion);
2097 dump_intfield(L, "supplement", sf->supplement);
2098 lua_setfield(L, -2, "cidinfo");
2100 /* SplineFont *cidmaster *//* parent in a subfont */
2101 if (sf->subfontcnt > 0) {
2102 lua_createtable(L, sf->subfontcnt, 0);
2103 for (k = 0; k < sf->subfontcnt; k++) {
2104 lua_checkstack(L, 10);
2105 lua_newtable(L);
2106 handle_splinefont(L, sf->subfonts[k]);
2107 lua_rawseti(L, -2, (k + 1));
2109 lua_setfield(L, -2, "subfonts");
2112 dump_stringfield(L, "comments", sf->comments);
2113 dump_stringfield(L, "fontlog", sf->fontlog);
2115 if (sf->cvt_names != NULL) {
2116 lua_newtable(L);
2117 for (k = 0; sf->cvt_names[k] != END_CVT_NAMES; ++k) {
2118 lua_pushstring(L, sf->cvt_names[k]);
2119 lua_rawseti(L, -2, (k + 1));
2121 lua_setfield(L, -2, "cvt_names");
2124 if (sf->ttf_tables != NULL) {
2125 lua_newtable(L);
2126 handle_ttf_table(L, sf->ttf_tables);
2127 lua_setfield(L, -2, "ttf_tables");
2130 if (sf->ttf_tab_saved != NULL) {
2131 lua_newtable(L);
2132 handle_ttf_table(L, sf->ttf_tab_saved);
2133 lua_setfield(L, -2, "ttf_tab_saved");
2136 if (sf->texdata.type != tex_unset) {
2137 lua_newtable(L);
2138 dump_enumfield(L, "type", sf->texdata.type, tex_type_enum);
2139 lua_newtable(L);
2140 for (k = 0; k < 22; k++) {
2141 lua_pushnumber(L, k);
2142 lua_pushnumber(L, sf->texdata.params[k]);
2143 lua_rawset(L, -3);
2145 lua_setfield(L, -2, "params");
2146 lua_setfield(L, -2, "texdata");
2148 if (sf->anchor != NULL) {
2149 lua_newtable(L);
2150 handle_anchorclass(L, sf->anchor);
2151 lua_setfield(L, -2, "anchor_classes");
2153 if (sf->kerns != NULL) {
2154 lua_newtable(L);
2155 handle_kernclass(L, sf->kerns, NULL);
2156 lua_setfield(L, -2, "kerns");
2158 if (sf->vkerns != NULL) {
2159 lua_newtable(L);
2160 handle_kernclass(L, sf->vkerns, NULL);
2161 lua_setfield(L, -2, "vkerns");
2163 if (sf->gsub_lookups != NULL) {
2164 lua_newtable(L);
2165 handle_lookup(L, sf->gsub_lookups, sf);
2166 lua_setfield(L, -2, "gsub");
2168 if (sf->gpos_lookups != NULL) {
2169 lua_newtable(L);
2170 handle_lookup(L, sf->gpos_lookups, sf);
2171 lua_setfield(L, -2, "gpos");
2174 if (sf->mm != NULL) {
2175 lua_newtable(L);
2176 handle_mmset(L, sf->mm);
2177 lua_setfield(L, -2, "mm");
2179 dump_stringfield(L, "chosenname", sf->chosenname);
2181 if (sf->macstyle!=-1) {
2182 dump_intfield(L, "macstyle", sf->macstyle);
2184 dump_stringfield(L, "fondname", sf->fondname);
2186 dump_intfield(L, "design_size", sf->design_size);
2187 dump_intfield(L, "fontstyle_id", sf->fontstyle_id);
2189 if (sf->fontstyle_name != NULL) {
2190 lua_newtable(L);
2191 handle_otfname(L, sf->fontstyle_name);
2192 lua_setfield(L, -2, "fontstyle_name");
2195 dump_intfield(L, "design_range_bottom", sf->design_range_bottom);
2196 dump_intfield(L, "design_range_top", sf->design_range_top);
2197 dump_floatfield(L, "strokewidth", sf->strokewidth);
2199 if (sf->mark_class_cnt > 0) {
2200 lua_newtable(L);
2201 for (k = 0; k < sf->mark_class_cnt; k++) {
2202 if (sf->mark_class_names[k] != NULL) {
2203 lua_pushstring(L, sf->mark_class_names[k]);
2204 lua_pushstring(L, sf->mark_classes[k]);
2205 lua_rawset(L, -3);
2208 lua_setfield(L, -2, "mark_classes");
2211 dump_uintfield(L, "creationtime", sf->creationtime);
2212 dump_uintfield(L, "modificationtime", sf->modificationtime);
2214 dump_intfield(L, "os2_version", sf->os2_version);
2215 dump_intfield(L, "sfd_version", sf->sfd_version);
2217 if (sf->MATH != NULL) {
2218 lua_newtable(L);
2219 handle_MATH(L, sf->MATH);
2220 lua_setfield(L, -2, "math");
2223 if (sf->loadvalidation_state != 0) {
2224 int val, st;
2225 lua_newtable(L);
2226 val = 1;
2227 st = sf->loadvalidation_state;
2228 if (st & lvs_bad_ps_fontname) {
2229 lua_pushliteral(L, "bad_ps_fontname");
2230 lua_rawseti(L, -2, val++);
2232 if (st & lvs_bad_glyph_table) {
2233 lua_pushliteral(L, "bad_glyph_table");
2234 lua_rawseti(L, -2, val++);
2236 if (st & lvs_bad_cff_table) {
2237 lua_pushliteral(L, "bad_cff_table");
2238 lua_rawseti(L, -2, val++);
2240 if (st & lvs_bad_metrics_table) {
2241 lua_pushliteral(L, "bad_metrics_table");
2242 lua_rawseti(L, -2, val++);
2244 if (st & lvs_bad_cmap_table) {
2245 lua_pushliteral(L, "bad_cmap_table");
2246 lua_rawseti(L, -2, val++);
2248 if (st & lvs_bad_bitmaps_table) {
2249 lua_pushliteral(L, "bad_bitmaps_table");
2250 lua_rawseti(L, -2, val++);
2252 if (st & lvs_bad_gx_table) {
2253 lua_pushliteral(L, "bad_gx_table");
2254 lua_rawseti(L, -2, val++);
2256 if (st & lvs_bad_ot_table) {
2257 lua_pushliteral(L, "bad_ot_table");
2258 lua_rawseti(L, -2, val++);
2260 if (st & lvs_bad_os2_version) {
2261 lua_pushliteral(L, "bad_os2_version");
2262 lua_rawseti(L, -2, val++);
2264 if (st & lvs_bad_sfnt_header) {
2265 lua_pushliteral(L, "bad_sfnt_header");
2266 lua_rawseti(L, -2, val++);
2268 lua_setfield(L, -2, "validation_state");
2271 if (sf->horiz_base != NULL) {
2272 lua_newtable(L);
2273 handle_base(L, sf->horiz_base);
2274 lua_setfield(L, -2, "horiz_base");
2276 if (sf->vert_base != NULL) {
2277 lua_newtable(L);
2278 handle_base(L, sf->vert_base);
2279 lua_setfield(L, -2, "vert_base");
2281 dump_intfield(L, "extrema_bound", sf->extrema_bound);
2284 static int ff_make_table(lua_State * L)
2286 SplineFont *sf;
2287 sf = *(check_isfont(L, 1));
2288 if (sf == NULL) {
2289 lua_pushboolean(L, 0);
2290 } else {
2291 lua_createtable(L, 0, 60);
2292 handle_splinefont(L, sf);
2294 return 1;
2297 static void do_ff_info(lua_State * L, SplineFont * sf)
2299 lua_newtable(L);
2300 dump_stringfield(L, "familyname", sf->familyname);
2301 dump_stringfield(L, "fontname", sf->fontname);
2302 dump_stringfield(L, "fullname", sf->fullname);
2303 dump_floatfield(L, "italicangle", sf->italicangle);
2304 dump_stringfield(L, "version", sf->version);
2305 dump_stringfield(L, "weight", sf->weight);
2307 dump_intfield(L, "units_per_em", sf->units_per_em);
2308 /* These are not assigned in info... */
2309 /*dump_intfield(L, "design_range_bottom", sf->design_range_bottom);*/
2310 /*dump_intfield(L, "design_range_top", sf->design_range_top);*/
2311 /*dump_intfield(L, "design_size", sf->design_size);*/
2313 lua_createtable(L, 0, 40);
2314 handle_pfminfo(L, sf->pfminfo);
2315 lua_setfield(L, -2, "pfminfo");
2317 /* Do we need this ? */
2318 if (sf->names != NULL) {
2319 lua_newtable(L);
2320 handle_ttflangname(L, sf->names);
2321 lua_setfield(L, -2, "names");
2325 typedef enum {
2326 FK_table_version = 0,
2327 FK_fontname,
2328 FK_fullname,
2329 FK_familyname,
2330 FK_weight,
2331 FK_copyright,
2332 FK_filename,
2333 FK_version,
2334 FK_italicangle,
2335 FK_upos,
2336 FK_uwidth,
2337 FK_ascent,
2338 FK_descent,
2339 FK_uniqueid,
2340 FK_glyphcnt,
2341 FK_glyphmax,
2342 FK_glyphmin,
2343 FK_units_per_em,
2344 FK_lookups,
2345 FK_glyphs,
2346 FK_hasvmetrics,
2347 FK_onlybitmaps,
2348 FK_serifcheck,
2349 FK_isserif,
2350 FK_issans,
2351 FK_encodingchanged,
2352 FK_strokedfont,
2353 FK_use_typo_metrics,
2354 FK_weight_width_slope_only,
2355 FK_head_optimized_for_cleartype,
2356 FK_uni_interp,
2357 FK_map,
2358 FK_origname,
2359 FK_private,
2360 FK_xuid,
2361 FK_pfminfo,
2362 FK_names,
2363 FK_cidinfo,
2364 FK_subfonts,
2365 FK_comments,
2366 FK_fontlog,
2367 FK_cvt_names,
2368 FK_ttf_tables,
2369 FK_ttf_tab_saved,
2370 FK_texdata,
2371 FK_anchor_classes,
2372 FK_kerns,
2373 FK_vkerns,
2374 FK_gsub,
2375 FK_gpos,
2376 /* FK_sm, */ /*this was removed because AAT is not supported anymore*/
2377 FK_features,
2378 FK_mm,
2379 FK_chosenname,
2380 FK_macstyle,
2381 FK_fondname,
2382 FK_design_size,
2383 FK_fontstyle_id,
2384 FK_fontstyle_name,
2385 FK_design_range_bottom,
2386 FK_design_range_top,
2387 FK_strokewidth,
2388 FK_mark_classes,
2389 FK_creationtime,
2390 FK_modificationtime,
2391 FK_os2_version,
2392 FK_sfd_version,
2393 FK_math,
2394 FK_validation_state,
2395 FK_horiz_base,
2396 FK_vert_base,
2397 FK_extrema_bound,
2398 } font_key_values;
2400 const char *font_keys[] = {
2401 "table_version",
2402 "fontname",
2403 "fullname",
2404 "familyname",
2405 "weight",
2406 "copyright",
2407 "filename",
2408 "version",
2409 "italicangle",
2410 "upos",
2411 "uwidth",
2412 "ascent",
2413 "descent",
2414 "uniqueid",
2415 "glyphcnt",
2416 "glyphmax",
2417 "glyphmin",
2418 "units_per_em",
2419 "lookups",
2420 "glyphs",
2421 "hasvmetrics",
2422 "onlybitmaps",
2423 "serifcheck",
2424 "isserif",
2425 "issans",
2426 "encodingchanged",
2427 "strokedfont",
2428 "use_typo_metrics",
2429 "weight_width_slope_only",
2430 "head_optimized_for_cleartype",
2431 "uni_interp",
2432 "map",
2433 "origname",
2434 "private",
2435 "xuid",
2436 "pfminfo",
2437 "names",
2438 "cidinfo",
2439 "subfonts",
2440 "comments",
2441 "fontlog",
2442 "cvt_names",
2443 "ttf_tables",
2444 "ttf_tab_saved",
2445 "texdata",
2446 "anchor_classes",
2447 "kerns",
2448 "vkerns",
2449 "gsub",
2450 "gpos",
2451 "features",
2452 "mm",
2453 "chosenname",
2454 "macstyle",
2455 "fondname",
2456 "design_size",
2457 "fontstyle_id",
2458 "fontstyle_name",
2459 "design_range_bottom",
2460 "design_range_top",
2461 "strokewidth",
2462 "mark_classes",
2463 "creationtime",
2464 "modificationtime",
2465 "os2_version",
2466 "sfd_version",
2467 "math",
2468 "validation_state",
2469 "horiz_base",
2470 "vert_base",
2471 "extrema_bound",
2472 NULL
2476 typedef enum {
2477 GK_name = 0,
2478 GK_unicode,
2479 GK_boundingbox,
2480 GK_vwidth,
2481 GK_width,
2482 GK_lsidebearing,
2483 GK_class,
2484 GK_kerns,
2485 GK_vkerns,
2486 GK_dependents,
2487 GK_lookups,
2488 GK_ligatures,
2489 GK_comment,
2490 GK_anchors,
2491 GK_altuni,
2492 GK_tex_height,
2493 GK_tex_depth,
2494 GK_is_extended_shape,
2495 GK_italic_correction,
2496 GK_top_accent,
2497 GK_vert_variants,
2498 GK_horiz_variants,
2499 GK_mathkern,
2500 GK_orig_pos,
2501 } font_glyph_key_values;
2503 const char *font_glyph_keys[] = {
2504 "name",
2505 "unicode",
2506 "boundingbox",
2507 "vwidth",
2508 "width",
2509 "lsidebearing",
2510 "class",
2511 "kerns",
2512 "vkerns",
2513 "dependents",
2514 "lookups",
2515 "ligatures",
2516 "comment",
2517 "anchors",
2518 "altuni",
2519 "tex_height",
2520 "tex_depth",
2521 "is_extended_shape",
2522 "italic_correction",
2523 "top_accent",
2524 "vert_variants",
2525 "horiz_variants",
2526 "mathkern",
2527 "orig_pos",
2528 NULL
2532 static int ff_fields(lua_State * L)
2534 int i;
2535 const char **fields = NULL;
2536 if (is_userdata(L, 1, FONT_METATABLE) ||
2537 is_userdata(L, 1, FONT_SUBFONT_METATABLE)) {
2538 fields = font_keys;
2539 } else if (is_userdata(L, 1, FONT_GLYPH_METATABLE)) {
2540 fields = font_glyph_keys;
2542 if (fields != NULL) {
2543 lua_newtable(L);
2544 for (i = 0; fields[i] != NULL; i++) {
2545 lua_pushstring(L, fields[i]);
2546 lua_rawseti(L, -2, (i + 1));
2548 } else {
2549 lua_pushnil(L);
2551 return 1;
2556 static int ff_glyphs_index(lua_State * L)
2559 SplineFont *sf;
2560 int gid = 0;
2561 int l = -1;
2562 int fix_notdef = 0;
2563 lua_pushstring(L, "__sf");
2564 lua_rawget(L, 1);
2565 /* sf = *check_isfont(L, -1); */
2566 if (!(is_userdata(L, -1, FONT_METATABLE) ||
2567 is_userdata(L, -1, FONT_SUBFONT_METATABLE))) {
2568 return luaL_error(L,
2569 "fontloader.__index: expected a (sub)font userdata object\n");
2571 sf = *((SplineFont **)lua_touserdata(L, -1));
2573 lua_pop(L, 1);
2574 gid = luaL_checkinteger(L, 2);
2575 /* if (gid < sf->glyphmin || gid >= sf->glyphmax) {*/
2576 if (gid < sf->glyphmin || gid > sf->glyphmax) {
2577 return luaL_error(L, "fontloader.glyphs.__index: index is invalid\n");
2579 /* This after-the-fact type discovery is not brilliant,
2580 I should really add a 'format' key in the structure */
2581 if ((sf->origname != NULL) &&
2582 (strmatch(sf->origname + strlen(sf->origname) - 4, ".pfa") == 0 ||
2583 strmatch(sf->origname + strlen(sf->origname) - 4, ".pfb") == 0)) {
2584 fix_notdef = 1;
2586 /* some code to ensure that the .notdef ends up in slot 0
2587 (this will actually be enforced by the CFF writer) */
2588 if (fix_notdef) {
2589 l = notdef_loc(sf);
2590 /* now l is the .notdef location, adjust gid if needed */
2591 if (l == sf->glyphcnt) { /* no .notdef at all, will be created at zero */
2592 if (gid == 0) {
2593 gid = l; /* .notdef was added at end */
2594 } else {
2595 gid--; /* f.glyphs[gid] == sf->glyphs[gid-1] */
2597 } else if (l != 0) {
2598 if (gid == 0) {
2599 gid = l;
2600 } else if (gid < l) {
2601 gid--;
2605 /* push the glyph */
2606 if (sf->glyphs[gid] && sf->glyphs[gid] != (struct splinechar *)-1) {
2607 lua_ff_pushglyph(L, sf->glyphs[gid]);
2608 } else {
2609 lua_pushnil(L);
2611 return 1;
2614 static int ff_glyph_index(lua_State * L)
2616 struct splinechar *glyph;
2617 int key;
2618 glyph = *check_isglyph(L, 1);
2619 if (glyph == NULL) {
2620 return luaL_error(L,
2621 "fontloader.glyph.__index: glyph is nonexistent\n");
2623 if (!lua_isstring(L, 2)) { /* 1 == 'font' */
2624 return luaL_error(L,
2625 "fontloader.glyph.__index: can only be indexed by string\n");
2627 key = luaL_checkoption(L, 2, NULL, font_glyph_keys);
2628 switch (key) {
2629 case GK_name:
2630 lua_pushstring(L, glyph->name);
2631 break;
2632 case GK_unicode:
2633 lua_pushnumber(L, glyph->unicodeenc);
2634 break;
2635 case GK_boundingbox:
2636 if (glyph->xmax == 0 && glyph->ymax == 0 && glyph->xmin == 0
2637 && glyph->ymin == 0) {
2638 DBounds bb;
2639 SplineCharFindBounds(glyph, &bb);
2640 glyph->xmin = bb.minx;
2641 glyph->ymin = bb.miny;
2642 glyph->xmax = bb.maxx;
2643 glyph->ymax = bb.maxy;
2645 lua_createtable(L, 4, 0);
2646 lua_pushnumber(L, 1);
2647 lua_pushnumber(L, glyph->xmin);
2648 lua_rawset(L, -3);
2649 lua_pushnumber(L, 2);
2650 lua_pushnumber(L, glyph->ymin);
2651 lua_rawset(L, -3);
2652 lua_pushnumber(L, 3);
2653 lua_pushnumber(L, glyph->xmax);
2654 lua_rawset(L, -3);
2655 lua_pushnumber(L, 4);
2656 lua_pushnumber(L, glyph->ymax);
2657 lua_rawset(L, -3);
2658 break;
2659 case GK_vwidth:
2660 lua_pushnumber(L, glyph->vwidth);
2661 break;
2662 case GK_width:
2663 lua_pushnumber(L, glyph->width);
2664 break;
2665 case GK_lsidebearing:
2666 lua_pushnumber(L, glyph->lsidebearing);
2667 break;
2668 case GK_class:
2669 if (glyph->glyph_class > 0) {
2670 lua_pushstring(L, glyph_class_enum[glyph->glyph_class]);
2671 } else {
2672 lua_pushnil(L);
2674 break;
2675 case GK_kerns:
2676 if (glyph->kerns != NULL) {
2677 lua_newtable(L);
2678 handle_kernpair(L, glyph->kerns);
2679 } else {
2680 lua_pushnil(L);
2682 break;
2683 case GK_vkerns:
2684 if (glyph->vkerns != NULL) {
2685 lua_newtable(L);
2686 handle_kernpair(L, glyph->vkerns);
2687 } else {
2688 lua_pushnil(L);
2690 break;
2691 case GK_dependents:
2692 if (glyph->dependents != NULL) {
2693 lua_newtable(L);
2694 handle_splinecharlist(L, glyph->dependents);
2695 } else {
2696 lua_pushnil(L);
2698 break;
2699 case GK_lookups:
2700 if (glyph->possub != NULL) {
2701 lua_newtable(L);
2702 handle_generic_pst(L, glyph->possub);
2703 } else {
2704 lua_pushnil(L);
2706 break;
2707 case GK_ligatures:
2708 if (glyph->ligofme != NULL) {
2709 lua_newtable(L);
2710 handle_liglist(L, glyph->ligofme);
2711 } else {
2712 lua_pushnil(L);
2714 break;
2715 case GK_comment:
2716 lua_pushstring(L, glyph->comment);
2717 break;
2718 case GK_anchors:
2719 if (glyph->anchor != NULL) {
2720 lua_newtable(L);
2721 handle_anchorpoint(L, glyph->anchor);
2722 } else {
2723 lua_pushnil(L);
2725 break;
2726 case GK_altuni:
2727 if (glyph->altuni != NULL) {
2728 lua_newtable(L);
2729 handle_altuni(L, glyph->altuni);
2730 } else {
2731 lua_pushnil(L);
2733 break;
2734 case GK_tex_height:
2735 if (glyph->tex_height != TEX_UNDEF) {
2736 lua_pushnumber(L, glyph->tex_height);
2737 } else {
2738 lua_pushnil(L);
2740 break;
2741 case GK_tex_depth:
2742 if (glyph->tex_height != TEX_UNDEF) {
2743 lua_pushnumber(L, glyph->tex_depth);
2744 } else {
2745 lua_pushnil(L);
2747 break;
2748 case GK_is_extended_shape:
2749 lua_pushnumber(L, glyph->is_extended_shape);
2750 break;
2751 case GK_italic_correction:
2752 if (glyph->italic_correction != TEX_UNDEF) {
2753 lua_pushnumber(L, glyph->italic_correction);
2754 } else {
2755 lua_pushnil(L);
2757 break;
2758 case GK_top_accent:
2759 if (glyph->top_accent_horiz != TEX_UNDEF) {
2760 lua_pushnumber(L, glyph->top_accent_horiz);
2761 } else {
2762 lua_pushnil(L);
2764 break;
2765 case GK_vert_variants:
2766 if (glyph->vert_variants != NULL) {
2767 lua_newtable(L);
2768 handle_glyphvariants(L, glyph->vert_variants);
2769 } else {
2770 lua_pushnil(L);
2772 break;
2773 case GK_horiz_variants:
2774 if (glyph->horiz_variants != NULL) {
2775 lua_newtable(L);
2776 handle_glyphvariants(L, glyph->horiz_variants);
2777 } else {
2778 lua_pushnil(L);
2780 break;
2781 case GK_mathkern:
2782 if (glyph->mathkern != NULL) {
2783 lua_newtable(L);
2784 handle_mathkern(L, glyph->mathkern);
2785 } else {
2786 lua_pushnil(L);
2788 break;
2789 case GK_orig_pos:
2790 if (glyph->orig_pos>=0) {
2791 lua_pushnumber(L, glyph->orig_pos);
2792 } else {
2793 lua_pushnil(L);
2795 break;
2796 default:
2797 lua_pushnil(L);
2799 return 1;
2803 static int ff_index(lua_State * L)
2805 SplineFont *sf;
2806 int k, key;
2807 /* sf = *check_isfont(L, 1); */
2808 if (!(is_userdata(L, 1, FONT_METATABLE) ||
2809 is_userdata(L, 1, FONT_SUBFONT_METATABLE))) {
2810 return luaL_error(L,
2811 "fontloader.__index: expected a (sub)font userdata object\n");
2813 sf = *((SplineFont **)lua_touserdata(L, 1));
2815 if (sf == NULL) {
2816 /* return luaL_error(L, */
2817 /* "fontloader.__index: font is nonexistent or freed already\n");*/
2818 lua_pushnil(L);
2819 return 1;
2821 if (!lua_isstring(L, 2)) { /* 1 == 'font' */
2822 return luaL_error(L,
2823 "fontloader.__index: can only be indexed by string\n");
2825 key = luaL_checkoption(L, 2, NULL, font_keys);
2826 switch (key) {
2827 case FK_table_version:
2828 lua_pushstring(L, LUA_OTF_VERSION);
2829 break;
2830 case FK_fontname:
2831 lua_pushstring(L, sf->fontname);
2832 break;
2833 case FK_fullname:
2834 lua_pushstring(L, sf->fullname);
2835 break;
2836 case FK_familyname:
2837 lua_pushstring(L, sf->familyname);
2838 break;
2839 case FK_weight:
2840 lua_pushstring(L, sf->weight);
2841 break;
2842 case FK_copyright:
2843 lua_pushstring(L, sf->copyright);
2844 break;
2845 case FK_filename:
2846 lua_pushstring(L, sf->filename);
2847 break;
2848 case FK_version:
2849 lua_pushstring(L, sf->version);
2850 break;
2851 case FK_italicangle:
2852 lua_pushnumber(L, sf->italicangle);
2853 break;
2854 case FK_upos:
2855 lua_pushnumber(L, sf->upos);
2856 break;
2857 case FK_uwidth:
2858 lua_pushnumber(L, sf->uwidth);
2859 break;
2860 case FK_ascent:
2861 lua_pushnumber(L, sf->ascent);
2862 break;
2863 case FK_descent:
2864 lua_pushnumber(L, sf->descent);
2865 break;
2866 case FK_uniqueid:
2867 lua_pushnumber(L, sf->uniqueid);
2868 break;
2869 case FK_glyphcnt:
2870 if (sf->glyphcnt > 0) {
2871 lua_pushnumber(L, sf->glyphmax - sf->glyphmin + 1);
2872 } else {
2873 lua_pushnumber(L, 0);
2875 break;
2876 case FK_glyphmax:
2877 lua_pushnumber(L, sf->glyphmax - 1);
2878 break;
2879 case FK_glyphmin:
2880 lua_pushnumber(L, sf->glyphmin);
2881 break;
2882 case FK_units_per_em:
2883 lua_pushnumber(L, sf->units_per_em);
2884 break;
2885 case FK_lookups:
2886 if (sf->possub != NULL) {
2887 lua_newtable(L);
2888 handle_generic_fpst(L, sf->possub);
2889 } else {
2890 lua_pushnil(L);
2892 break;
2893 case FK_glyphs:
2894 lua_newtable(L); /* the virtual glyph table */
2895 lua_pushstring(L, "__sf");
2896 lua_pushvalue(L, 1); /* that is our font */
2897 lua_rawset(L, -3);
2898 luaL_getmetatable(L, FONT_GLYPHS_METATABLE);
2899 lua_setmetatable(L, -2); /* assign the metatable */
2900 break;
2901 case FK_hasvmetrics:
2902 lua_pushnumber(L, sf->hasvmetrics);
2903 break;
2904 case FK_onlybitmaps:
2905 lua_pushnumber(L, sf->onlybitmaps);
2906 break;
2907 case FK_serifcheck:
2908 lua_pushnumber(L, sf->serifcheck);
2909 break;
2910 case FK_isserif:
2911 lua_pushnumber(L, sf->isserif);
2912 break;
2913 case FK_issans:
2914 lua_pushnumber(L, sf->issans);
2915 break;
2916 case FK_encodingchanged:
2917 lua_pushnumber(L, sf->encodingchanged);
2918 break;
2919 case FK_strokedfont:
2920 lua_pushnumber(L, sf->strokedfont);
2921 break;
2922 case FK_use_typo_metrics:
2923 lua_pushnumber(L, sf->use_typo_metrics);
2924 break;
2925 case FK_weight_width_slope_only:
2926 lua_pushnumber(L, sf->weight_width_slope_only);
2927 break;
2928 case FK_head_optimized_for_cleartype:
2929 lua_pushnumber(L, sf->head_optimized_for_cleartype);
2930 break;
2931 case FK_uni_interp:
2932 lua_pushstring(L, uni_interp_enum[(sf->uni_interp + 1)]);
2933 break;
2934 case FK_map:
2935 if (sf->map != NULL) {
2936 lua_newtable(L);
2937 handle_encmap(L, sf->map, notdef_loc(sf));
2938 } else {
2939 lua_pushnil(L);
2941 break;
2942 case FK_origname:
2943 lua_pushstring(L, sf->origname);
2944 break;
2945 case FK_private:
2946 if (sf->private != NULL) {
2947 lua_newtable(L);
2948 handle_psdict(L, sf->private);
2949 } else {
2950 lua_pushnil(L);
2952 break;
2953 case FK_xuid:
2954 lua_pushstring(L, sf->xuid);
2955 break;
2956 case FK_pfminfo:
2957 lua_createtable(L, 0, 40);
2958 handle_pfminfo(L, sf->pfminfo);
2959 break;
2960 case FK_names:
2961 if (sf->names != NULL) {
2962 lua_newtable(L);
2963 handle_ttflangname(L, sf->names);
2964 } else {
2965 lua_pushnil(L);
2967 break;
2968 case FK_cidinfo:
2969 lua_createtable(L, 0, 4);
2970 dump_stringfield(L, "registry", sf->cidregistry);
2971 dump_stringfield(L, "ordering", sf->ordering);
2972 dump_intfield(L, "version", sf->cidversion);
2973 dump_intfield(L, "supplement", sf->supplement);
2974 break;
2975 case FK_subfonts:
2976 if (sf->subfontcnt > 0) {
2977 lua_createtable(L, sf->subfontcnt, 0);
2978 for (k = 0; k < sf->subfontcnt; k++) {
2979 lua_ff_pushsubfont(L, sf->subfonts[k]);
2980 lua_rawseti(L, -2, (k + 1));
2982 } else {
2983 lua_pushnil(L);
2985 break;
2986 case FK_comments:
2987 lua_pushstring(L, sf->comments);
2988 break;
2989 case FK_fontlog:
2990 lua_pushstring(L, sf->fontlog);
2991 break;
2992 case FK_cvt_names:
2993 if (sf->cvt_names != NULL) {
2994 lua_newtable(L);
2995 for (k = 0; sf->cvt_names[k] != END_CVT_NAMES; ++k) {
2996 lua_pushstring(L, sf->cvt_names[k]);
2997 lua_rawseti(L, -2, (k + 1));
2999 } else {
3000 lua_pushnil(L);
3002 break;
3003 case FK_ttf_tables:
3004 if (sf->ttf_tables != NULL) {
3005 lua_newtable(L);
3006 handle_ttf_table(L, sf->ttf_tables);
3007 } else {
3008 lua_pushnil(L);
3010 break;
3011 case FK_ttf_tab_saved:
3012 if (sf->ttf_tab_saved != NULL) {
3013 lua_newtable(L);
3014 handle_ttf_table(L, sf->ttf_tab_saved);
3015 } else {
3016 lua_pushnil(L);
3018 break;
3019 case FK_texdata:
3020 if (sf->texdata.type != tex_unset) {
3021 lua_newtable(L);
3022 dump_enumfield(L, "type", sf->texdata.type, tex_type_enum);
3023 lua_newtable(L);
3024 for (k = 0; k < 22; k++) {
3025 lua_pushnumber(L, k);
3026 lua_pushnumber(L, sf->texdata.params[k]);
3027 lua_rawset(L, -3);
3029 lua_setfield(L, -2, "params");
3030 } else {
3031 lua_pushnil(L);
3033 break;
3034 case FK_anchor_classes:
3035 if (sf->anchor != NULL) {
3036 lua_newtable(L);
3037 handle_anchorclass(L, sf->anchor);
3038 } else {
3039 lua_pushnil(L);
3041 break;
3042 case FK_kerns:
3043 if (sf->kerns != NULL) {
3044 lua_newtable(L);
3045 handle_kernclass(L, sf->kerns, NULL);
3046 } else {
3047 lua_pushnil(L);
3049 break;
3050 case FK_vkerns:
3051 if (sf->vkerns != NULL) {
3052 lua_newtable(L);
3053 handle_kernclass(L, sf->vkerns, NULL);
3054 } else {
3055 lua_pushnil(L);
3057 break;
3058 case FK_gsub:
3059 if (sf->gsub_lookups != NULL) {
3060 lua_newtable(L);
3061 handle_lookup(L, sf->gsub_lookups, sf);
3062 } else {
3063 lua_pushnil(L);
3065 break;
3066 case FK_gpos:
3067 if (sf->gpos_lookups != NULL) {
3068 lua_newtable(L);
3069 handle_lookup(L, sf->gpos_lookups, sf);
3070 } else {
3071 lua_pushnil(L);
3073 break;
3074 case FK_mm:
3075 if (sf->mm != NULL) {
3076 lua_newtable(L);
3077 handle_mmset(L, sf->mm);
3078 } else {
3079 lua_pushnil(L);
3081 break;
3082 case FK_chosenname:
3083 lua_pushstring(L, sf->chosenname);
3084 break;
3085 case FK_macstyle:
3086 lua_pushnumber(L, sf->macstyle);
3087 break;
3088 case FK_fondname:
3089 lua_pushstring(L, sf->fondname);
3090 break;
3091 case FK_design_size:
3092 lua_pushnumber(L, sf->design_size);
3093 break;
3094 case FK_fontstyle_id:
3095 lua_pushnumber(L, sf->fontstyle_id);
3096 break;
3097 case FK_fontstyle_name:
3098 if (sf->fontstyle_name != NULL) {
3099 lua_newtable(L);
3100 handle_otfname(L, sf->fontstyle_name);
3101 } else {
3102 lua_pushnil(L);
3104 break;
3105 case FK_design_range_bottom:
3106 lua_pushnumber(L, sf->design_range_bottom);
3107 break;
3108 case FK_design_range_top:
3109 lua_pushnumber(L, sf->design_range_top);
3110 break;
3111 case FK_strokewidth:
3112 lua_pushnumber(L, sf->strokewidth);
3113 break;
3114 case FK_mark_classes:
3115 if (sf->mark_class_cnt > 0) {
3116 lua_newtable(L);
3117 for (k = 0; k < sf->mark_class_cnt; k++) {
3118 if (sf->mark_class_names[k] != NULL) {
3119 lua_pushstring(L, sf->mark_class_names[k]);
3120 lua_pushstring(L, sf->mark_classes[k]);
3121 lua_rawset(L, -3);
3124 } else {
3125 lua_pushnil(L);
3127 break;
3128 case FK_creationtime:
3129 lua_pushnumber(L, sf->creationtime);
3130 break;
3131 case FK_modificationtime:
3132 lua_pushnumber(L, sf->modificationtime);
3133 break;
3134 case FK_os2_version:
3135 lua_pushnumber(L, sf->os2_version);
3136 break;
3137 case FK_sfd_version:
3138 lua_pushnumber(L, sf->sfd_version);
3139 break;
3140 case FK_math:
3141 if (sf->MATH != NULL) {
3142 lua_newtable(L);
3143 handle_MATH(L, sf->MATH);
3144 } else {
3145 lua_pushnil(L);
3147 break;
3148 case FK_validation_state:
3149 if (sf->loadvalidation_state != 0) {
3150 int val, st;
3151 lua_newtable(L);
3152 val = 1;
3153 st = sf->loadvalidation_state;
3154 if (st & lvs_bad_ps_fontname) {
3155 lua_pushliteral(L, "bad_ps_fontname");
3156 lua_rawseti(L, -2, val++);
3158 if (st & lvs_bad_glyph_table) {
3159 lua_pushliteral(L, "bad_glyph_table");
3160 lua_rawseti(L, -2, val++);
3162 if (st & lvs_bad_cff_table) {
3163 lua_pushliteral(L, "bad_cff_table");
3164 lua_rawseti(L, -2, val++);
3166 if (st & lvs_bad_metrics_table) {
3167 lua_pushliteral(L, "bad_metrics_table");
3168 lua_rawseti(L, -2, val++);
3170 if (st & lvs_bad_cmap_table) {
3171 lua_pushliteral(L, "bad_cmap_table");
3172 lua_rawseti(L, -2, val++);
3174 if (st & lvs_bad_bitmaps_table) {
3175 lua_pushliteral(L, "bad_bitmaps_table");
3176 lua_rawseti(L, -2, val++);
3178 if (st & lvs_bad_gx_table) {
3179 lua_pushliteral(L, "bad_gx_table");
3180 lua_rawseti(L, -2, val++);
3182 if (st & lvs_bad_ot_table) {
3183 lua_pushliteral(L, "bad_ot_table");
3184 lua_rawseti(L, -2, val++);
3186 if (st & lvs_bad_os2_version) {
3187 lua_pushliteral(L, "bad_os2_version");
3188 lua_rawseti(L, -2, val++);
3190 if (st & lvs_bad_sfnt_header) {
3191 lua_pushliteral(L, "bad_sfnt_header");
3192 lua_rawseti(L, -2, val++);
3194 } else {
3195 lua_pushnil(L);
3197 break;
3198 case FK_horiz_base:
3199 if (sf->horiz_base != NULL) {
3200 lua_newtable(L);
3201 handle_base(L, sf->horiz_base);
3202 } else {
3203 lua_pushnil(L);
3205 break;
3206 case FK_vert_base:
3207 if (sf->vert_base != NULL) {
3208 lua_newtable(L);
3209 handle_base(L, sf->vert_base);
3210 } else {
3211 lua_pushnil(L);
3213 break;
3214 case FK_extrema_bound:
3215 lua_pushnumber(L, sf->extrema_bound);
3216 break;
3217 default: /* can't actually happen, |luaL_checkoption| raises an error instead */
3218 lua_pushnil(L);
3219 break;
3221 return 1;
3225 static int ff_info(lua_State * L)
3227 SplineFont *sf;
3228 FILE *l;
3229 int i;
3230 const char *fontname;
3231 char *fontnamecopy;
3232 int openflags = 1;
3233 fontname = luaL_checkstring(L, 1);
3234 if (!strlen(fontname)) {
3235 lua_pushnil(L);
3236 lua_pushfstring(L, "font loading failed: empty string given\n",
3237 fontname);
3238 return 2;
3240 /* test fontname for existance */
3241 if ((l = fopen(fontname, "r"))) {
3242 recorder_record_input(fontname);
3243 fclose(l);
3244 } else {
3245 lua_pushnil(L);
3246 lua_pushfstring(L, "font loading failed for %s (read error)\n",
3247 fontname);
3248 return 2;
3251 gww_error_count = 0;
3252 fontnamecopy = xstrdup(fontname);
3253 sf = ReadSplineFontInfo(fontnamecopy, openflags);
3254 free(fontnamecopy);
3255 if (gww_error_count > 0)
3256 gwwv_errors_free();
3258 if (sf == NULL) {
3259 lua_pushnil(L);
3260 lua_pushfstring(L, "font loading failed for %s\n", fontname);
3261 return 2;
3262 } else {
3263 if (sf->next != NULL) {
3264 SplineFont *sf_next;
3265 i = 1;
3266 lua_newtable(L);
3267 while (sf) {
3268 do_ff_info(L, sf);
3269 lua_rawseti(L, -2, i);
3270 i++;
3271 sf_next = sf->next;
3272 EncMapFree(sf->map);
3273 SplineFontFree(sf);
3274 sf = sf_next;
3276 } else {
3277 do_ff_info(L, sf);
3278 EncMapFree(sf->map);
3279 SplineFontFree(sf);
3282 return 1;
3285 static void ff_do_cff(SplineFont * sf, char *filename, unsigned char **buf,
3286 int *bufsiz)
3288 FILE *f;
3289 int32 *bsizes = NULL;
3290 int flags = ps_flag_nocffsugar + ps_flag_nohints;
3291 EncMap *map;
3293 map = EncMap1to1(sf->glyphcnt);
3295 if (WriteTTFFont
3296 (filename, sf, ff_cff, bsizes, bf_none, flags, map, ly_fore)) {
3297 /* success */
3298 f = fopen(filename, "rb");
3299 recorder_record_input(filename);
3300 readbinfile(f, buf, bufsiz);
3301 /*fprintf(stdout,"\n%s => CFF, size: %d\n", sf->filename, *bufsiz); */
3302 fclose(f);
3303 return;
3305 /* errors */
3306 fprintf(stdout, "\n%s => CFF, failed\n", sf->filename);
3310 /* exported for writecff.c */
3312 int ff_createcff(char *file, unsigned char **buf, int *bufsiz)
3314 SplineFont *sf;
3315 int k;
3316 char s[] = "tempfile.cff";
3317 int openflags = 1;
3318 int notdefpos = 0;
3319 sf = ReadSplineFont(file, openflags);
3320 if (sf) {
3321 /* this is not the best way. nicer to have no temp file at all */
3322 ff_do_cff(sf, s, buf, bufsiz);
3323 for (k = 0; k < sf->glyphcnt; k++) {
3324 if (sf->glyphs[k] && strcmp(sf->glyphs[k]->name, ".notdef") == 0) {
3325 notdefpos = k;
3326 break;
3329 remove(s);
3330 EncMapFree(sf->map);
3331 SplineFontFree(sf);
3333 return notdefpos;
3336 int ff_get_ttc_index(char *ffname, char *psname)
3338 SplineFont *sf;
3339 int i = 0;
3340 int openflags = 1;
3341 int index = -1;
3343 sf = ReadSplineFontInfo((char *) ffname, openflags);
3344 if (sf == NULL) {
3345 perror("font loading failed unexpectedly\n");
3346 exit(EXIT_FAILURE);
3348 while (sf != NULL) {
3349 if (strcmp(sf->fontname, psname) == 0) {
3350 index = i;
3352 i++;
3353 sf = sf->next;
3355 if (index>=0)
3356 return (i-index-1);
3357 return -1;
3360 static struct luaL_Reg fllib[] = {
3361 {"open", ff_open},
3362 {"info", ff_info},
3363 {"close", ff_close},
3364 {"fields", ff_fields},
3365 {"apply_afmfile", ff_apply_afmfile},
3366 {"apply_featurefile", ff_apply_featurefile},
3367 {"to_table", ff_make_table},
3368 {NULL, NULL}
3371 static const struct luaL_Reg fflib_m[] = {
3372 {"__gc", ff_close}, /* doesnt work yet! */
3373 {"__index", ff_index},
3374 {NULL, NULL} /* sentinel */
3377 int luaopen_ff(lua_State * L)
3379 static char coord_sep_string[] = ",";
3380 static char SaveTablesPref_string[] = "VORG,JSTF,acnt,bsln,fdsc,fmtx,hsty,just,trak,Zapf,LINO";
3381 InitSimpleStuff();
3382 setlocale(LC_ALL, "C"); /* undo whatever InitSimpleStuff has caused */
3383 coord_sep = coord_sep_string;
3384 FF_SetUiInterface(&luaui_interface);
3385 default_encoding = FindOrMakeEncoding("ISO8859-1");
3386 SaveTablesPref = SaveTablesPref_string;
3387 luaL_newmetatable(L, FONT_METATABLE);
3388 luaL_register(L, NULL, fflib_m);
3390 /* virtual subfont table */
3391 luaL_newmetatable(L, FONT_SUBFONT_METATABLE);
3392 lua_pushstring(L, "__index");
3393 lua_pushcfunction(L, ff_index);
3394 lua_rawset(L, -3);
3395 lua_pop(L, 1);
3396 /* virtual glyphs table */
3397 luaL_newmetatable(L, FONT_GLYPHS_METATABLE);
3398 lua_pushstring(L, "__index");
3399 lua_pushcfunction(L, ff_glyphs_index);
3400 lua_rawset(L, -3);
3401 lua_pop(L, 1);
3402 /* virtual glyph table */
3403 luaL_newmetatable(L, FONT_GLYPH_METATABLE);
3404 lua_pushstring(L, "__index");
3405 lua_pushcfunction(L, ff_glyph_index);
3406 lua_rawset(L, -3);
3407 lua_pop(L, 1);
3410 luaL_openlib(L, "fontloader", fllib, 0);
3412 return 1;