summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/luafontloader/src/luafflib.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/luafontloader/src/luafflib.c')
-rw-r--r--Build/source/texk/web2c/luatexdir/luafontloader/src/luafflib.c2379
1 files changed, 2379 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/luafontloader/src/luafflib.c b/Build/source/texk/web2c/luatexdir/luafontloader/src/luafflib.c
new file mode 100644
index 00000000000..bc344fdd416
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/luafontloader/src/luafflib.c
@@ -0,0 +1,2379 @@
+/**
+* $Id $
+* @desc Support interface for fontforge 20070607
+* @version 1.0
+* @author Taco Hoekwater
+*/
+
+#include <stdio.h>
+#include <lua.h>
+#include <lauxlib.h>
+#include <locale.h>
+
+#include "pfaedit.h"
+#include "ustring.h"
+
+extern char **gww_errors;
+extern int gww_error_count;
+extern void gwwv_errors_free (void);
+extern struct ui_interface luaui_interface;
+
+extern int readbinfile(FILE *f, unsigned char **b, int *s);
+
+#define FONT_METATABLE "fontloader.splinefont"
+
+#define LUA_OTF_VERSION "0.3"
+
+static char *possub_type_enum[] = {
+ "null", "position", "pair", "substitution",
+ "alternate", "multiple", "ligature", "lcaret",
+ "kerning", "vkerning", "anchors", "contextpos",
+ "contextsub", "chainpos", "chainsub","reversesub",
+ "max", "kernback", "vkernback", NULL };
+
+#define LAST_POSSUB_TYPE_ENUM 18
+
+#define eight_nulls() NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+
+static char *asm_type_enum[] = {
+ "indic", "context", "lig", NULL, "simple", "insert", NULL, NULL,
+ eight_nulls(),
+ NULL, "kern" };
+
+static char *otf_lookup_type_enum[] = {
+ "gsub_start", "gsub_single", "gsub_multiple", "gsub_alternate",
+ "gsub_ligature", "gsub_context", "gsub_contextchain", NULL,
+ "gsub_reversecontextchain", NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*0x00F */
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(), NULL, NULL, NULL, NULL, NULL, "morx_indic", "morx_context", "morx_insert", /* 0x0FF*/
+ "gpos_start", "gpos_single", "gpos_pair", "gpos_cursive",
+ "gpos_mark2base", "gpos_mark2ligature", "gpos_mark2mark", "gpos_context",
+ "gpos_contextchain", NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 0x10F */
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(),eight_nulls(),
+ eight_nulls(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, "kern_statemachine", /* 0x1FF*/
+};
+
+
+static char *anchor_type_enum[] = {
+ "mark", "basechar", "baselig", "basemark", "centry", "cexit", "max", NULL };
+
+#define MAX_ANCHOR_TYPE 7
+
+static char *anchorclass_type_enum[] = {
+ "mark", "mkmk", "curs", "mklg", NULL };
+
+static char *glyph_class_enum[] = {
+ "automatic", "none" ,"base", "ligature","mark", "component", NULL };
+
+static char *ttfnames_enum[ttf_namemax] = {
+ "copyright", "family", "subfamily", "uniqueid",
+ "fullname", "version", "postscriptname", "trademark",
+ "manufacturer", "designer", "descriptor", "venderurl",
+ "designerurl", "license", "licenseurl", "idontknow",
+ "preffamilyname", "prefmodifiers", "compatfull", "sampletext",
+ "cidfindfontname", "wwsfamily", "wwssubfamily" };
+
+static char *fpossub_format_enum [] = {
+ "glyphs", "class","coverage","reversecoverage" , NULL};
+
+static char *tex_type_enum[4] = { "unset", "text", "math", "mathext"};
+
+/* has an offset of 1, ui_none = 0. */
+static char *uni_interp_enum[9] = {
+ "unset", "none", "adobe", "greek", "japanese",
+ "trad_chinese", "simp_chinese", "korean", "ams" };
+
+#define check_isfont(L,b) (SplineFont **)luaL_checkudata(L,b,FONT_METATABLE)
+
+void handle_generic_pst (lua_State *L, struct generic_pst *pst); /* forward */
+void handle_generic_fpst (lua_State *L, struct generic_fpst *fpst); /* forward */
+void handle_generic_asm (lua_State *L, struct generic_asm *sm) ;
+void handle_kernclass (lua_State *L, struct kernclass *kerns);
+void handle_anchorclass (lua_State *L, struct anchorclass *anchor);
+void handle_splinefont(lua_State *L, struct splinefont *sf) ;
+
+
+void
+lua_ff_pushfont(lua_State *L, SplineFont *sf) {
+ SplineFont **a;
+ if (sf==NULL) {
+ lua_pushnil(L);
+ } else {
+ a = lua_newuserdata(L,sizeof(SplineFont *));
+ *a = sf;
+ luaL_getmetatable(L,FONT_METATABLE);
+ lua_setmetatable(L,-2);
+ }
+ return;
+}
+
+
+static int
+ff_open (lua_State *L) {
+ SplineFont *sf;
+ const char *fontname;
+ FILE *l;
+ char s[511];
+ size_t len;
+ int args,i ;
+ int openflags = 1;
+ fontname = luaL_checkstring(L,1);
+ /* test fontname for existance */
+ if ((l = fopen(fontname,"r"))) {
+ fclose(l);
+ } else {
+ lua_pushfstring(L,"font loading failed for %s (read error)\n", fontname);
+ lua_error(L);
+ }
+ args = lua_gettop(L);
+ if (args>=2 && lua_isstring(L,2)) {
+ if (*(fontname+strlen(fontname))!=')') {
+ /* possibly fails for embedded parens in the font name */
+ snprintf(s,511,"%s(%s)", fontname, lua_tolstring(L,2,&len));
+ if (len==0) {
+ snprintf(s,511,"%s", fontname);
+ }
+ }
+ } else {
+ snprintf(s,511,"%s", fontname);
+ }
+ if (strlen(s)>0) {
+ gww_error_count=0;
+ sf = ReadSplineFont((char *)s,openflags);
+ if (sf==NULL) {
+ lua_pushfstring(L,"font loading failed for %s\n", s);
+ if (gww_error_count>0) {
+ for (i=0;i<gww_error_count;i++) {
+ lua_pushstring(L,gww_errors[i]);
+ lua_concat(L,2);
+ }
+ gwwv_errors_free();
+ }
+ lua_error(L);
+ } else {
+ FVAppend(_FontViewCreate(sf));
+ lua_ff_pushfont(L,sf);
+ if (gww_error_count>0) {
+ lua_newtable(L);
+ for (i=0;i<gww_error_count;i++) {
+ lua_pushstring(L,gww_errors[i]);
+ lua_rawseti(L,-2,(i+1));
+ }
+ gwwv_errors_free();
+ } else {
+ lua_pushnil(L);
+ }
+ }
+ } else {
+ lua_pushfstring(L,"font loading failed: empty string given\n", fontname);
+ lua_error(L);
+ }
+ return 2;
+}
+
+
+static int
+ff_close (lua_State *L) {
+ SplineFont **sf;
+ /*fputs("ff_close called",stderr);*/
+ sf = check_isfont(L,1);
+ if (*sf!=NULL) {
+ SplineFontFree(*sf);
+ *sf = NULL;
+ }
+ return 0;
+}
+
+static int
+ff_apply_featurefile (lua_State *L) {
+ SplineFont **sf;
+ char *fname;
+ sf = check_isfont(L,1);
+ fname = (char *)luaL_checkstring(L,2);
+ SFApplyFeatureFilename(*sf,fname);
+ return 0;
+}
+
+static int
+ff_apply_afmfile (lua_State *L) {
+ SplineFont **sf;
+ char *fname;
+ sf = check_isfont(L,1);
+ fname = (char *)luaL_checkstring(L,2);
+ CheckAfmOfPostscript(*sf,fname,(*sf)->map);
+
+ return 0;
+}
+
+
+
+static void
+dump_intfield (lua_State *L, char *name, long int field) {
+ lua_checkstack(L,2);
+ lua_pushstring(L,name);
+ lua_pushnumber(L,field);
+ lua_rawset(L,-3);
+}
+
+static void
+dump_realfield (lua_State *L, char *name, real field) {
+ lua_checkstack(L,2);
+ lua_pushstring(L,name);
+ lua_pushnumber(L,field);
+ lua_rawset(L,-3);
+}
+
+
+#define dump_cond_intfield(a,b,c) if ((c)!=0) { dump_intfield ((a),(b),(c)); }
+
+
+static void
+dump_stringfield (lua_State *L, char *name, char *field) {
+ lua_checkstack(L,2);
+ lua_pushstring(L,name);
+ lua_pushstring(L,field);
+ lua_rawset(L,-3);
+}
+
+static void
+dump_char_ref (lua_State *L, struct splinechar *spchar) {
+ lua_checkstack(L,2);
+ lua_pushstring(L,"char");
+ lua_pushstring(L,spchar->name);
+ lua_rawset(L,-3);
+}
+
+
+static void
+dump_lstringfield (lua_State *L, char *name, char *field, int len) {
+ lua_checkstack(L,2);
+ lua_pushstring(L,name);
+ lua_pushlstring(L,field,len);
+ lua_rawset(L,-3);
+}
+
+static void
+dump_enumfield (lua_State *L, char *name, int fid, char **fields) {
+ lua_checkstack(L,2);
+ lua_pushstring(L,name);
+ lua_pushstring(L,fields[fid]);
+ lua_rawset(L,-3);
+}
+
+static void
+dump_floatfield (lua_State *L, char *name, double field) {
+ lua_checkstack(L,2);
+ lua_pushstring(L,name);
+ lua_pushnumber(L,field);
+ lua_rawset(L,-3);
+}
+
+static char tag_string [5] = {0};
+
+static char *make_tag_string (unsigned int field) {
+ tag_string[0] = (field&0xFF000000) >> 24;
+ tag_string[1] = (field&0x00FF0000) >> 16;
+ tag_string[2] = (field&0x0000FF00) >> 8;
+ tag_string[3] = (field&0x000000FF);
+ return (char *)tag_string;
+}
+
+static char featbuf[32] = {0};
+
+static char *make_mactag_string (unsigned int field) {
+ sprintf( featbuf, "<%d,%d>", field>>16, field&0xffff );
+ return (char *)featbuf;
+}
+
+
+static void
+dump_tag (lua_State *L, char *name, unsigned int field) {
+ lua_checkstack(L,2);
+ lua_pushstring(L,name);
+ lua_pushlstring(L,make_tag_string(field),4);
+ lua_rawset(L,-3);
+}
+
+static void
+dump_mactag (lua_State *L, char *name, unsigned int field) {
+ lua_checkstack(L,2);
+ lua_pushstring(L,name);
+ lua_pushstring(L,make_mactag_string(field));
+ lua_rawset(L,-3);
+}
+
+void
+dump_subtable_name (lua_State *L, char *name, struct lookup_subtable *s) {
+ /* this is likely a backref */
+ if (s==NULL)
+ return;
+ lua_checkstack(L,2);
+ if (s->next == NULL) {
+ dump_stringfield(L,name,s->subtable_name);
+ } else {
+ /* can this really happen ? */
+ int i = 0;
+ lua_newtable(L);
+ while (s!=NULL) {
+ lua_pushstring(L, s->subtable_name);
+ lua_rawseti(L, -2, ++i);
+ s = s->next;
+ }
+ lua_setfield(L, -2, name);
+ }
+}
+
+
+
+#define NESTED_TABLE(a,b,c) { \
+ int k = 1; \
+ next = b; \
+ while (next != NULL) { \
+ lua_checkstack(L,2); \
+ lua_pushnumber(L,k); k++; \
+ lua_createtable(L,0,c); \
+ a(L, next); \
+ lua_rawset(L,-3); \
+ next = next->next; \
+ } }
+
+void
+do_handle_scriptlanglist (lua_State *L, struct scriptlanglist *sl) {
+ int k;
+ dump_tag(L,"script", sl->script);
+
+ lua_checkstack(L,3);
+ lua_newtable(L);
+ for (k=0;k<MAX_LANG;k++) {
+ if (sl->langs[k] != 0) {
+ lua_pushnumber(L,(k+1));
+ lua_pushstring(L,make_tag_string(sl->langs[k]));
+ lua_rawset(L,-3);
+ }
+ }
+
+ if (sl->lang_cnt>=MAX_LANG) {
+ for (k=MAX_LANG;k<sl->lang_cnt;k++) {
+ lua_pushnumber(L,(k+1));
+ lua_pushstring(L,make_tag_string(sl->morelangs[k-MAX_LANG]));
+ lua_rawset(L,-3);
+ }
+ }
+ lua_setfield(L,-2,"langs");
+}
+
+void
+handle_scriptlanglist (lua_State *L, struct scriptlanglist *sll) {
+ struct scriptlanglist *next;
+ NESTED_TABLE(do_handle_scriptlanglist,sll,4);
+}
+
+void
+do_handle_featurescriptlanglist (lua_State *L, struct featurescriptlanglist *features) {
+ if (features->ismac) {
+ dump_mactag (L,"tag",features->featuretag);
+ } else {
+ dump_tag (L,"tag",features->featuretag);
+ }
+ lua_newtable(L);
+ handle_scriptlanglist(L, features->scripts);
+ lua_setfield(L,-2,"scripts");
+ dump_cond_intfield (L,"ismac",features->ismac);
+}
+
+void
+handle_featurescriptlanglist (lua_State *L, struct featurescriptlanglist *features) {
+ struct featurescriptlanglist *next;
+ NESTED_TABLE(do_handle_featurescriptlanglist,features,3);
+}
+
+void
+do_handle_lookup_subtable (lua_State *L, struct lookup_subtable *subtable) {
+
+ dump_stringfield(L,"name", subtable->subtable_name);
+ dump_stringfield(L,"suffix", subtable->suffix);
+
+ /* struct otlookup *lookup; */ /* this is the parent */
+
+ /* dump_intfield (L,"unused", subtable->unused); */
+ /* The next one is true if there is no fpst, false otherwise */
+ /*
+ dump_intfield (L,"per_glyph_pst_or_kern",subtable->per_glyph_pst_or_kern);
+ */
+ dump_cond_intfield (L,"anchor_classes", subtable->anchor_classes);
+ dump_cond_intfield (L,"vertical_kerning", subtable->vertical_kerning);
+
+ if (subtable->kc != NULL) {
+ lua_newtable(L);
+ handle_kernclass(L, subtable->kc);
+ lua_setfield(L,-2, "kernclass");
+ }
+
+#if 0
+ if (subtable->fpst != NULL) {
+ /* lua_newtable(L); */
+ handle_generic_fpst(L, subtable->fpst);
+ /* lua_setfield(L,-2, "fpst"); */
+ }
+#endif
+
+ if (subtable->sm != NULL) {
+ lua_newtable(L);
+ handle_generic_asm(L, subtable->sm);
+ lua_setfield(L,-2, "sm");
+ }
+ /* int subtable_offset; */ /* used by OTF file generation */
+ /* int32 *extra_subtables; */ /* used by OTF file generation */
+}
+
+void
+handle_lookup_subtable (lua_State *L, struct lookup_subtable *subtable) {
+ struct lookup_subtable *next;
+ NESTED_TABLE(do_handle_lookup_subtable,subtable,2);
+}
+
+void
+do_handle_lookup (lua_State *L, struct otlookup *lookup ) {
+
+ dump_enumfield (L,"type", lookup->lookup_type, otf_lookup_type_enum);
+
+ lua_newtable(L);
+ if (lookup->lookup_flags & pst_r2l) {
+ lua_pushstring(L,"r2l"); lua_pushboolean(L,1); lua_rawset(L,-3);
+ }
+ if (lookup->lookup_flags & pst_ignorebaseglyphs) {
+ lua_pushstring(L,"ignorebaseglyphs"); lua_pushboolean(L,1); lua_rawset(L,-3);
+ }
+ if (lookup->lookup_flags & pst_ignoreligatures) {
+ lua_pushstring(L,"ignoreligatures"); lua_pushboolean(L,1); lua_rawset(L,-3);
+ }
+ if (lookup->lookup_flags & pst_ignorecombiningmarks) {
+ lua_pushstring(L,"ignorecombiningmarks"); lua_pushboolean(L,1); lua_rawset(L,-3);
+ }
+ lua_setfield(L,-2,"flags");
+
+
+ dump_stringfield (L,"name", lookup->lookup_name);
+
+ if (lookup->features != NULL) {
+ lua_newtable(L);
+ handle_featurescriptlanglist(L,lookup->features);
+ lua_setfield(L,-2,"features");
+ }
+
+ if (lookup->subtables != NULL) {
+ lua_newtable(L);
+ handle_lookup_subtable(L,lookup->subtables);
+ lua_setfield(L,-2,"subtables");
+ }
+
+ /* dump_intfield (L,"unused", lookup->unused); */
+ /* dump_intfield (L,"empty", lookup->empty); */
+ /* dump_intfield (L,"store_in_afm", lookup->store_in_afm); */
+ /* dump_intfield (L,"needs_extension", lookup->needs_extension); */
+ /* dump_intfield (L,"temporary_kern", lookup->temporary_kern); */
+ /* dump_intfield (L,"def_lang_checked", lookup->def_lang_checked); */
+ /* dump_intfield (L,"def_lang_found", lookup->def_lang_found); */
+ /* dump_intfield (L,"ticked", lookup->ticked); */
+ /* dump_intfield (L,"subcnt", lookup->subcnt); */
+ /* dump_intfield (L,"lookup_index", lookup->lookup_index); */ /* identical to array index */
+ /* dump_intfield (L,"lookup_offset", lookup->lookup_offset); */
+ /* dump_intfield (L,"lookup_length", lookup->lookup_length); */
+ /* dump_stringfield(L,"tempname", lookup->tempname); */
+
+}
+
+void
+handle_lookup (lua_State *L, struct otlookup *lookup ) {
+ struct otlookup *next;
+ NESTED_TABLE(do_handle_lookup,lookup,18); /* 18 is a guess */
+}
+
+void
+do_handle_kernpair (lua_State *L, struct kernpair *kp) {
+
+ if (kp->sc != NULL)
+ dump_char_ref(L, kp->sc);
+ dump_intfield(L,"off", kp->off);
+ /* uint16 kcid; */ /* temporary value */
+ dump_subtable_name(L, "lookup", kp->subtable);
+}
+
+void
+handle_kernpair (lua_State *L, struct kernpair *kp) {
+ struct kernpair *next;
+ NESTED_TABLE(do_handle_kernpair,kp,4);
+}
+
+void
+handle_splinecharlist (lua_State *L, struct splinecharlist *scl) {
+
+ struct splinecharlist *next = scl;
+ int k = 1;
+ lua_checkstack(L,10);
+ while( next != NULL) {
+ if (next->sc != NULL) {
+ lua_pushnumber(L,k); k++;
+ lua_pushstring(L,next->sc->name);
+ lua_rawset(L,-3);
+ }
+ next = next->next;
+ }
+}
+
+
+
+/* vs is the "variation selector" a unicode codepoint which modifieds */
+/* the code point before it. If vs is -1 then unienc is just an */
+/* alternate encoding (greek Alpha and latin A), but if vs is one */
+/* of unicode's variation selectors then this glyph is somehow a */
+/* variant shape. The specifics depend on the selector and script */
+/* fid is currently unused, but may, someday, be used to do ttcs */
+/* NOTE: GlyphInfo displays vs==-1 as vs==0, and fixes things up */
+void
+handle_altuni (lua_State *L, struct altuni *au) {
+ struct altuni *next = au;
+ int k = 1;
+ lua_checkstack(L,3);
+ while( next != NULL) {
+ lua_newtable(L);
+ dump_intfield(L, "unicode", next->unienc);
+ if (next->vs != -1)
+ dump_intfield(L, "variant", next->vs);
+ /* dump_intfield(L, "fid", next->fid); */
+ lua_rawseti(L, -2, k++);
+ next = next->next;
+ }
+}
+
+
+
+#define interesting_vr(a) (((a)->xoff!=0) || ((a)->yoff!=0) || ((a)->h_adv_off!=0) || ((a)->v_adv_off!=0))
+
+void handle_vr (lua_State *L, struct vr *pos) {
+
+ dump_cond_intfield(L,"x", pos->xoff);
+ dump_cond_intfield(L,"y", pos->yoff);
+ dump_cond_intfield(L,"h", pos->h_adv_off);
+ dump_cond_intfield(L,"v", pos->v_adv_off);
+
+}
+
+void
+do_handle_generic_pst (lua_State *L, struct generic_pst *pst) {
+ int k;
+ if (pst->type>LAST_POSSUB_TYPE_ENUM) {
+ dump_tag(L,"type", pst->type);
+ } else {
+ dump_enumfield(L,"type", pst->type, possub_type_enum);
+ }
+ /* unsigned int ticked: 1;*/
+ /* unsigned int temporary: 1;*/ /* Used in afm ligature closure */
+ /* struct lookup_subtable *subtable; */ /* handled by caller */
+
+ lua_checkstack(L,4);
+ lua_pushstring(L,"specification");
+ lua_createtable(L,0,4);
+ if (pst->type == pst_position) {
+ handle_vr (L, &pst->u.pos);
+ } else if (pst->type == pst_pair) {
+ dump_stringfield(L,"paired",pst->u.pair.paired);
+ if (pst->u.pair.vr != NULL) {
+ lua_pushstring(L,"offsets");
+ lua_createtable(L,2,0);
+ if (interesting_vr(pst->u.pair.vr)) {
+ lua_createtable(L,0,4);
+ handle_vr (L, pst->u.pair.vr);
+ lua_rawseti(L,-2,1);
+ }
+ if (interesting_vr(pst->u.pair.vr+1)) {
+ lua_createtable(L,0,4);
+ handle_vr (L, pst->u.pair.vr+1);
+ lua_rawseti(L,-2,2);
+ }
+ lua_rawset(L,-3);
+ }
+ } else if (pst->type == pst_substitution) {
+ dump_stringfield(L,"variant",pst->u.subs.variant);
+ } else if (pst->type == pst_alternate) {
+ dump_stringfield(L,"components",pst->u.mult.components);
+ } else if (pst->type == pst_multiple) {
+ dump_stringfield(L,"components",pst->u.alt.components);
+ } else if (pst->type == pst_ligature) {
+ dump_stringfield(L,"components",pst->u.lig.components);
+ if (pst->u.lig.lig != NULL) {
+ dump_char_ref(L,pst->u.lig.lig);
+ }
+ } else if (pst->type == pst_lcaret) {
+ for (k=0;k<pst->u.lcaret.cnt;k++) {
+ lua_pushnumber(L,(k+1));
+ lua_pushnumber(L,pst->u.lcaret.carets[k]);
+ lua_rawset(L,-3);
+ }
+ }
+ lua_rawset(L,-3);
+}
+
+
+void
+handle_generic_pst (lua_State *L, struct generic_pst *pst) {
+ struct generic_pst *next;
+ int k;
+ int l = 1;
+ next = pst;
+ /* most likely everything arrives in proper order. But to prevent
+ * surprises, better do this is the proper way
+ */
+ while (next != NULL) {
+ if (next->subtable !=NULL &&
+ next->subtable->subtable_name !=NULL) {
+ lua_checkstack(L,3); /* just in case */
+ lua_getfield(L,-1,next->subtable->subtable_name);
+ if (!lua_istable(L,-1)) {
+ lua_pop(L,1);
+ lua_newtable(L);
+ lua_setfield(L,-2,next->subtable->subtable_name);
+ lua_getfield(L,-1,next->subtable->subtable_name);
+ }
+ k = lua_objlen(L,-1) + 1;
+ lua_pushnumber(L,k);
+ lua_createtable(L,0,4);
+ do_handle_generic_pst(L, next);
+ lua_rawset(L,-3);
+ next = next->next;
+ lua_pop(L,1); /* pop the subtable */
+ } else {
+ /* Found a pst without subtable, or without subtable name */
+ lua_pushnumber(L,l); l++;
+ lua_createtable(L,0,4);
+ do_handle_generic_pst(L, next);
+ lua_rawset(L,-3);
+ next = next->next;
+ }
+ }
+}
+
+void
+do_handle_liglist (lua_State *L, struct liglist *ligofme) {
+ lua_checkstack(L,2);
+ if(ligofme->lig != NULL) {
+ lua_createtable(L,0,6);
+ handle_generic_pst (L,ligofme->lig);
+ lua_setfield(L,-2,"lig");
+ }
+ dump_char_ref(L,ligofme->first);
+ if (ligofme->components != NULL) {
+ lua_newtable(L);
+ handle_splinecharlist (L,ligofme->components);
+ lua_setfield(L,-2,"components");
+ }
+ dump_intfield(L,"ccnt",ligofme->ccnt);
+}
+
+void
+handle_liglist (lua_State *L, struct liglist *ligofme) {
+ struct liglist *next;
+ NESTED_TABLE(do_handle_liglist,ligofme,3);
+}
+
+void
+do_handle_anchorpoint (lua_State *L, struct anchorpoint *anchor) {
+
+ if (anchor->anchor==NULL) {
+ return;
+ }
+ if (anchor->type>=0 && anchor->type <= MAX_ANCHOR_TYPE ) {
+ lua_pushstring(L,anchor_type_enum[anchor->type]);
+ } else {
+ lua_pushstring(L,"Anchorpoint has an unknown type!");
+ lua_error(L);
+ }
+ /* unsigned int selected: 1; */
+ /* unsigned int ticked: 1; */
+
+ lua_rawget(L,-2);
+ if (!lua_istable(L,-1)) {
+ /* create the table first */
+ lua_pop(L,1);
+ lua_pushstring(L,anchor_type_enum[anchor->type]);
+ lua_pushvalue(L,-1);
+ lua_newtable(L);
+ lua_rawset(L,-4);
+ lua_rawget(L,-2);
+ }
+ /* now the 'type' table is top of stack */
+ if (anchor->type==at_baselig) {
+ lua_pushstring(L,anchor->anchor->name);
+ lua_rawget(L,-2);
+ if (!lua_istable(L,-1)) {
+ /* create the table first */
+ lua_pop(L,1);
+ lua_pushstring(L,anchor->anchor->name);
+ lua_pushvalue(L,-1);
+ lua_newtable(L);
+ lua_rawset(L,-4);
+ lua_rawget(L,-2);
+ }
+ lua_newtable(L);
+ dump_intfield(L,"x", anchor->me.x);
+ dump_intfield(L,"y", anchor->me.y);
+ if (anchor->has_ttf_pt)
+ dump_intfield(L,"ttf_pt_index", anchor->ttf_pt_index);
+ dump_intfield(L,"lig_index", anchor->lig_index);
+ lua_rawseti(L,-2,(anchor->lig_index+1));
+ lua_pop(L,1);
+ } else {
+ lua_pushstring(L,anchor->anchor->name);
+ lua_newtable(L);
+ dump_intfield(L,"x", anchor->me.x);
+ dump_intfield(L,"y", anchor->me.y);
+ if (anchor->has_ttf_pt)
+ dump_intfield(L,"ttf_pt_index", anchor->ttf_pt_index);
+ dump_intfield(L,"lig_index", anchor->lig_index);
+ lua_rawset(L,-3);
+ }
+ lua_pop(L,1);
+}
+
+void
+handle_anchorpoint (lua_State *L, struct anchorpoint *anchor) {
+ struct anchorpoint *next;
+ next = anchor;
+ while (next != NULL) {
+ do_handle_anchorpoint(L, next);
+ next = next->next;
+ }
+}
+
+void
+handle_glyphvariants (lua_State *L, struct glyphvariants *vars) {
+ int i ;
+ dump_stringfield(L, "variants", vars->variants);
+ dump_intfield (L, "italic_correction", vars->italic_correction);
+ lua_newtable(L);
+ for (i=0; i< vars->part_cnt; i++) {
+ lua_newtable(L);
+ dump_stringfield(L, "component", vars->parts[i].component);
+ dump_intfield(L, "extender", vars->parts[i].is_extender);
+ dump_intfield(L, "start", vars->parts[i].startConnectorLength);
+ dump_intfield(L, "end", vars->parts[i].endConnectorLength);
+ dump_intfield(L, "advance", vars->parts[i].fullAdvance);
+ lua_rawseti(L,-2,(i+1));
+ }
+ lua_setfield(L, -2, "parts");
+}
+
+void handle_mathkernvertex (lua_State *L, struct mathkernvertex *mkv) {
+ int i;
+ for (i=0; i<mkv->cnt;i++) {
+ lua_newtable(L);
+ dump_intfield(L, "height", mkv->mkd[i].height );
+ dump_intfield(L, "kern", mkv->mkd[i].kern );
+ lua_rawseti(L,-2, (i+1));
+ }
+}
+
+void handle_mathkern (lua_State *L, struct mathkern *mk) {
+ lua_newtable(L);
+ handle_mathkernvertex(L, &(mk->top_right));
+ lua_setfield(L, -2, "top_right");
+ lua_newtable(L);
+ handle_mathkernvertex(L, &(mk->top_left));
+ lua_setfield(L, -2, "top_left");
+ lua_newtable(L);
+ handle_mathkernvertex(L, &(mk->bottom_right));
+ lua_setfield(L, -2, "bottom_right");
+ lua_newtable(L);
+ handle_mathkernvertex(L, &(mk->bottom_left));
+ lua_setfield(L, -2, "bottom_left");
+}
+
+
+
+void
+handle_splinechar (lua_State *L,struct splinechar *glyph, int hasvmetrics) {
+ DBounds bb;
+ if (glyph->xmax==0 && glyph->ymax==0 && glyph->xmin==0 && glyph->ymin==0) {
+ SplineCharFindBounds(glyph,&bb);
+ glyph->xmin = bb.minx;
+ glyph->ymin = bb.miny;
+ glyph->xmax = bb.maxx;
+ glyph->ymax = bb.maxy;
+ }
+ dump_stringfield(L,"name", glyph->name);
+ dump_intfield(L,"unicode", glyph->unicodeenc);
+ lua_createtable(L,4,0);
+ lua_pushnumber(L,1); lua_pushnumber(L,glyph->xmin); lua_rawset(L,-3);
+ lua_pushnumber(L,2); lua_pushnumber(L,glyph->ymin); lua_rawset(L,-3);
+ lua_pushnumber(L,3); lua_pushnumber(L,glyph->xmax); lua_rawset(L,-3);
+ lua_pushnumber(L,4); lua_pushnumber(L,glyph->ymax); lua_rawset(L,-3);
+ lua_setfield(L,-2,"boundingbox");
+ /*dump_intfield(L,"orig_pos", glyph->orig_pos);*/
+ if (hasvmetrics)
+ dump_intfield(L,"vwidth", glyph->vwidth);
+ dump_intfield(L,"width", glyph->width);
+
+ if (glyph->lsidebearing != glyph->xmin) {
+ dump_cond_intfield(L,"lsidebearing", glyph->lsidebearing);
+ }
+ /* dump_intfield(L,"ttf_glyph", glyph->ttf_glyph); */
+
+ /* Layer layers[2]; */ /* TH Not used */
+ /* int layer_cnt; */ /* TH Not used */
+ /* StemInfo *hstem; */ /* TH Not used */
+ /* StemInfo *vstem; */ /* TH Not used */
+ /* DStemInfo *dstem; */ /* TH Not used */
+
+ /* MinimumDistance *md; */ /* TH Not used */
+ /* struct charviewbase *views; */ /* TH Not used */
+ /* struct charinfo *charinfo; */ /* TH ? (charinfo.c) */
+ /* struct splinefont *parent; */ /* TH Not used */
+
+ if (glyph->glyph_class>0) {
+ dump_enumfield(L,"class", glyph->glyph_class, glyph_class_enum);
+ }
+ /* TH: internal fontforge stuff
+ dump_intfield(L,"changed", glyph->changed);
+ dump_intfield(L,"changedsincelasthinted", glyph->changedsincelasthinted);
+ dump_intfield(L,"manualhints", glyph->manualhints);
+ dump_intfield(L,"ticked", glyph->ticked);
+ dump_intfield(L,"changed_since_autosave", glyph->changed_since_autosave);
+ dump_intfield(L,"widthset", glyph->widthset);
+ dump_intfield(L,"vconflicts", glyph->vconflicts);
+ dump_intfield(L,"hconflicts", glyph->hconflicts);
+ dump_intfield(L,"searcherdummy", glyph->searcherdummy);
+ dump_intfield(L,"changed_since_search", glyph->changed_since_search);
+ dump_intfield(L,"wasopen", glyph->wasopen);
+ dump_intfield(L,"namechanged", glyph->namechanged);
+ dump_intfield(L,"blended", glyph->blended);
+ dump_intfield(L,"ticked2", glyph->ticked2);
+ dump_intfield(L,"unused_so_far", glyph->unused_so_far);
+ dump_intfield(L,"numberpointsbackards", glyph->numberpointsbackards);
+ dump_intfield(L,"instructions_out_of_date", glyph->instructions_out_of_date);
+ dump_intfield(L,"complained_about_ptnums", glyph->complained_about_ptnums);
+ unsigned int vs_open: 1;
+ unsigned int unlink_rm_ovrlp_save_undo: 1;
+ unsigned int inspiro: 1;
+ unsigned int lig_caret_cnt_fixed: 1;
+
+
+ uint8 *ttf_instrs;
+ int16 ttf_instrs_len;
+ int16 countermask_cnt;
+ HintMask *countermasks;
+ */
+
+ if (glyph->kerns != NULL) {
+ lua_newtable(L);
+ handle_kernpair(L,glyph->kerns);
+ lua_setfield(L,-2,"kerns");
+ }
+ if (glyph->vkerns != NULL) {
+ lua_newtable(L);
+ handle_kernpair(L,glyph->vkerns);
+ lua_setfield(L,-2,"vkerns");
+ }
+
+ if (glyph->dependents != NULL) {
+ lua_newtable(L);
+ handle_splinecharlist(L,glyph->dependents);
+ lua_setfield(L,-2,"dependents");
+
+ }
+ if (glyph->possub != NULL) {
+ lua_newtable(L);
+ handle_generic_pst(L,glyph->possub);
+ lua_setfield(L,-2,"lookups");
+ }
+
+ if (glyph->ligofme != NULL) {
+ lua_newtable(L);
+ handle_liglist(L,glyph->ligofme);
+ lua_setfield(L,-2,"ligatures");
+ }
+
+ if (glyph->comment != NULL)
+ dump_stringfield(L,"comment", glyph->comment);
+
+ /* Color color; */ /* dont care */
+
+ if (glyph->anchor != NULL) {
+ lua_newtable(L);
+ handle_anchorpoint(L,glyph->anchor);
+ lua_setfield(L,-2,"anchors");
+ }
+
+ if (glyph->altuni != NULL) {
+ lua_newtable(L);
+ handle_altuni(L, glyph->altuni);
+ lua_setfield(L,-2,"altuni");
+ }
+
+ if (glyph->tex_height != TEX_UNDEF)
+ dump_intfield(L,"tex_height", glyph->tex_height);
+ if (glyph->tex_depth != TEX_UNDEF)
+ dump_intfield(L,"tex_depth", glyph->tex_depth);
+
+ dump_cond_intfield(L, "is_extended_shape", glyph->is_extended_shape);
+ if (glyph->italic_correction != TEX_UNDEF)
+ dump_intfield(L, "italic_correction", glyph->italic_correction);
+ if (glyph->top_accent_horiz != TEX_UNDEF)
+ dump_intfield(L, "top_accent", glyph->top_accent_horiz);
+
+ if (glyph->vert_variants != NULL) {
+ lua_newtable(L);
+ handle_glyphvariants(L, glyph->vert_variants);
+ lua_setfield(L,-2,"vert_variants");
+ }
+ if (glyph->horiz_variants != NULL) {
+ lua_newtable(L);
+ handle_glyphvariants(L, glyph->horiz_variants);
+ lua_setfield(L,-2,"horiz_variants");
+ }
+ if (glyph->mathkern != NULL) {
+ lua_newtable(L);
+ handle_mathkern(L, glyph->mathkern);
+ lua_setfield(L,-2,"mathkern");
+ }
+}
+
+char *panose_values_0[] = { "Any", "No Fit", "Text and Display", "Script", "Decorative", "Pictorial" };
+
+char *panose_values_1[] = { "Any", "No Fit", "Cove", "Obtuse Cove", "Square Cove", "Obtuse Square Cove",
+ "Square", "Thin", "Bone", "Exaggerated", "Triangle", "Normal Sans",
+ "Obtuse Sans", "Perp Sans", "Flared", "Rounded" } ;
+
+char *panose_values_2[] = { "Any", "No Fit", "Very Light", "Light", "Thin", "Book",
+ "Medium", "Demi", "Bold", "Heavy", "Black", "Nord" } ;
+
+char *panose_values_3[] = { "Any", "No Fit", "Old Style", "Modern", "Even Width",
+ "Expanded", "Condensed", "Very Expanded", "Very Condensed", "Monospaced" };
+
+char *panose_values_4[] = { "Any", "No Fit", "None", "Very Low", "Low", "Medium Low",
+ "Medium", "Medium High", "High", "Very High" };
+
+char *panose_values_5[] = { "Any", "No Fit", "Gradual/Diagonal", "Gradual/Transitional","Gradual/Vertical",
+ "Gradual/Horizontal", "Rapid/Vertical", "Rapid/Horizontal", "Instant/Vertical" };
+
+char *panose_values_6[] = {"Any","No Fit","Straight Arms/Horizontal","Straight Arms/Wedge","Straight Arms/Vertical",
+ "Straight Arms/Single Serif","Straight Arms/Double Serif","Non-Straight Arms/Horizontal",
+ "Non-Straight Arms/Wedge","Non-Straight Arms/Vertical","Non-Straight Arms/Single Serif",
+ "Non-Straight Arms/Double Serif" };
+
+char *panose_values_7[] = { "Any", "No Fit","Normal/Contact","Normal/Weighted","Normal/Boxed","Normal/Flattened",
+ "Normal/Rounded","Normal/Off Center","Normal/Square","Oblique/Contact","Oblique/Weighted",
+ "Oblique/Boxed","Oblique/Flattened","Oblique/Rounded","Oblique/Off Center","Oblique/Square" };
+
+char *panose_values_8[] = { "Any","No Fit","Standard/Trimmed","Standard/Pointed","Standard/Serifed","High/Trimmed",
+ "High/Pointed","High/Serifed","Constant/Trimmed","Constant/Pointed","Constant/Serifed",
+ "Low/Trimmed","Low/Pointed","Low/Serifed"};
+
+char *panose_values_9[] = { "Any","No Fit", "Constant/Small", "Constant/Standard",
+ "Constant/Large", "Ducking/Small", "Ducking/Standard", "Ducking/Large" };
+
+
+void
+handle_pfminfo (lua_State *L, struct pfminfo pfm) {
+
+ dump_intfield (L, "pfmset", pfm.pfmset);
+ dump_intfield (L, "winascent_add", pfm.winascent_add);
+ dump_intfield (L, "windescent_add", pfm.windescent_add);
+ dump_intfield (L, "hheadascent_add", pfm.hheadascent_add);
+ dump_intfield (L, "hheaddescent_add", pfm.hheaddescent_add);
+ dump_intfield (L, "typoascent_add", pfm.typoascent_add);
+ dump_intfield (L, "typodescent_add", pfm.typodescent_add);
+ dump_intfield (L, "subsuper_set", pfm.subsuper_set);
+ dump_intfield (L, "panose_set", pfm.panose_set);
+ dump_intfield (L, "hheadset", pfm.hheadset);
+ dump_intfield (L, "vheadset", pfm.vheadset);
+ dump_intfield (L, "pfmfamily", pfm.pfmfamily);
+ dump_intfield (L, "weight", pfm.weight);
+ dump_intfield (L, "width", pfm.width);
+ dump_intfield (L, "avgwidth", pfm.avgwidth);
+ dump_intfield (L, "firstchar", pfm.firstchar);
+ dump_intfield (L, "lastchar", pfm.lastchar);
+ lua_createtable(L,0,10);
+ dump_enumfield(L,"familytype", pfm.panose[0], panose_values_0);
+ dump_enumfield(L,"serifstyle", pfm.panose[1], panose_values_1);
+ dump_enumfield(L,"weight", pfm.panose[2], panose_values_2);
+ dump_enumfield(L,"proportion", pfm.panose[3], panose_values_3);
+ dump_enumfield(L,"contrast", pfm.panose[4], panose_values_4);
+ dump_enumfield(L,"strokevariation", pfm.panose[5], panose_values_5);
+ dump_enumfield(L,"armstyle", pfm.panose[6], panose_values_6);
+ dump_enumfield(L,"letterform", pfm.panose[7], panose_values_7);
+ dump_enumfield(L,"midline", pfm.panose[8], panose_values_8);
+ dump_enumfield(L,"xheight", pfm.panose[9], panose_values_9);
+ lua_setfield (L,-2,"panose");
+
+ dump_intfield (L, "fstype", pfm.fstype);
+ dump_intfield (L, "linegap", pfm.linegap);
+ dump_intfield (L, "vlinegap", pfm.vlinegap);
+ dump_intfield (L, "hhead_ascent", pfm.hhead_ascent);
+ dump_intfield (L, "hhead_descent", pfm.hhead_descent);
+ dump_intfield (L, "hhead_descent", pfm.hhead_descent);
+ dump_intfield (L, "os2_typoascent", pfm.os2_typoascent );
+ dump_intfield (L, "os2_typodescent", pfm.os2_typodescent );
+ dump_intfield (L, "os2_typolinegap", pfm.os2_typolinegap );
+ dump_intfield (L, "os2_winascent", pfm.os2_winascent );
+ dump_intfield (L, "os2_windescent", pfm.os2_windescent );
+ dump_intfield (L, "os2_subxsize", pfm.os2_subxsize );
+ dump_intfield (L, "os2_subysize", pfm.os2_subysize );
+ dump_intfield (L, "os2_subxoff", pfm.os2_subxoff );
+ dump_intfield (L, "os2_subyoff", pfm.os2_subyoff );
+ dump_intfield (L, "os2_supxsize", pfm.os2_supxsize );
+ dump_intfield (L, "os2_supysize", pfm.os2_supysize );
+ dump_intfield (L, "os2_supxoff", pfm.os2_supxoff );
+ dump_intfield (L, "os2_supyoff", pfm.os2_supyoff );
+ dump_intfield (L, "os2_strikeysize", pfm.os2_strikeysize );
+ dump_intfield (L, "os2_strikeypos", pfm.os2_strikeypos );
+ dump_lstringfield (L, "os2_vendor", pfm.os2_vendor, 4);
+ dump_intfield (L, "os2_family_class", pfm.os2_family_class);
+ dump_intfield (L, "os2_xheight", pfm.os2_xheight);
+ dump_intfield (L, "os2_capheight", pfm.os2_capheight);
+ dump_intfield (L, "os2_defaultchar", pfm.os2_defaultchar);
+ dump_intfield (L, "os2_breakchar", pfm.os2_breakchar);
+ if (pfm.hascodepages) {
+ lua_newtable(L);
+ lua_pushnumber(L, pfm.codepages[0]); lua_rawseti(L,-2,1);
+ lua_pushnumber(L, pfm.codepages[1]); lua_rawseti(L,-2,2);
+ lua_setfield(L,-2,"codepages");
+ }
+ if (pfm.hasunicoderanges) {
+ lua_newtable(L);
+ lua_pushnumber(L, pfm.unicoderanges[0]); lua_rawseti(L,-2,1);
+ lua_pushnumber(L, pfm.unicoderanges[1]); lua_rawseti(L,-2,2);
+ lua_pushnumber(L, pfm.unicoderanges[2]); lua_rawseti(L,-2,3);
+ lua_pushnumber(L, pfm.unicoderanges[3]); lua_rawseti(L,-2,4);
+ lua_setfield(L,-2,"unicoderanges");
+ }
+}
+
+
+void
+do_handle_enc (lua_State *L, struct enc *enc) {
+ int i;
+
+ dump_stringfield(L,"enc_name", enc->enc_name);
+ dump_intfield (L,"char_cnt", enc->char_cnt);
+
+ lua_checkstack(L,4);
+ if (enc->char_cnt && enc->unicode != NULL) {
+ lua_createtable(L,enc->char_cnt,1);
+ for (i=0;i<enc->char_cnt;i++) {
+ lua_pushnumber(L,i);
+ lua_pushnumber(L,enc->unicode[i]);
+ lua_rawset(L,-3);
+ }
+ lua_setfield(L,-2,"unicode");
+ }
+
+ if (enc->char_cnt && enc->psnames != NULL) {
+ lua_createtable(L,enc->char_cnt,1);
+ for (i=0;i<enc->char_cnt;i++) {
+ lua_pushnumber(L,i);
+ lua_pushstring(L,enc->psnames[i]);
+ lua_rawset(L,-3);
+ }
+ lua_setfield(L,-2,"psnames");
+ }
+ dump_intfield (L,"builtin", enc->builtin );
+ dump_intfield (L,"hidden", enc->hidden );
+ dump_intfield (L,"only_1byte", enc->only_1byte );
+ dump_intfield (L,"has_1byte", enc->has_1byte );
+ dump_intfield (L,"has_2byte", enc->has_2byte );
+ dump_cond_intfield (L,"is_unicodebmp", enc->is_unicodebmp );
+ dump_cond_intfield (L,"is_unicodefull", enc->is_unicodefull );
+ dump_cond_intfield (L,"is_custom", enc->is_custom );
+ dump_cond_intfield (L,"is_original", enc->is_original );
+ dump_cond_intfield (L,"is_compact", enc->is_compact );
+ dump_cond_intfield (L,"is_japanese", enc->is_japanese );
+ dump_cond_intfield (L,"is_korean", enc->is_korean );
+ dump_cond_intfield (L,"is_tradchinese", enc->is_tradchinese );
+ dump_cond_intfield (L,"is_simplechinese", enc->is_simplechinese);
+
+ if (enc->iso_2022_escape_len > 0) {
+ dump_lstringfield (L,"iso_2022_escape", enc->iso_2022_escape, enc->iso_2022_escape_len);
+ }
+ dump_intfield (L,"low_page", enc->low_page);
+ dump_intfield(L,"high_page", enc->high_page);
+
+ dump_stringfield(L,"iconv_name", enc->iconv_name);
+
+ dump_intfield (L,"char_max", enc->char_max);
+}
+
+void
+handle_enc (lua_State *L, struct enc *enc) {
+ struct enc *next;
+ NESTED_TABLE(do_handle_enc,enc,24);
+}
+
+void
+handle_encmap (lua_State *L, struct encmap *map, int notdef_loc) {
+ int i;
+ dump_intfield(L,"enccount", map->enccount) ;
+ dump_intfield(L,"encmax", map->encmax) ;
+ dump_intfield(L,"backmax", map->backmax) ;
+ /*dump_intfield(L,"ticked", map->ticked) ;*/
+ if (map->remap != NULL) {
+ lua_newtable(L);
+ dump_intfield(L,"firstenc", map->remap->firstenc) ;
+ dump_intfield(L,"lastenc", map->remap->lastenc) ;
+ dump_intfield(L,"infont", map->remap->infont) ;
+ lua_setfield(L,-2,"remap");
+ }
+ lua_checkstack(L,4);
+ if (map->encmax > 0 && map->map != NULL) {
+ lua_createtable(L,map->encmax,1);
+ for (i=0;i<map->encmax;i++) {
+ if (map->map[i]!=-1) {
+ int l = map->map[i];
+ lua_pushnumber(L,i);
+ if (l<notdef_loc)
+ lua_pushnumber(L,(l+1));
+ else
+ lua_pushnumber(L,l);
+ lua_rawset(L,-3);
+ }
+ }
+ lua_setfield(L,-2,"map");
+ }
+
+ if (map->backmax > 0 && map->backmap != NULL) {
+ lua_newtable(L);
+ for (i=0;i<map->backmax;i++) {
+ if (map->backmap[i]!=-1) { /* TODO: check this, because valgrind sometimes says
+ "Conditional jump or move depends on uninitialised value(s)"
+ needs a test file.
+ */
+ if (i<notdef_loc)
+ lua_pushnumber(L,(i+1));
+ else
+ lua_pushnumber(L,i);
+ lua_pushnumber(L,map->backmap[i]);
+ lua_rawset(L,-3);
+ }
+ }
+ lua_setfield(L,-2,"backmap");
+ }
+
+ if (map->enc != NULL) {
+ lua_newtable(L);
+ handle_enc(L,map->enc);
+ lua_setfield(L,-2,"enc");
+ }
+}
+
+static void
+handle_psdict (lua_State *L, struct psdict *private) {
+ int k;
+ if (private->keys != NULL && private->values != NULL) {
+ for (k=0;k<private->next;k++) {
+ lua_pushstring(L,private->keys[k]);
+ lua_pushstring(L,private->values[k]);
+ lua_rawset(L,-3);
+ }
+ }
+}
+
+void
+do_handle_ttflangname (lua_State *L, struct ttflangname *names) {
+ int k;
+ dump_stringfield(L,"lang", (char *)MSLangString(names->lang)) ;
+ lua_checkstack(L,4);
+ lua_createtable(L,0,ttf_namemax);
+ for (k=0;k<ttf_namemax;k++) {
+ lua_pushstring(L,ttfnames_enum[k]);
+ lua_pushstring(L,names->names[k]);
+ lua_rawset(L,-3);
+ }
+ lua_setfield(L, -2 , "names");
+}
+
+
+void
+handle_ttflangname (lua_State *L, struct ttflangname *names) {
+ struct ttflangname *next;
+ NESTED_TABLE(do_handle_ttflangname,names,2);
+}
+
+
+void
+do_handle_anchorclass (lua_State *L, struct anchorclass *anchor) {
+
+ dump_stringfield(L,"name", anchor->name);
+ dump_subtable_name (L, "lookup", anchor->subtable);
+ dump_enumfield(L,"type", anchor->type, anchorclass_type_enum);
+ /* uint8 has_base; */
+ /* uint8 processed, has_mark, matches, ac_num; */
+ /* uint8 ticked; */
+}
+
+void
+handle_anchorclass (lua_State *L, struct anchorclass *anchor) {
+ struct anchorclass *next;
+ NESTED_TABLE(do_handle_anchorclass,anchor,10);
+}
+
+void
+do_handle_ttf_table (lua_State *L, struct ttf_table *ttf_tab) {
+
+ dump_tag(L,"tag", ttf_tab->tag);
+ dump_intfield(L,"len", ttf_tab->len);
+ dump_intfield(L,"maxlen", ttf_tab->maxlen);
+ dump_lstringfield(L,"data", (char *)ttf_tab->data, ttf_tab->len);
+}
+
+void
+handle_ttf_table (lua_State *L, struct ttf_table *ttf_tab) {
+ struct ttf_table *next;
+ NESTED_TABLE(do_handle_ttf_table,ttf_tab,4);
+}
+
+void
+do_handle_kernclass (lua_State *L, struct kernclass *kerns) {
+ int k;
+
+ /*
+ * dump_intfield(L,"first_cnt", kerns->first_cnt);
+ * dump_intfield(L,"second_cnt", kerns->second_cnt);
+ */
+ lua_checkstack(L,4);
+ lua_createtable(L,kerns->first_cnt,1);
+ for (k=0;k<kerns->first_cnt;k++) {
+ lua_pushnumber(L,(k+1));
+ lua_pushstring(L,kerns->firsts[k]);
+ lua_rawset(L,-3);
+ }
+ lua_setfield(L,-2,"firsts");
+
+ lua_createtable(L,kerns->second_cnt,1);
+ for (k=0;k<kerns->second_cnt;k++) {
+ lua_pushnumber(L,(k+1));
+ lua_pushstring(L,kerns->seconds[k]);
+ lua_rawset(L,-3);
+ }
+ lua_setfield(L,-2,"seconds");
+
+ dump_subtable_name(L, "lookup", kerns->subtable);
+ /*dump_intfield(L,"kcid", kerns->kcid); *//* probably not needed */
+
+ lua_createtable(L,kerns->second_cnt*kerns->first_cnt,1);
+ for (k=0;k<(kerns->second_cnt*kerns->first_cnt);k++) {
+ if (kerns->offsets[k]!=0) {
+ lua_pushnumber(L,(k+1));
+ lua_pushnumber(L,kerns->offsets[k]);
+ lua_rawset(L,-3);
+ }
+ }
+ lua_setfield(L,-2,"offsets");
+
+}
+
+void
+handle_kernclass (lua_State *L, struct kernclass *kerns) {
+ struct kernclass *next;
+ NESTED_TABLE(do_handle_kernclass,kerns,8);
+}
+
+
+#define DUMP_NUMBER_ARRAY(s,cnt,item) { \
+ if (cnt>0 && item != NULL) { \
+ int kk; \
+ lua_newtable(L); \
+ for (kk=0;kk<cnt;kk++) { \
+ lua_pushnumber(L,(kk+1)); \
+ lua_pushnumber(L,item[kk]); \
+ lua_rawset(L,-3); } \
+ lua_setfield(L,-2,s); } }
+
+
+#define DUMP_STRING_ARRAY(s,cnt,item) { \
+ if (cnt>0 && item!=NULL) { \
+ int kk; \
+ lua_newtable(L); \
+ for (kk=0;kk<cnt;kk++) { \
+ lua_pushnumber(L,(kk+1)); \
+ lua_pushstring(L,item[kk]); \
+ lua_rawset(L,-3); } \
+ lua_setfield(L,-2,s); } }
+
+#define DUMP_EXACT_STRING_ARRAY(s,cnt,item) { \
+ if (cnt>0 && item!=NULL) { \
+ int kk; \
+ lua_newtable(L); \
+ for (kk=0;kk<cnt;kk++) { \
+ lua_pushnumber(L,(kk)); \
+ lua_pushstring(L,item[kk]); \
+ lua_rawset(L,-3); } \
+ lua_setfield(L,-2,s); } }
+
+
+void handle_fpst_rule (lua_State *L, struct fpst_rule *rule, int format) {
+ int k;
+
+
+ if (format == pst_glyphs) {
+
+ lua_newtable(L);
+ dump_stringfield(L,"names",rule->u.glyph.names);
+ dump_stringfield(L,"back",rule->u.glyph.back);
+ dump_stringfield(L,"fore",rule->u.glyph.fore);
+ lua_setfield(L,-2,fpossub_format_enum[format]);
+
+ } else if (format == pst_class) {
+
+ lua_newtable(L);
+ DUMP_NUMBER_ARRAY("current", rule->u.class.ncnt,rule->u.class.nclasses);
+ DUMP_NUMBER_ARRAY("before", rule->u.class.bcnt,rule->u.class.bclasses);
+ DUMP_NUMBER_ARRAY("after", rule->u.class.fcnt,rule->u.class.fclasses);
+#if 0
+ DUMP_NUMBER_ARRAY("allclasses", 0,rule->u.class.allclasses);
+#endif
+ lua_setfield(L,-2,fpossub_format_enum[format]);
+
+ } else if (format == pst_coverage) {
+
+ lua_newtable(L);
+ DUMP_STRING_ARRAY("current", rule->u.coverage.ncnt,rule->u.coverage.ncovers);
+ DUMP_STRING_ARRAY("before", rule->u.coverage.bcnt,rule->u.coverage.bcovers);
+ DUMP_STRING_ARRAY("after", rule->u.coverage.fcnt,rule->u.coverage.fcovers);
+ lua_setfield(L,-2,fpossub_format_enum[format]);
+
+ } else if (format == pst_reversecoverage) {
+
+ lua_newtable(L);
+ DUMP_STRING_ARRAY("current", rule->u.rcoverage.always1,rule->u.rcoverage.ncovers);
+ DUMP_STRING_ARRAY("before", rule->u.rcoverage.bcnt,rule->u.rcoverage.bcovers);
+ DUMP_STRING_ARRAY("after", rule->u.rcoverage.fcnt,rule->u.rcoverage.fcovers);
+ dump_stringfield(L,"replacements", rule->u.rcoverage.replacements);
+ lua_setfield(L,-2,fpossub_format_enum[format]);
+ } else {
+ fprintf(stderr,"handle_fpst_rule(): Unknown rule format: %d\n",format);
+ }
+
+ if (rule->lookup_cnt>0) {
+ lua_newtable(L);
+ for (k=0;k<rule->lookup_cnt;k++) {
+ lua_pushnumber(L,(rule->lookups[k].seq+1));
+ if (rule->lookups[k].lookup!=NULL) {
+ lua_pushstring(L,rule->lookups[k].lookup->lookup_name);
+ } else {
+ lua_pushnil(L);
+ }
+ lua_rawset(L,-3);
+ }
+ lua_setfield(L,-2,"lookups");
+ } else {
+ /*fprintf(stderr,"handle_fpst_rule(): No lookups?\n");*/
+ }
+}
+
+void
+do_handle_generic_fpst(lua_State *L, struct generic_fpst *fpst) {
+ int k;
+
+ if (fpst->type>LAST_POSSUB_TYPE_ENUM) {
+ dump_intfield(L,"type", fpst->type);
+ } else {
+ dump_enumfield(L,"type", fpst->type, possub_type_enum);
+ }
+ dump_enumfield(L,"format", fpst->format, fpossub_format_enum);
+
+ if (fpst->format==pst_class) {
+ DUMP_EXACT_STRING_ARRAY("current_class",fpst->nccnt,fpst->nclass);
+ DUMP_EXACT_STRING_ARRAY("before_class",fpst->bccnt,fpst->bclass);
+ DUMP_EXACT_STRING_ARRAY("after_class",fpst->fccnt,fpst->fclass);
+ } else {
+ DUMP_STRING_ARRAY("current_class",fpst->nccnt,fpst->nclass);
+ DUMP_STRING_ARRAY("before_class",fpst->bccnt,fpst->bclass);
+ DUMP_STRING_ARRAY("after_class",fpst->fccnt,fpst->fclass);
+ }
+
+ lua_checkstack(L,4);
+ if (fpst->rule_cnt>0) {
+ lua_createtable(L,fpst->rule_cnt,1);
+ for (k=0;k<fpst->rule_cnt;k++) {
+ lua_pushnumber(L,(k+1));
+ lua_newtable(L);
+ handle_fpst_rule(L,&(fpst->rules[k]),fpst->format);
+ lua_rawset(L,-3);
+ }
+ lua_setfield(L,-2,"rules");
+ }
+ /*dump_intfield (L,"ticked", fpst->ticked);*/
+}
+
+void
+handle_generic_fpst(lua_State *L, struct generic_fpst *fpst) {
+ struct generic_fpst *next;
+ int k = 1;
+ lua_checkstack(L,3);
+ if (fpst->subtable != NULL &&
+ fpst->subtable->subtable_name != NULL) {
+ lua_pushstring(L,fpst->subtable->subtable_name);
+ } else {
+ lua_pushnumber(L,k); k++;
+ }
+ lua_createtable(L,0,10);
+ do_handle_generic_fpst(L,fpst);
+ lua_rawset(L,-3);
+ next = fpst->next;
+ while (next != NULL) {
+ lua_checkstack(L,3);
+ if (next->subtable != NULL &&
+ next->subtable->subtable_name != NULL) {
+ lua_pushstring(L,next->subtable->subtable_name);
+ } else {
+ lua_pushnumber(L,k); k++;
+ }
+ lua_createtable(L,0,10);
+ do_handle_generic_fpst(L, next);
+ lua_rawset(L,-3);
+ next = next->next;
+ }
+}
+
+void
+do_handle_otfname (lua_State *L, struct otfname *oname) {
+ dump_intfield(L,"lang", oname->lang);
+ dump_stringfield(L,"name", oname->name);
+}
+
+void
+handle_otfname (lua_State *L, struct otfname *oname) {
+ struct otfname *next;
+ NESTED_TABLE(do_handle_otfname,oname,2);
+}
+
+void
+do_handle_macname (lua_State *L, struct macname *featname) {
+ dump_intfield(L,"enc", featname->enc);
+ dump_intfield(L,"lang", featname->lang);
+ dump_stringfield(L,"name", featname->name);
+}
+
+void
+handle_macname (lua_State *L, struct macname *featname) {
+ struct macname *next;
+ NESTED_TABLE(do_handle_macname,featname,3);
+}
+
+void
+do_handle_macsetting (lua_State *L, struct macsetting *settings) {
+ dump_intfield(L,"setting", settings->setting);
+ dump_intfield(L,"strid", settings->strid);
+ dump_intfield(L,"initially_enabled", settings->initially_enabled);
+ if (settings->setname != NULL) {
+ lua_newtable(L);
+ handle_macname(L,settings->setname);
+ lua_setfield(L,-2,"setname");
+ }
+}
+
+void
+handle_macsetting (lua_State *L, struct macsetting *settings) {
+ struct macsetting *next;
+ NESTED_TABLE(do_handle_macsetting,settings,4);
+}
+
+
+void
+do_handle_macfeat (lua_State *L, struct macfeat *features) {
+
+ dump_intfield(L,"feature", features->feature);
+ dump_intfield(L,"ismutex", features->ismutex);
+ dump_intfield(L,"default_setting", features->default_setting);
+ dump_intfield(L,"strid", features->strid);
+
+ if (features->featname != NULL) {
+ lua_newtable(L);
+ handle_macname(L,features->featname);
+ lua_setfield(L,-2,"featname");
+ }
+
+ if (features->settings != NULL) {
+ lua_newtable(L);
+ handle_macsetting(L,features->settings);
+ lua_setfield(L,-2,"settings");
+ }
+}
+
+void
+handle_macfeat (lua_State *L, struct macfeat *features) {
+ struct macfeat *next;
+ NESTED_TABLE(do_handle_macfeat,features,6);
+}
+
+
+/* asm_state flags:
+ Indic:
+ 0x8000 mark current glyph as first in rearrangement
+ 0x4000 don't advance to next glyph
+ 0x2000 mark current glyph as last
+ 0x000f verb
+ 0 = no change 8 = AxCD => CDxA
+ 1 = Ax => xA 9 = AxCD => DCxA
+ 2 = xD => Dx a = ABxD => DxAB
+ 3 = AxD => DxA b = ABxD => DxBA
+ 4 = ABx => xAB c = ABxCD => CDxAB
+ 5 = ABx => xBA d = ABxCD => CDxBA
+ 6 = xCD => CDx e = ABxCD => DCxAB
+ 7 = xCD => DCx f = ABxCD => DCxBA
+ Contextual:
+ 0x8000 mark current glyph
+ 0x4000 don't advance to next glyph
+ Insert:
+ 0x8000 mark current glyph
+ 0x4000 don't advance to next glyph
+ 0x2000 current is Kashida like
+ 0x1000 mark is Kashida like
+ 0x0800 current insert before
+ 0x0400 mark insert before
+ 0x03e0 count of chars to be inserted at current (31 max)
+ 0x001f count of chars to be inserted at mark (31 max)
+ Kern:
+ 0x8000 add current glyph to kerning stack
+ 0x4000 don't advance to next glyph
+ 0x3fff value offset
+*/
+/* to be tested */
+void
+do_handle_generic_asm (lua_State *L, struct generic_asm *sm) {
+ int i, k;
+
+ dump_enumfield (L,"type", sm->type, asm_type_enum);
+ /* backref */
+ dump_subtable_name(L, "lookup", sm->subtable);
+ /* uint8 ticked; */
+ lua_newtable(L);
+ if (sm->flags & asm_vert) {
+ lua_pushstring(L,"vert"); lua_pushboolean(L,1); lua_rawset(L,-3);
+ }
+ if (sm->flags & asm_descending) {
+ lua_pushstring(L,"descending"); lua_pushboolean(L,1); lua_rawset(L,-3);
+ }
+ if (sm->flags & asm_always) {
+ lua_pushstring(L,"always"); lua_pushboolean(L,1); lua_rawset(L,-3);
+ }
+ lua_setfield(L,-2,"flags");
+
+ if (sm->class_cnt >0) {
+ lua_newtable(L);
+ for (i=0; i<sm->class_cnt; i++) {
+ if (sm->classes[i]!=NULL) {
+ lua_pushstring(L,sm->classes[i]);
+ lua_rawseti(L,-2,(i+1));
+ }
+ }
+ lua_setfield(L,-2,"classes");
+ }
+ if (sm->state_cnt >0) {
+ lua_newtable(L);
+ for (i=0; i<(sm->class_cnt * sm->state_cnt); i++) {
+ struct asm_state as = sm->state[i];
+ dump_intfield(L,"next", as.next_state);
+ dump_intfield(L,"flags", as.flags);
+ if (sm->type==asm_context) {
+ lua_newtable(L);
+ if (as.u.context.mark_lookup!=NULL)
+ dump_stringfield(L,"mark", as.u.context.mark_lookup->lookup_name); /* backref */
+ if (as.u.context.cur_lookup!=NULL)
+ dump_stringfield(L,"cur", as.u.context.cur_lookup->lookup_name); /* backref */
+ lua_setfield(L,-2,"context");
+ } else if (sm->type==asm_insert) {
+ lua_newtable(L);
+ lua_pushstring(L, as.u.insert.mark_ins);
+ lua_setfield(L, -2, "mark");
+ lua_pushstring(L, as.u.insert.cur_ins);
+ lua_setfield(L, -2, "cur");
+ lua_setfield(L,-2,"insert");
+ } else if (sm->type==asm_kern) {
+ lua_newtable(L);
+ for (k=0;k<as.u.kern.kcnt;k++) {
+ lua_pushnumber(L,as.u.kern.kerns[k]);
+ lua_rawseti(L,-2, (k+1));
+ }
+ lua_setfield(L,-2,"kerns");
+ }
+ }
+ lua_setfield(L,-2,"states");
+ }
+}
+
+void
+handle_generic_asm (lua_State *L, struct generic_asm *sm) {
+ struct generic_asm *next;
+ NESTED_TABLE(do_handle_generic_asm,sm,6);
+}
+
+
+
+
+void handle_MATH (lua_State *L, struct MATH *MATH) {
+ dump_intfield(L,"ScriptPercentScaleDown",MATH->ScriptPercentScaleDown);
+ dump_intfield(L,"ScriptScriptPercentScaleDown",MATH->ScriptScriptPercentScaleDown);
+ dump_intfield(L,"DelimitedSubFormulaMinHeight",MATH->DelimitedSubFormulaMinHeight);
+ dump_intfield(L,"DisplayOperatorMinHeight",MATH->DisplayOperatorMinHeight);
+ dump_intfield(L,"MathLeading",MATH->MathLeading);
+ dump_intfield(L,"AxisHeight",MATH->AxisHeight);
+ dump_intfield(L,"AccentBaseHeight",MATH->AccentBaseHeight);
+ dump_intfield(L,"FlattenedAccentBaseHeight",MATH->FlattenedAccentBaseHeight);
+ dump_intfield(L,"SubscriptShiftDown",MATH->SubscriptShiftDown);
+ dump_intfield(L,"SubscriptTopMax",MATH->SubscriptTopMax);
+ dump_intfield(L,"SubscriptBaselineDropMin",MATH->SubscriptBaselineDropMin);
+ dump_intfield(L,"SuperscriptShiftUp",MATH->SuperscriptShiftUp);
+ dump_intfield(L,"SuperscriptShiftUpCramped",MATH->SuperscriptShiftUpCramped);
+ dump_intfield(L,"SuperscriptBottomMin",MATH->SuperscriptBottomMin);
+ dump_intfield(L,"SuperscriptBaselineDropMax",MATH->SuperscriptBaselineDropMax);
+ dump_intfield(L,"SubSuperscriptGapMin",MATH->SubSuperscriptGapMin);
+ dump_intfield(L,"SuperscriptBottomMaxWithSubscript",MATH->SuperscriptBottomMaxWithSubscript);
+ dump_intfield(L,"SpaceAfterScript",MATH->SpaceAfterScript);
+ dump_intfield(L,"UpperLimitGapMin",MATH->UpperLimitGapMin);
+ dump_intfield(L,"UpperLimitBaselineRiseMin",MATH->UpperLimitBaselineRiseMin);
+ dump_intfield(L,"LowerLimitGapMin",MATH->LowerLimitGapMin);
+ dump_intfield(L,"LowerLimitBaselineDropMin",MATH->LowerLimitBaselineDropMin);
+ dump_intfield(L,"StackTopShiftUp",MATH->StackTopShiftUp);
+ dump_intfield(L,"StackTopDisplayStyleShiftUp",MATH->StackTopDisplayStyleShiftUp);
+ dump_intfield(L,"StackBottomShiftDown",MATH->StackBottomShiftDown);
+ dump_intfield(L,"StackBottomDisplayStyleShiftDown",MATH->StackBottomDisplayStyleShiftDown);
+ dump_intfield(L,"StackGapMin",MATH->StackGapMin);
+ dump_intfield(L,"StackDisplayStyleGapMin",MATH->StackDisplayStyleGapMin);
+ dump_intfield(L,"StretchStackTopShiftUp",MATH->StretchStackTopShiftUp);
+ dump_intfield(L,"StretchStackBottomShiftDown",MATH->StretchStackBottomShiftDown);
+ dump_intfield(L,"StretchStackGapAboveMin",MATH->StretchStackGapAboveMin);
+ dump_intfield(L,"StretchStackGapBelowMin",MATH->StretchStackGapBelowMin);
+ dump_intfield(L,"FractionNumeratorShiftUp",MATH->FractionNumeratorShiftUp);
+ dump_intfield(L,"FractionNumeratorDisplayStyleShiftUp",MATH->FractionNumeratorDisplayStyleShiftUp);
+ dump_intfield(L,"FractionDenominatorShiftDown",MATH->FractionDenominatorShiftDown);
+ dump_intfield(L,"FractionDenominatorDisplayStyleShiftDown",MATH->FractionDenominatorDisplayStyleShiftDown);
+ dump_intfield(L,"FractionNumeratorGapMin",MATH->FractionNumeratorGapMin);
+ dump_intfield(L,"FractionNumeratorDisplayStyleGapMin",MATH->FractionNumeratorDisplayStyleGapMin);
+ dump_intfield(L,"FractionRuleThickness",MATH->FractionRuleThickness);
+ dump_intfield(L,"FractionDenominatorGapMin",MATH->FractionDenominatorGapMin);
+ dump_intfield(L,"FractionDenominatorDisplayStyleGapMin",MATH->FractionDenominatorDisplayStyleGapMin);
+ dump_intfield(L,"SkewedFractionHorizontalGap",MATH->SkewedFractionHorizontalGap);
+ dump_intfield(L,"SkewedFractionVerticalGap",MATH->SkewedFractionVerticalGap);
+ dump_intfield(L,"OverbarVerticalGap",MATH->OverbarVerticalGap);
+ dump_intfield(L,"OverbarRuleThickness",MATH->OverbarRuleThickness);
+ dump_intfield(L,"OverbarExtraAscender",MATH->OverbarExtraAscender);
+ dump_intfield(L,"UnderbarVerticalGap",MATH->UnderbarVerticalGap);
+ dump_intfield(L,"UnderbarRuleThickness",MATH->UnderbarRuleThickness);
+ dump_intfield(L,"UnderbarExtraDescender",MATH->UnderbarExtraDescender);
+ dump_intfield(L,"RadicalVerticalGap",MATH->RadicalVerticalGap);
+ dump_intfield(L,"RadicalDisplayStyleVerticalGap",MATH->RadicalDisplayStyleVerticalGap);
+ dump_intfield(L,"RadicalRuleThickness",MATH->RadicalRuleThickness);
+ dump_intfield(L,"RadicalExtraAscender",MATH->RadicalExtraAscender);
+ dump_intfield(L,"RadicalKernBeforeDegree",MATH->RadicalKernBeforeDegree);
+ dump_intfield(L,"RadicalKernAfterDegree",MATH->RadicalKernAfterDegree);
+ dump_intfield(L,"RadicalDegreeBottomRaisePercent",MATH->RadicalDegreeBottomRaisePercent);
+ dump_intfield(L,"MinConnectorOverlap",MATH->MinConnectorOverlap);
+}
+
+/* the handling of BASE is untested, no font */
+void handle_baselangextent (lua_State *L, struct baselangextent *ble);
+
+void
+do_handle_baselangextent (lua_State *L, struct baselangextent *ble) {
+ dump_tag(L,"tag",ble->lang);
+ dump_intfield(L,"ascent",ble->ascent);
+ dump_intfield(L,"descent",ble->descent);
+ lua_newtable(L);
+ handle_baselangextent(L, ble->features);
+ lua_setfield(L,-2,"features");
+}
+
+
+void handle_baselangextent (lua_State *L, struct baselangextent *ble) {
+ struct baselangextent *next;
+ NESTED_TABLE(do_handle_baselangextent,ble,4);
+}
+
+
+void handle_base (lua_State *L, struct Base *Base) {
+ int i;
+ struct basescript *next = Base->scripts;
+ lua_newtable(L);
+ for ( i=0; i<Base->baseline_cnt; i++ ) {
+ lua_pushstring(L,make_tag_string(Base->baseline_tags[i]));
+ lua_rawseti(L,-2,(i+1));
+ }
+ lua_setfield(L,-2,"tags");
+ if (next != NULL) {
+ lua_newtable(L);
+ while (next != NULL) {
+ lua_pushstring(L,make_tag_string(next->script));
+ lua_newtable(L);
+ dump_intfield(L, "default_baseline", (next->def_baseline+1)) ;
+ lua_newtable(L);
+ for ( i=0; i<Base->baseline_cnt; i++ ) {
+ lua_pushnumber(L, next->baseline_pos[i]) ;
+ lua_rawseti(L,-2, (i+1));
+ }
+ lua_setfield(L, -2, "baseline");
+ lua_newtable(L);
+ handle_baselangextent(L, next->langs);
+ lua_setfield(L, -2, "lang");
+ lua_rawset(L,-3);
+ next = next->next;
+ }
+ lua_setfield(L,-2,"scripts");
+ }
+}
+
+
+void
+handle_axismap (lua_State *L, struct axismap *am) {
+ int i;
+ lua_checkstack(L,3);
+ lua_newtable(L);
+ for (i=0;i<am->points;i++) {
+ lua_pushnumber(L, am->blends[i] ) ;
+ lua_rawseti(L,-2, (i+1));
+ }
+ lua_setfield(L,-2,"blends");
+ lua_newtable(L);
+ for (i=0;i<am->points;i++) {
+ lua_pushnumber(L, am->designs[i] ) ;
+ lua_rawseti(L,-2, (i+1));
+ }
+ lua_setfield(L,-2,"designs");
+ dump_realfield(L, "min", am->min) ;
+ dump_realfield(L, "def", am->def) ;
+ dump_realfield(L, "max", am->max) ;
+ if (am->axisnames != NULL ){
+ lua_newtable(L);
+ handle_macname(L, am->axisnames);
+ lua_setfield(L,-2,"axisnames");
+ }
+}
+
+
+void
+handle_mmset (lua_State *L, struct mmset *mm) {
+ int i, k;
+ lua_newtable(L);
+ for (i=0;i<mm->axis_count;i++) {
+ lua_pushstring(L, mm->axes[i]) ;
+ lua_rawseti(L,-2, (i+1));
+ }
+ lua_setfield(L,-2,"axes");
+
+ dump_intfield(L,"instance_count",mm->instance_count);
+ /* SplineFont *normal; */ /* this is the parent */
+ if (mm->instance_count>0) {
+ lua_newtable(L);
+ for (i=0;i<mm->instance_count*mm->axis_count;i++) {
+ lua_pushnumber(L, mm->positions[i]) ;
+ lua_rawseti(L,-2, (i+1));
+ }
+ lua_setfield(L,-2,"positions");
+
+ /* better not to do this */
+#if 0
+ {
+ struct mmset *mmsave ;
+ lua_newtable(L);
+ for (i=0;i<mm->instance_count;i++) {
+ lua_checkstack(L,20);
+ lua_createtable(L,0,60);
+ mmsave = mm->instances[i]->mm;
+ mm->instances[i]->mm = NULL;
+ handle_splinefont(L, mm->instances[i]);
+ mm->instances[i]->mm = mmsave;
+ lua_rawseti(L,-2, (i+1));
+ }
+ lua_setfield(L,-2,"instances");
+ }
+#endif
+
+ lua_newtable(L);
+ for (i=0;i<mm->instance_count;i++) {
+ lua_pushnumber(L, mm->defweights[i]) ;
+ lua_rawseti(L,-2, (i+1));
+ }
+ lua_setfield(L,-2,"defweights");
+ }
+
+ if (mm->axismaps != NULL) {
+ lua_newtable(L);
+ for (i=0;i<mm->axis_count;i++) {
+ lua_newtable(L);
+ handle_axismap(L, &(mm->axismaps[i]));
+ lua_rawseti(L, -2, (i+1));
+ }
+ lua_setfield(L,-2,"axismaps");
+ }
+ dump_stringfield(L,"cdv",mm->cdv);
+ dump_stringfield(L,"ndv",mm->ndv);
+ dump_intfield(L,"named_instance_count",mm->named_instance_count);
+
+ if (mm->named_instance_count>0) {
+ lua_newtable(L);
+ for (i=0; i<mm->named_instance_count;i++) {
+ struct named_instance *ni = &(mm->named_instances[i]);
+ lua_newtable(L);
+
+ lua_newtable(L);
+ for (k=0;k<=mm->axis_count;k++) {
+ lua_pushnumber(L,ni->coords[k]);
+ lua_rawseti(L,-2,(k+1));
+ }
+ lua_setfield(L,-2,"coords");
+
+ lua_newtable(L);
+ handle_macname(L, ni->names);
+ lua_setfield(L,-2,"names");
+
+ lua_rawseti(L,-2,(i+1));
+ }
+ lua_setfield(L,-2,"named_instances");
+ }
+ /* unsigned int changed: 1; */
+ dump_intfield(L,"apple",mm->apple);
+}
+
+
+
+void
+handle_splinefont(lua_State *L, struct splinefont *sf) {
+ int k;
+ int fix_notdef = 0;
+ int l = -1;
+
+ dump_stringfield(L,"table_version", LUA_OTF_VERSION);
+ dump_stringfield(L,"fontname", sf->fontname);
+ dump_stringfield(L,"fullname", sf->fullname);
+ dump_stringfield(L,"familyname", sf->familyname);
+ dump_stringfield(L,"weight", sf->weight);
+ dump_stringfield(L,"copyright", sf->copyright);
+ dump_stringfield(L,"filename", sf->filename);
+ /* dump_stringfield(L,"defbasefilename", sf->defbasefilename); */
+ dump_stringfield(L,"version", sf->version);
+ dump_floatfield (L,"italicangle", sf->italicangle);
+ dump_floatfield (L,"upos", sf->upos);
+ dump_floatfield (L,"uwidth", sf->uwidth);
+ dump_intfield (L,"ascent", sf->ascent);
+ dump_intfield (L,"descent", sf->descent);
+ dump_intfield (L,"uniqueid", sf->uniqueid);
+ dump_intfield (L,"glyphcnt", sf->glyphcnt);
+ dump_intfield (L,"glyphmax", sf->glyphmax);
+ dump_intfield (L,"units_per_em", sf->units_per_em);
+
+ if (sf->possub != NULL) {
+ lua_newtable(L);
+ handle_generic_fpst(L,sf->possub);
+ lua_setfield(L,-2,"lookups");
+ }
+
+ lua_checkstack(L,4);
+ lua_createtable(L,sf->glyphcnt,0);
+
+ /* This after-the-fact type discovery is not brilliant,
+ I should really add a 'format' key in the structure */
+ if ((sf->origname != NULL) &&
+ (strmatch(sf->origname+strlen(sf->origname)-4, ".pfa")==0 ||
+ strmatch(sf->origname+strlen(sf->origname)-4, ".pfb")==0)) {
+ fix_notdef = 1;
+ }
+
+ if (fix_notdef) {
+ /* some code to ensure that the .notdef ends up in slot 0
+ (this will actually be enforced by the CFF writer) */
+ for (k=0;k<sf->glyphcnt;k++) {
+ if (sf->glyphs[k]) {
+ if (strcmp(sf->glyphs[k]->name,".notdef") == 0) {
+ l = k;
+ }
+ }
+ }
+ if (l==-1) { /* fake a .notdef at the end */
+ l = sf->glyphcnt;
+ }
+ for (k=0;k<l;k++) {
+ lua_pushnumber(L,(k+1));
+ lua_createtable(L,0,12);
+ if (sf->glyphs[k]) {
+ handle_splinechar(L,sf->glyphs[k], sf->hasvmetrics);
+ }
+ lua_rawset(L,-3);
+ }
+ if (sf->glyphs != NULL && l<sf->glyphcnt) {
+ lua_pushnumber(L,0);
+ lua_createtable(L,0,12);
+ if (sf->glyphs[l]) {
+ handle_splinechar(L,sf->glyphs[l], sf->hasvmetrics);
+ }
+ lua_rawset(L,-3);
+ }
+ }
+ if ((l+1)<sf->glyphcnt) {
+ for (k=(l+1);k<sf->glyphcnt;k++) {
+ lua_pushnumber(L,k);
+ lua_createtable(L,0,12);
+ if (sf->glyphs[k]) {
+ handle_splinechar(L,sf->glyphs[k], sf->hasvmetrics);
+ }
+ lua_rawset(L,-3);
+ }
+ }
+ lua_setfield(L,-2,"glyphs");
+
+ /* dump_intfield(L,"changed", sf->changed); */
+ dump_intfield(L,"hasvmetrics", sf->hasvmetrics);
+ dump_intfield(L,"onlybitmaps", sf->onlybitmaps);
+ dump_intfield(L,"serifcheck", sf->serifcheck);
+ dump_intfield(L,"isserif", sf->isserif);
+ dump_intfield(L,"issans", sf->issans);
+ dump_intfield(L,"encodingchanged", sf->encodingchanged);
+ dump_intfield(L,"strokedfont", sf->strokedfont);
+ dump_intfield(L,"use_typo_metrics", sf->use_typo_metrics);
+ dump_intfield(L,"weight_width_slope_only", sf->weight_width_slope_only);
+ dump_intfield(L,"head_optimized_for_cleartype",sf->head_optimized_for_cleartype);
+
+ dump_enumfield(L,"uni_interp", (sf->uni_interp+1), uni_interp_enum);
+
+ if (sf->map != NULL ) {
+ lua_newtable(L);
+ handle_encmap(L,sf->map, l);
+ lua_setfield(L,-2,"map");
+ }
+
+ dump_stringfield(L,"origname", sf->origname); /* new */
+
+ if (sf->private != NULL) {
+ lua_newtable(L);
+ handle_psdict(L, sf->private);
+ lua_setfield(L,-2,"private");
+ }
+
+ dump_stringfield(L,"xuid", sf->xuid);
+
+ lua_createtable(L,0,40);
+ handle_pfminfo(L,sf->pfminfo);
+ lua_setfield(L,-2,"pfminfo");
+
+ if (sf->names != NULL) {
+ lua_newtable(L);
+ handle_ttflangname(L,sf->names);
+ lua_setfield(L,-2,"names");
+ }
+
+ lua_createtable(L,0,4);
+ dump_stringfield(L,"registry", sf->cidregistry);
+ dump_stringfield(L,"ordering", sf->ordering);
+ dump_intfield (L,"version", sf->cidversion);
+ dump_intfield (L,"supplement", sf->supplement);
+ lua_setfield(L,-2,"cidinfo");
+
+ /* SplineFont *cidmaster */ /* parent in a subfont */
+ if (sf->subfontcnt>0) {
+ lua_createtable(L,sf->subfontcnt,0);
+ for (k=0;k<sf->subfontcnt;k++) {
+ lua_checkstack(L,10);
+ lua_newtable(L);
+ handle_splinefont(L,sf->subfonts[k]);
+ lua_rawseti(L,-2,(k+1));
+ }
+ lua_setfield(L,-2,"subfonts");
+ }
+
+ dump_stringfield(L,"comments", sf->comments);
+ dump_stringfield(L,"fontlog", sf->fontlog);
+
+ if (sf->cvt_names != NULL) {
+ lua_newtable(L);
+ for (k=0; sf->cvt_names[k]!=END_CVT_NAMES; ++k) {
+ lua_pushstring(L, sf->cvt_names[k]);
+ lua_rawseti(L,-2,(k+1));
+ }
+ lua_setfield(L,-2,"cvt_names");
+ }
+
+ if (sf->ttf_tables != NULL) {
+ lua_newtable(L);
+ handle_ttf_table(L,sf->ttf_tables);
+ lua_setfield(L,-2,"ttf_tables");
+ }
+
+ if (sf->ttf_tab_saved != NULL) {
+ lua_newtable(L);
+ handle_ttf_table(L,sf->ttf_tab_saved);
+ lua_setfield(L,-2,"ttf_tab_saved");
+ }
+
+ if (sf->texdata.type != tex_unset) {
+ lua_newtable(L);
+ dump_enumfield(L,"type", sf->texdata.type, tex_type_enum);
+ lua_newtable(L);
+ for (k=0;k<22;k++) {
+ lua_pushnumber(L,k);
+ lua_pushnumber(L,sf->texdata.params[k]);
+ lua_rawset(L,-3);
+ }
+ lua_setfield(L,-2,"params");
+ lua_setfield(L,-2,"texdata");
+ }
+ if (sf->anchor != NULL) {
+ lua_newtable(L);
+ handle_anchorclass(L,sf->anchor);
+ lua_setfield(L,-2,"anchor_classes");
+ }
+ if (sf->kerns != NULL) {
+ lua_newtable(L);
+ handle_kernclass(L,sf->kerns);
+ lua_setfield(L,-2,"kerns");
+ }
+ if (sf->vkerns != NULL) {
+ lua_newtable(L);
+ handle_kernclass(L,sf->vkerns);
+ lua_setfield(L,-2,"vkerns");
+ }
+ if (sf->gsub_lookups != NULL) {
+ lua_newtable(L);
+ handle_lookup(L,sf->gsub_lookups);
+ lua_setfield(L,-2,"gsub");
+ }
+ if (sf->gpos_lookups != NULL) {
+ lua_newtable(L);
+ handle_lookup(L,sf->gpos_lookups);
+ lua_setfield(L,-2,"gpos");
+ }
+
+ if (sf->sm != NULL) {
+ lua_newtable(L);
+ handle_generic_asm(L,sf->sm);
+ lua_setfield(L,-2,"sm");
+ }
+ if (sf->features != NULL) {
+ lua_newtable(L);
+ handle_macfeat(L,sf->features);
+ lua_setfield(L,-2,"features");
+ }
+ if (sf->mm != NULL) {
+ lua_newtable(L);
+ handle_mmset (L,sf->mm);
+ lua_setfield(L,-2,"mm");
+ }
+ dump_stringfield(L,"chosenname", sf->chosenname);
+
+ dump_intfield(L,"macstyle", sf->macstyle);
+ dump_stringfield(L,"fondname", sf->fondname);
+
+ dump_intfield(L,"design_size", sf->design_size);
+ dump_intfield(L,"fontstyle_id", sf->fontstyle_id);
+
+ if (sf->fontstyle_name != NULL) {
+ lua_newtable(L);
+ handle_otfname(L,sf->fontstyle_name);
+ lua_setfield(L,-2,"fontstyle_name");
+ }
+
+ dump_intfield(L,"design_range_bottom",sf->design_range_bottom);
+ dump_intfield(L,"design_range_top", sf->design_range_top);
+ dump_floatfield(L,"strokewidth", sf->strokewidth);
+
+ if (sf->mark_class_cnt>0) {
+ lua_newtable(L);
+ for ( k=0; k<sf->mark_class_cnt; ++k ) {
+ lua_pushnumber(L,(k+1));
+ lua_pushstring(L,sf->mark_classes[k]);
+ lua_rawset(L,-3);
+ }
+ lua_setfield(L,-1,"mark_classes");
+
+ lua_newtable(L);
+ for ( k=0; k<sf->mark_class_cnt; ++k ) {
+ lua_pushnumber(L,(k+1));
+ lua_pushstring(L,sf->mark_class_names[k]);
+ lua_rawset(L,-3);
+ }
+ lua_setfield(L,-1,"mark_class_names");
+ }
+
+ dump_intfield(L,"creationtime", sf->creationtime);
+ dump_intfield(L,"modificationtime", sf->modificationtime);
+
+ dump_intfield(L,"os2_version", sf->os2_version);
+ dump_intfield(L,"sfd_version", sf->sfd_version);
+
+ if (sf->MATH != NULL) {
+ lua_newtable(L);
+ handle_MATH(L, sf->MATH);
+ lua_setfield(L,-2,"math");
+ }
+
+ if (sf->loadvalidation_state != 0) {
+ lua_newtable(L);
+ int val = 1;
+ int st = sf->loadvalidation_state;
+ if (st & lvs_bad_ps_fontname) {
+ lua_pushliteral(L, "bad_ps_fontname"); lua_rawseti(L,-2,val++);
+ }
+ if (st & lvs_bad_glyph_table) {
+ lua_pushliteral(L, "bad_glyph_table"); lua_rawseti(L,-2,val++);
+ }
+ if (st & lvs_bad_cff_table) {
+ lua_pushliteral(L, "bad_cff_table"); lua_rawseti(L,-2,val++);
+ }
+ if (st & lvs_bad_metrics_table) {
+ lua_pushliteral(L, "bad_metrics_table"); lua_rawseti(L,-2,val++);
+ }
+ if (st & lvs_bad_cmap_table) {
+ lua_pushliteral(L, "bad_cmap_table"); lua_rawseti(L,-2,val++);
+ }
+ if (st & lvs_bad_bitmaps_table) {
+ lua_pushliteral(L, "bad_bitmaps_table"); lua_rawseti(L,-2,val++);
+ }
+ if (st & lvs_bad_gx_table) {
+ lua_pushliteral(L, "bad_gx_table"); lua_rawseti(L,-2,val++);
+ }
+ if (st & lvs_bad_ot_table) {
+ lua_pushliteral(L, "bad_ot_table"); lua_rawseti(L,-2,val++);
+ }
+ if (st & lvs_bad_os2_version) {
+ lua_pushliteral(L, "bad_os2_version"); lua_rawseti(L,-2,val++);
+ }
+ if (st & lvs_bad_sfnt_header) {
+ lua_pushliteral(L, "bad_sfnt_header"); lua_rawseti(L,-2,val++);
+ }
+ lua_setfield(L,-2,"validation_state");
+ }
+
+ if (sf->horiz_base != NULL) {
+ lua_newtable(L);
+ handle_base(L, sf->horiz_base);
+ lua_setfield(L,-2,"horiz_base");
+ }
+ if (sf->vert_base != NULL) {
+ lua_newtable(L);
+ handle_base(L, sf->vert_base);
+ lua_setfield(L,-2,"vert_base");
+ }
+ dump_intfield(L,"extrema_bound", sf->extrema_bound);
+}
+
+int
+ff_make_table (lua_State *L) {
+ SplineFont *sf;
+ sf = *(check_isfont(L,1));
+ if (sf == NULL) {
+ lua_pushboolean(L,0);
+ } else {
+ lua_createtable(L,0,60);
+ handle_splinefont(L,sf);
+ }
+ return 1;
+}
+
+void do_ff_info (lua_State *L, SplineFont *sf) {
+ lua_newtable(L);
+ dump_stringfield(L,"familyname", sf->familyname);
+ dump_stringfield(L,"fontname", sf->fontname);
+ dump_stringfield(L,"fullname", sf->fullname);
+ dump_intfield (L,"italicangle", sf->italicangle);
+ dump_stringfield(L,"version", sf->version);
+ dump_stringfield(L,"weight", sf->weight);
+
+}
+
+static int
+ff_info (lua_State *L) {
+ SplineFont *sf;
+ FILE *l;
+ int i;
+ const char *fontname;
+ int openflags = 1;
+ fontname = luaL_checkstring(L,1);
+ if (!strlen(fontname)) {
+ lua_pushfstring(L,"font loading failed: empty string given\n", fontname);
+ lua_error(L);
+ return 1;
+ }
+ /* test fontname for existance */
+ if ((l = fopen(fontname,"r"))) {
+ fclose(l);
+ } else {
+ lua_pushfstring(L,"font loading failed for %s (read error)\n", fontname);
+ lua_error(L);
+ }
+ sf = ReadSplineFontInfo((char *)fontname,openflags);
+ if (sf==NULL) {
+ lua_pushfstring(L,"font loading failed for %s\n", fontname);
+ lua_error(L);
+ } else {
+ if (sf->next != NULL) {
+ SplineFont *sf_next;
+ i = 1;
+ lua_newtable(L);
+ while (sf) {
+ do_ff_info(L, sf);
+ lua_rawseti(L,-2,i);
+ i++;
+ sf_next = sf->next;
+ SplineFontFree(sf);
+ sf = sf_next;
+ }
+ } else {
+ do_ff_info(L, sf);
+ SplineFontFree(sf);
+ }
+ }
+ return 1;
+}
+
+static void ff_do_cff (SplineFont *sf, char *filename, unsigned char **buf, int *bufsiz) {
+ FILE *f;
+ int32 *bsizes = NULL;
+ int flags = ps_flag_nocffsugar + ps_flag_nohints;
+ EncMap *map;
+
+ map = EncMap1to1(sf->glyphcnt);
+
+ if(WriteTTFFont(filename, sf, ff_cff, bsizes, bf_none, flags, map, ly_fore)) {
+ /* success */
+ f = fopen(filename,"rb");
+ readbinfile(f , buf, bufsiz);
+ /*fprintf(stdout,"\n%s => CFF, size: %d\n", sf->filename, *bufsiz);*/
+ fclose(f);
+ return;
+ }
+ /* errors */
+ fprintf(stdout,"\n%s => CFF, failed\n", sf->filename);
+
+}
+
+/* exported for writecff.c */
+
+int ff_createcff (char *file, unsigned char **buf, int *bufsiz) {
+ SplineFont *sf;
+ int k ;
+ char s[] = "tempfile.cff";
+ int openflags = 1;
+ int notdefpos = 0;
+ sf = ReadSplineFont(file,openflags);
+ if (sf) {
+ /* this is not the best way. nicer to have no temp file at all */
+ ff_do_cff(sf, s, buf,bufsiz);
+ for (k=0;k<sf->glyphcnt;k++) {
+ if (sf->glyphs[k] && strcmp(sf->glyphs[k]->name,".notdef")==0) {
+ notdefpos=k;
+ break;
+ }
+ }
+ remove(s);
+ SplineFontFree(sf);
+ }
+ return notdefpos;
+}
+
+int ff_get_ttc_index(char *ffname, char*psname) {
+ SplineFont *sf;
+ int i = 0;
+ int openflags = 1;
+ int index = 0;
+
+ sf = ReadSplineFontInfo((char *)ffname,openflags);
+ if (sf==NULL) {
+ perror("font loading failed unexpectedly\n");
+ exit(EXIT_FAILURE);
+ }
+ while (sf != NULL) {
+ if (strcmp(sf->fontname,psname)==0) {
+ index = i;
+ break;
+ }
+ i++;
+ sf = sf->next;
+ }
+ return index;
+}
+
+static int warning_given = 0;
+
+static int
+ffold_info (lua_State *L) {
+ if (warning_given<5) {
+ fprintf (stderr, "Warning: The 'fontforge' table has been renamed to 'fontloader'.\n");
+ fprintf (stderr, " Please update your source file(s) accordingly.\n");
+ warning_given ++;
+ }
+ return ff_info(L);
+}
+
+static int
+ffold_open (lua_State *L) {
+ fprintf (stderr, "Warning: The 'fontforge' table has been renamed to 'fontloader'.\n");
+ fprintf (stderr, " Please update your source file(s) accordingly.\n");
+ return ff_open(L);
+}
+
+
+static struct luaL_reg fflib[] = {
+ {"open", ffold_open},
+ {"info", ffold_info},
+ {"close", ff_close},
+ {"apply_afmfile", ff_apply_afmfile},
+ {"apply_featurefile", ff_apply_featurefile},
+ {"to_table", ff_make_table},
+ {NULL, NULL}
+};
+
+static struct luaL_reg fllib[] = {
+ {"open", ff_open},
+ {"info", ff_info},
+ {"close", ff_close},
+ {"apply_afmfile", ff_apply_afmfile},
+ {"apply_featurefile", ff_apply_featurefile},
+ {"to_table", ff_make_table},
+ {NULL, NULL}
+};
+
+static const struct luaL_reg fflib_m [] = {
+ {"__gc", ff_close }, /* doesnt work yet! */
+ {NULL, NULL} /* sentinel */
+};
+
+extern char *SaveTablesPref;
+extern char *coord_sep ;
+
+int luaopen_ff (lua_State *L) {
+ InitSimpleStuff();
+ setlocale(LC_ALL,"C"); /* undo whatever InitSimpleStuff has caused */
+ coord_sep = ",";
+ FF_SetUiInterface(&luaui_interface);
+ default_encoding = FindOrMakeEncoding("ISO8859-1");
+ SaveTablesPref = "VORG,JSTF,acnt,bsln,fdsc,fmtx,hsty,just,trak,Zapf,LINO";
+ luaL_newmetatable(L,FONT_METATABLE);
+ luaL_register(L, NULL, fflib_m);
+ luaL_openlib(L, "fontforge", fflib, 0);
+ luaL_openlib(L, "fontloader", fllib, 0);
+ return 1;
+}
+