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