add glyphlist.txt
[neatmkfn.git] / trfn.c
blob8d23e77c0870da94e8629e6e41e2f1b040744aba
1 #include <ctype.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include "sbuf.h"
6 #include "tab.h"
7 #include "trfn.h"
8 #include "trfn_ch.h"
10 #define WX(w) (((w) < 0 ? (w) - trfn_div / 2 : (w) + trfn_div / 2) / trfn_div)
11 #define LEN(a) ((sizeof(a) / sizeof((a)[0])))
12 #define HEXDIGS "0123456789abcdef"
13 #define GNLEN 32
14 #define AGLLEN (8 * 1024)
16 static struct sbuf sbuf_char; /* charset section */
17 static struct sbuf sbuf_kern; /* kernpairs section */
18 static int trfn_div; /* divisor of widths */
19 static int trfn_swid; /* space width */
20 static int trfn_special; /* special flag */
21 static char trfn_ligs[1024]; /* font ligatures */
22 static char trfn_trname[256]; /* font troff name */
23 static char trfn_psname[256]; /* font ps name */
25 /* adobe glyphlist mapping */
26 static char agl_key[AGLLEN][GNLEN];
27 static char agl_val[AGLLEN][GNLEN];
28 static int agl_n;
30 /* lookup tables */
31 static struct tab *tab_agl;
32 static struct tab *tab_alts;
33 static struct tab *tab_ctyp;
35 static void pututf8(char **d, int c)
37 int l;
38 if (c > 0xffff) {
39 *(*d)++ = 0xf0 | (c >> 18);
40 l = 3;
41 } else if (c > 0x7ff) {
42 *(*d)++ = 0xe0 | (c >> 12);
43 l = 2;
44 } else if (c > 0x7f) {
45 *(*d)++ = 0xc0 | (c >> 6);
46 l = 1;
47 } else {
48 *(*d)++ = c > 0 ? c : ' ';
49 l = 0;
51 while (l--)
52 *(*d)++ = 0x80 | ((c >> (l * 6)) & 0x3f);
53 **d = '\0';
56 static int hexval(char *s, int len)
58 char *digs = HEXDIGS;
59 int n = 0;
60 int i;
61 for (i = 0; i < len; i++) {
62 if (s[i] && strchr(digs, tolower(s[i])))
63 n = n * 16 + (strchr(digs, tolower(s[i])) - digs);
64 else
65 break;
67 return len == 1 ? n << 4 : n;
70 static int agl_read(char *path)
72 FILE *fin = fopen(path, "r");
73 char ln[GNLEN * 8];
74 char val[GNLEN];
75 char *s, *d;
76 int i;
77 if (!fin)
78 return 1;
79 while (fgets(ln, sizeof(ln), fin)) {
80 s = strchr(ln, ';');
81 if (ln[0] == '#' || !s)
82 continue;
83 *s++ = '\0';
84 d = val;
85 while (s && *s) {
86 while (*s == ' ')
87 s++;
88 pututf8(&d, hexval(s, 6));
89 s = strchr(s, ' ');
91 *d = '\0';
92 strcpy(agl_key[agl_n], ln);
93 strcpy(agl_val[agl_n], val);
94 agl_n++;
96 fclose(fin);
97 tab_agl = tab_alloc(agl_n);
98 for (i = 0; i < agl_n; i++)
99 tab_put(tab_agl, agl_key[i], agl_val[i]);
100 return 0;
103 static char *agl_map(char *s)
105 return tab_get(tab_agl, s);
108 static int achar_map(char *name)
110 int i;
111 for (i = 0; i < LEN(achars); i++) {
112 struct achar *a = &achars[i];
113 if (!strncmp(a->name, name, strlen(a->name))) {
114 char *postfix = name + strlen(a->name);
115 if (!*postfix)
116 return a->c;
117 if (!strcmp("isolated", postfix))
118 return a->s ? a->s : a->c;
119 if (!strcmp("initial", postfix))
120 return a->i ? a->i : a->c;
121 if (!strcmp("medial", postfix))
122 return a->m ? a->m : a->c;
123 if (!strcmp("final", postfix))
124 return a->f ? a->f : a->c;
127 return 0;
130 static int trfn_name(char *dst, char *src)
132 char ch[GNLEN];
133 char *s;
134 int i;
135 if (src[0] == '.')
136 return 1;
137 if (src[1] && strchr(src, '.'))
138 return 1; /* ignore opentype features for now */
139 while (*src && *src != '.') {
140 s = ch;
141 if (src[0] == '_')
142 src++;
143 while (*src && *src != '_' && *src != '.')
144 *s++ = *src++;
145 *s = '\0';
146 if (agl_map(ch)) {
147 strcpy(dst, agl_map(ch));
148 for (i = 0; i < LEN(agl_exceptions); i++)
149 if (!strcmp(agl_exceptions[i][0], dst))
150 strcpy(dst, agl_exceptions[i][1]);
151 dst = strchr(dst, '\0');
152 } else if (ch[0] == 'u' && ch[1] == 'n' && ch[2] == 'i') {
153 for (i = 0; strlen(ch + 3 + 4 * i) >= 4; i++)
154 pututf8(&dst, hexval(ch + 3 + 4 * i, 4));
155 } else if (ch[0] == 'u' && ch[1] && strchr(HEXDIGS, tolower(ch[1]))) {
156 pututf8(&dst, hexval(ch + 1, 6));
157 } else if (achar_map(ch)) {
158 pututf8(&dst, achar_map(ch));
159 } else {
160 return 1;
163 return src[0];
166 static void trfn_lig(char *c)
168 int i;
169 for (i = 0; i < LEN(ligs); i++)
170 if (!strcmp(ligs[i], c))
171 sprintf(strchr(trfn_ligs, '\0'), "%s ", c);
174 static int trfn_type(char *c)
176 struct ctype *t = tab_get(tab_ctyp, c);
177 return t ? t->type : 3;
180 void trfn_char(char *c, char *n, int wid, int typ)
182 char uc[GNLEN];
183 char pos[GNLEN];
184 char **a;
185 if (trfn_name(uc, c))
186 strcpy(uc, "---");
187 if (strchr(uc, ' ')) { /* space not allowed in character names */
188 if (!trfn_swid && !strcmp(" ", uc))
189 trfn_swid = WX(wid);
190 return;
192 trfn_lig(uc);
193 if (typ < 0)
194 typ = trfn_type(uc);
195 strcpy(pos, c);
196 if (n && atoi(n) >= 0 && atoi(n) < 256)
197 strcpy(pos, n);
198 if (!n && !uc[1] && uc[0] >= 32 && uc[0] <= 125)
199 sprintf(pos, "%d", uc[0]);
200 sbuf_printf(&sbuf_char, "%s\t%d\t%d\t%s\n", uc, WX(wid), typ, pos);
201 a = tab_get(tab_alts, uc);
202 while (a && *a)
203 sbuf_printf(&sbuf_char, "%s\t\"\n", *a++);
206 void trfn_kern(char *c1, char *c2, int x)
208 char g1[GNLEN], g2[GNLEN];
209 if (!trfn_name(g1, c1) && !trfn_name(g2, c2) && abs(WX(x)) > WX(20))
210 if (!strchr(g1, ' ') && !strchr(g2, ' '))
211 sbuf_printf(&sbuf_kern, "%s\t%s\t%d\n", g1, g2, WX(x));
214 void trfn_trfont(char *name)
216 if (!trfn_trname[0])
217 strcpy(trfn_trname, name);
220 void trfn_psfont(char *name)
222 if (!trfn_psname[0])
223 strcpy(trfn_psname, name);
226 void trfn_print(void)
228 if (trfn_trname[0])
229 printf("name %s\n", trfn_trname);
230 if (trfn_psname[0])
231 printf("fontname %s\n", trfn_psname);
232 printf("spacewidth %d\n", trfn_swid);
233 printf("ligatures %s 0\n", trfn_ligs);
234 if (trfn_special)
235 printf("special\n");
236 printf("charset\n");
237 printf("%s", sbuf_buf(&sbuf_char));
238 printf("kernpairs\n");
239 printf("%s", sbuf_buf(&sbuf_kern));
242 void trfn_init(int res, int spc)
244 int i;
245 trfn_div = 7200 / res;
246 trfn_special = spc;
247 if (agl_read("glyphlist.txt"))
248 fprintf(stderr, "mktrfn: could not open glyphlist.txt\n");
249 sbuf_init(&sbuf_char);
250 sbuf_init(&sbuf_kern);
251 tab_alts = tab_alloc(LEN(alts));
252 tab_ctyp = tab_alloc(LEN(ctype));
253 for (i = 0; i < LEN(alts); i++)
254 tab_put(tab_alts, alts[i][0], alts[i] + 1);
255 for (i = 0; i < LEN(ctype); i++)
256 tab_put(tab_ctyp, ctype[i].ch, &ctype[i]);
259 void trfn_done(void)
261 sbuf_done(&sbuf_char);
262 sbuf_done(&sbuf_kern);
263 tab_free(tab_alts);
264 tab_free(tab_ctyp);
265 if (tab_agl)
266 tab_free(tab_agl);