ref: 389b96d68669a44851fb55a4a6969244ac8aed34
dir: /trfn.c/
#include <ctype.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include "sbuf.h" #include "tab.h" #include "trfn.h" #include "trfn_ch.h" #define WX(w) (((w) < 0 ? (w) - trfn_div / 2 : (w) + trfn_div / 2) / trfn_div) #define LEN(a) ((sizeof(a) / sizeof((a)[0]))) #define HEXDIGS "0123456789abcdef" #define GNLEN 32 #define AGLLEN (8 * 1024) static struct sbuf sbuf_char; /* charset section */ static struct sbuf sbuf_kern; /* kernpairs section */ static int trfn_div; /* divisor of widths */ static int trfn_swid; /* space width */ static int trfn_special; /* special flag */ static char trfn_ligs[1024]; /* font ligatures */ static char trfn_trname[256]; /* font troff name */ static char trfn_psname[256]; /* font ps name */ /* adobe glyphlist mapping */ static char agl_key[AGLLEN][GNLEN]; static char agl_val[AGLLEN][GNLEN]; static int agl_n; /* lookup tables */ static struct tab *tab_agl; static struct tab *tab_alts; static struct tab *tab_ctyp; static void pututf8(char **d, int c) { int l; if (c > 0xffff) { *(*d)++ = 0xf0 | (c >> 18); l = 3; } else if (c > 0x7ff) { *(*d)++ = 0xe0 | (c >> 12); l = 2; } else if (c > 0x7f) { *(*d)++ = 0xc0 | (c >> 6); l = 1; } else { *(*d)++ = c > 0 ? c : ' '; l = 0; } while (l--) *(*d)++ = 0x80 | ((c >> (l * 6)) & 0x3f); **d = '\0'; } static int hexval(char *s, int len) { char *digs = HEXDIGS; int n = 0; int i; for (i = 0; i < len; i++) { if (s[i] && strchr(digs, tolower(s[i]))) n = n * 16 + (strchr(digs, tolower(s[i])) - digs); else break; } return len == 1 ? n << 4 : n; } static int agl_read(char *path) { FILE *fin = fopen(path, "r"); char ln[GNLEN * 8]; char val[GNLEN]; char *s, *d; int i; if (!fin) return 1; while (fgets(ln, sizeof(ln), fin)) { s = strchr(ln, ';'); if (ln[0] == '#' || !s) continue; *s++ = '\0'; d = val; while (s && *s) { while (*s == ' ') s++; pututf8(&d, hexval(s, 6)); s = strchr(s, ' '); } *d = '\0'; strcpy(agl_key[agl_n], ln); strcpy(agl_val[agl_n], val); agl_n++; } fclose(fin); tab_agl = tab_alloc(agl_n); for (i = 0; i < agl_n; i++) tab_put(tab_agl, agl_key[i], agl_val[i]); return 0; } static char *agl_map(char *s) { return tab_get(tab_agl, s); } static int achar_map(char *name) { int i; for (i = 0; i < LEN(achars); i++) { struct achar *a = &achars[i]; if (!strncmp(a->name, name, strlen(a->name))) { char *postfix = name + strlen(a->name); if (!*postfix) return a->c; if (!strcmp("isolated", postfix)) return a->s ? a->s : a->c; if (!strcmp("initial", postfix)) return a->i ? a->i : a->c; if (!strcmp("medial", postfix)) return a->m ? a->m : a->c; if (!strcmp("final", postfix)) return a->f ? a->f : a->c; } } return 0; } static int trfn_name(char *dst, char *src) { char ch[GNLEN]; char *s; int i; if (src[0] == '.') return 1; if (src[1] && strchr(src, '.')) return 1; /* ignore opentype features for now */ while (*src && *src != '.') { s = ch; if (src[0] == '_') src++; while (*src && *src != '_' && *src != '.') *s++ = *src++; *s = '\0'; if (agl_map(ch)) { strcpy(dst, agl_map(ch)); for (i = 0; i < LEN(agl_exceptions); i++) if (!strcmp(agl_exceptions[i][0], dst)) strcpy(dst, agl_exceptions[i][1]); dst = strchr(dst, '\0'); } else if (ch[0] == 'u' && ch[1] == 'n' && ch[2] == 'i') { for (i = 0; strlen(ch + 3 + 4 * i) >= 4; i++) pututf8(&dst, hexval(ch + 3 + 4 * i, 4)); } else if (ch[0] == 'u' && ch[1] && strchr(HEXDIGS, tolower(ch[1]))) { pututf8(&dst, hexval(ch + 1, 6)); } else if (achar_map(ch)) { pututf8(&dst, achar_map(ch)); } else { return 1; } } return src[0]; } static void trfn_lig(char *c) { int i; for (i = 0; i < LEN(ligs); i++) if (!strcmp(ligs[i], c)) sprintf(strchr(trfn_ligs, '\0'), "%s ", c); } static int trfn_type(char *c) { struct ctype *t = tab_get(tab_ctyp, c); return t ? t->type : 3; } void trfn_char(char *c, char *n, int wid, int typ) { char uc[GNLEN]; char pos[GNLEN]; char **a; if (trfn_name(uc, c)) strcpy(uc, "---"); if (strchr(uc, ' ')) { /* space not allowed in character names */ if (!trfn_swid && !strcmp(" ", uc)) trfn_swid = WX(wid); return; } trfn_lig(uc); if (typ < 0) typ = trfn_type(uc); strcpy(pos, c); if (n && atoi(n) >= 0 && atoi(n) < 256) strcpy(pos, n); if (!n && !uc[1] && uc[0] >= 32 && uc[0] <= 125) sprintf(pos, "%d", uc[0]); sbuf_printf(&sbuf_char, "%s\t%d\t%d\t%s\n", uc, WX(wid), typ, pos); a = tab_get(tab_alts, uc); while (a && *a) sbuf_printf(&sbuf_char, "%s\t\"\n", *a++); } void trfn_kern(char *c1, char *c2, int x) { char g1[GNLEN], g2[GNLEN]; if (!trfn_name(g1, c1) && !trfn_name(g2, c2) && abs(WX(x)) > WX(20)) if (!strchr(g1, ' ') && !strchr(g2, ' ')) sbuf_printf(&sbuf_kern, "%s\t%s\t%d\n", g1, g2, WX(x)); } void trfn_trfont(char *name) { if (!trfn_trname[0]) strcpy(trfn_trname, name); } void trfn_psfont(char *name) { if (!trfn_psname[0]) strcpy(trfn_psname, name); } void trfn_print(void) { if (trfn_trname[0]) printf("name %s\n", trfn_trname); if (trfn_psname[0]) printf("fontname %s\n", trfn_psname); printf("spacewidth %d\n", trfn_swid); printf("ligatures %s 0\n", trfn_ligs); if (trfn_special) printf("special\n"); printf("charset\n"); printf("%s", sbuf_buf(&sbuf_char)); printf("kernpairs\n"); printf("%s", sbuf_buf(&sbuf_kern)); } void trfn_init(int res, int spc) { int i; trfn_div = 7200 / res; trfn_special = spc; agl_read("glyphlist.txt"); sbuf_init(&sbuf_char); sbuf_init(&sbuf_kern); tab_alts = tab_alloc(LEN(alts)); tab_ctyp = tab_alloc(LEN(ctype)); for (i = 0; i < LEN(alts); i++) tab_put(tab_alts, alts[i][0], alts[i] + 1); for (i = 0; i < LEN(ctype); i++) tab_put(tab_ctyp, ctype[i].ch, &ctype[i]); } void trfn_done(void) { sbuf_done(&sbuf_char); sbuf_done(&sbuf_kern); tab_free(tab_alts); tab_free(tab_ctyp); if (tab_agl) tab_free(tab_agl); }