trfn: include adobe glyph list inside mkfn binary
[neatmkfn.git] / trfn.c
blob5bfe859404c9f21153ae38940fbcdc6e3d483203
1 #include <ctype.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include "sbuf.h"
6 #include "tab.h"
7 #include "trfn.h"
8 #include "trfn_agl.h"
9 #include "trfn_ch.h"
11 #define WX(w) (((w) < 0 ? (w) - trfn_div / 2 : (w) + trfn_div / 2) / trfn_div)
12 #define LEN(a) ((sizeof(a) / sizeof((a)[0])))
13 #define HEXDIGS "0123456789abcdef"
14 #define NCHAR 8 /* number of characters per glyph */
15 #define GNLEN 64 /* glyph name length */
16 #define AGLLEN 8192 /* adobe glyphlist length */
18 static struct sbuf sbuf_char; /* characters */
19 static struct sbuf sbuf_kern; /* kerning pairs */
20 static int trfn_div; /* divisor of widths */
21 static int trfn_swid; /* space width */
22 static int trfn_special; /* special flag */
23 static int trfn_kmin; /* minimum kerning value */
24 static int trfn_bbox; /* include bounding box */
25 static char trfn_ligs[8192]; /* font ligatures */
26 static char trfn_trname[256]; /* font troff name */
27 static char trfn_psname[256]; /* font ps name */
28 /* character type */
29 static int trfn_asc; /* minimum height of glyphs with ascender */
30 static int trfn_desc; /* minimum depth of glyphs with descender */
32 /* lookup tables */
33 static struct tab *tab_agl; /* adobe glyph list table */
34 static struct tab *tab_alts; /* character aliases table */
36 static int utf8len(int c)
38 if (c > 0 && c <= 0x7f)
39 return 1;
40 if (c >= 0xfc)
41 return 6;
42 if (c >= 0xf8)
43 return 5;
44 if (c >= 0xf0)
45 return 4;
46 if (c >= 0xe0)
47 return 3;
48 if (c >= 0xc0)
49 return 2;
50 return c != 0;
53 static int utf8get(char **src)
55 int result;
56 int l = 1;
57 char *s = *src;
58 if (~((unsigned char) **src) & 0xc0)
59 return (unsigned char) *(*src)++;
60 while (l < 6 && (unsigned char) *s & (0x40 >> l))
61 l++;
62 result = (0x3f >> l) & (unsigned char) *s++;
63 while (l--)
64 result = (result << 6) | ((unsigned char) *s++ & 0x3f);
65 *src = s;
66 return result;
69 static void utf8put(char **d, int c)
71 int l;
72 if (c > 0xffff) {
73 *(*d)++ = 0xf0 | (c >> 18);
74 l = 3;
75 } else if (c > 0x7ff) {
76 *(*d)++ = 0xe0 | (c >> 12);
77 l = 2;
78 } else if (c > 0x7f) {
79 *(*d)++ = 0xc0 | (c >> 6);
80 l = 1;
81 } else {
82 *(*d)++ = c > 0 ? c : ' ';
83 l = 0;
85 while (l--)
86 *(*d)++ = 0x80 | ((c >> (l * 6)) & 0x3f);
87 **d = '\0';
90 static int hexval(char *s, int len)
92 char *digs = HEXDIGS;
93 int n = 0;
94 int i;
95 for (i = 0; i < len; i++) {
96 if (s[i] && strchr(digs, tolower(s[i])))
97 n = n * 16 + (strchr(digs, tolower(s[i])) - digs);
98 else
99 break;
101 return len == 1 ? n << 4 : n;
104 static int agl_map(char *d, char *s)
106 char *u = tab_get(tab_agl, s); /* unicode code point like "FB8E" */
107 if (!u)
108 return 1;
109 while (u && *u) {
110 while (*u == ' ')
111 u++;
112 utf8put(&d, hexval(u, 6));
113 u = strchr(u, ' ');
115 *d = '\0';
116 return 0;
119 static int achar_map(char *name)
121 int i;
122 for (i = 0; i < LEN(achars); i++) {
123 struct achar *a = &achars[i];
124 if (!strncmp(a->name, name, strlen(a->name))) {
125 char *postfix = name + strlen(a->name);
126 if (!*postfix)
127 return a->c;
128 if (!strcmp("isolated", postfix))
129 return a->s ? a->s : a->c;
130 if (!strcmp("initial", postfix))
131 return a->i ? a->i : a->c;
132 if (!strcmp("medial", postfix))
133 return a->m ? a->m : a->c;
134 if (!strcmp("final", postfix))
135 return a->f ? a->f : a->c;
138 return 0;
141 static int achar_shape(int c, int pjoin, int njoin)
143 int i;
144 for (i = 0; i < LEN(achars); i++) {
145 struct achar *a = &achars[i];
146 if (a->c == c) {
147 if (!pjoin && !njoin)
148 return a->c;
149 if (!pjoin && njoin)
150 return a->i ? a->i : a->c;
151 if (pjoin && njoin)
152 return a->m ? a->m : a->c;
153 if (pjoin && !njoin)
154 return a->f ? a->f : a->c;
157 return c;
160 static void ashape(char *str, char *ext)
162 int s[NCHAR];
163 char *src = str;
164 int i, l;
165 int bjoin = !strcmp(".medi", ext) || !strcmp(".fina", ext);
166 int ejoin = !strcmp(".medi", ext) || !strcmp(".init", ext);
167 for (l = 0; l < NCHAR && *src; l++)
168 s[l] = utf8get(&src);
169 for (i = 0; i < l; i++)
170 s[i] = achar_shape(s[i], i > 0 || bjoin, i < l - 1 || ejoin);
171 for (i = 0; i < l; i++)
172 utf8put(&str, s[i]);
175 /* find the utf-8 name of src with the given unicode codepoint */
176 static int trfn_name(char *dst, char *src, int codepoint)
178 char ch[GNLEN];
179 char *d = dst;
180 char *s;
181 int i;
182 if (codepoint) {
183 utf8put(&dst, codepoint);
184 return 0;
186 if (!src || src[0] == '.')
187 return 1;
188 while (*src && *src != '.') {
189 s = ch;
190 if (src[0] == '_')
191 src++;
192 while (*src && *src != '_' && *src != '.')
193 *s++ = *src++;
194 *s = '\0';
195 if (!agl_map(d, ch)) {
196 for (i = 0; i < LEN(agl_exceptions); i++) {
197 if (!strcmp(agl_exceptions[i][0], d)) {
198 strcpy(d, agl_exceptions[i][1]);
199 break;
202 d = strchr(d, '\0');
203 } else if (ch[0] == 'u' && ch[1] == 'n' && ch[2] == 'i') {
204 for (i = 0; strlen(ch + 3 + 4 * i) >= 4; i++)
205 utf8put(&d, hexval(ch + 3 + 4 * i, 4));
206 } else if (ch[0] == 'u' && ch[1] && strchr(HEXDIGS, tolower(ch[1]))) {
207 utf8put(&d, hexval(ch + 1, 6));
208 } else if (achar_map(ch)) {
209 utf8put(&d, achar_map(ch));
210 } else {
211 return 1;
214 ashape(dst, src);
215 return *src && strcmp(src, ".medi") && strcmp(src, ".fina") &&
216 strcmp(src, ".init") && strcmp(src, ".isol");
219 static void trfn_lig(char *c)
221 int i;
222 for (i = 0; i < LEN(ligs_exceptions); i++)
223 if (!strcmp(ligs_exceptions[i], c))
224 return;
225 if (c[0] && c[1] && strlen(c) > utf8len((unsigned char) c[0])) {
226 sprintf(strchr(trfn_ligs, '\0'), "%s ", c);
227 } else {
228 for (i = 0; i < LEN(ligs_utf8); i++)
229 if (!strcmp(ligs_utf8[i][0], c))
230 sprintf(strchr(trfn_ligs, '\0'),
231 "%s ", ligs_utf8[i][1]);
235 static int trfn_type(char *s, int lly, int ury)
237 int typ = 0;
238 int c = !s[0] || s[1] ? 0 : (unsigned char) *s;
239 if (c == 't' && !trfn_asc)
240 trfn_asc = ury;
241 if ((c == 'g' || c == 'j' || c == 'p' || c == 'q' || c == 'y') &&
242 (!trfn_desc || trfn_desc < lly))
243 trfn_desc = lly;
244 if (!trfn_desc || !trfn_asc) {
245 if (c > 0 && c < 128)
246 return ctype_ascii[c];
247 return 3;
249 if (!trfn_desc || lly <= trfn_desc)
250 typ |= 1;
251 if (!trfn_asc || ury >= trfn_asc)
252 typ |= 2;
253 return typ;
256 /* n is the position and u is the unicode codepoint */
257 void trfn_char(char *psname, int n, int u, int wid,
258 int llx, int lly, int urx, int ury)
260 char uc[GNLEN]; /* mapping unicode character */
261 char **a_tr; /* troff character names */
262 char pos[GNLEN] = ""; /* postscript character position/name */
263 int typ; /* character type */
264 /* initializing character attributes */
265 if (trfn_name(uc, psname, u))
266 strcpy(uc, "---");
267 if (n >= 0 && n < 256)
268 sprintf(pos, "%d", n);
269 if (n < 0 && !uc[1] && uc[0] >= 32 && uc[0] <= 125)
270 if (!strchr(psname, '.'))
271 sprintf(pos, "%d", uc[0]);
272 typ = trfn_type(!strchr(psname, '.') ? uc : "", lly, ury);
273 /* printing troff charset */
274 if (strchr(uc, ' ')) { /* space not allowed in char names */
275 if (!trfn_swid && !strcmp(" ", uc))
276 trfn_swid = WX(wid);
277 return;
279 if (strcmp("---", uc))
280 trfn_lig(uc);
281 sbuf_printf(&sbuf_char, "char %s\t%d", uc, WX(wid));
282 if (trfn_bbox && (llx || lly || urx || ury))
283 sbuf_printf(&sbuf_char, ",%d,%d,%d,%d",
284 WX(llx), WX(lly), WX(urx), WX(ury));
285 sbuf_printf(&sbuf_char, "\t%d\t%s\t%s\n", typ, psname, pos);
286 a_tr = tab_get(tab_alts, uc);
287 while (a_tr && *a_tr)
288 sbuf_printf(&sbuf_char, "char %s\t\"\n", *a_tr++);
291 void trfn_kern(char *c1, char *c2, int x)
293 if (WX(x) && abs(WX(x)) >= trfn_kmin)
294 sbuf_printf(&sbuf_kern, "kern %s\t%s\t%d\n", c1, c2, WX(x));
297 void trfn_trfont(char *name)
299 if (!trfn_trname[0])
300 strcpy(trfn_trname, name);
303 void trfn_psfont(char *name)
305 if (!trfn_psname[0])
306 strcpy(trfn_psname, name);
309 void trfn_print(void)
311 if (trfn_trname[0])
312 printf("name %s\n", trfn_trname);
313 if (trfn_psname[0])
314 printf("fontname %s\n", trfn_psname);
315 printf("spacewidth %d\n", trfn_swid);
316 printf("ligatures %s0\n", trfn_ligs);
317 if (trfn_special)
318 printf("special\n");
319 printf("%s", sbuf_buf(&sbuf_char));
320 printf("%s", sbuf_buf(&sbuf_kern));
323 void trfn_init(int res, int spc, int kmin, int bbox)
325 int i;
326 trfn_div = 7200 / res;
327 trfn_special = spc;
328 trfn_kmin = kmin;
329 trfn_bbox = bbox;
330 sbuf_init(&sbuf_char);
331 sbuf_init(&sbuf_kern);
332 tab_agl = tab_alloc(LEN(agl));
333 for (i = 0; i < LEN(agl); i++)
334 tab_put(tab_agl, agl[i][0], agl[i][1]);
335 tab_alts = tab_alloc(LEN(alts));
336 for (i = 0; i < LEN(alts); i++)
337 tab_put(tab_alts, alts[i][0], alts[i] + 1);
340 void trfn_done(void)
342 sbuf_done(&sbuf_char);
343 sbuf_done(&sbuf_kern);
344 tab_free(tab_alts);
345 if (tab_agl)
346 tab_free(tab_agl);