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"
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 char trfn_ligs
[1024]; /* font ligatures */
21 static char trfn_trname
[256]; /* font troff name */
22 static char trfn_psname
[256]; /* font ps name */
24 /* adobe glyphlist mapping */
25 static char agl_key
[AGLLEN
][GNLEN
];
26 static char agl_val
[AGLLEN
][GNLEN
];
30 static struct tab
*tab_agl
;
31 static struct tab
*tab_alts
;
32 static struct tab
*tab_ctyp
;
34 static void pututf8(char **d
, int c
)
38 *(*d
)++ = 0xf0 | (c
>> 18);
40 } else if (c
> 0x7ff) {
41 *(*d
)++ = 0xe0 | (c
>> 12);
43 } else if (c
> 0x7f) {
44 *(*d
)++ = 0xc0 | (c
>> 6);
47 *(*d
)++ = c
> 0 ? c
: ' ';
51 *(*d
)++ = 0x80 | ((c
>> (l
* 6)) & 0x3f);
55 static int hexval(char *s
, int len
)
60 for (i
= 0; i
< len
; i
++) {
61 if (s
[i
] && strchr(digs
, tolower(s
[i
])))
62 n
= n
* 16 + (strchr(digs
, tolower(s
[i
])) - digs
);
66 return len
== 1 ? n
<< 4 : n
;
69 static int agl_read(char *path
)
71 FILE *fin
= fopen(path
, "r");
78 while (fgets(ln
, sizeof(ln
), fin
)) {
80 if (ln
[0] == '#' || !s
)
87 pututf8(&d
, hexval(s
, 6));
91 strcpy(agl_key
[agl_n
], ln
);
92 strcpy(agl_val
[agl_n
], val
);
96 tab_agl
= tab_alloc(agl_n
);
97 for (i
= 0; i
< agl_n
; i
++)
98 tab_put(tab_agl
, agl_key
[i
], agl_val
[i
]);
102 static char *agl_map(char *s
)
104 return tab_get(tab_agl
, s
);
107 static int achar_map(char *name
)
110 for (i
= 0; i
< LEN(achars
); i
++) {
111 struct achar
*a
= &achars
[i
];
112 if (!strncmp(a
->name
, name
, strlen(a
->name
))) {
113 char *postfix
= name
+ strlen(a
->name
);
116 if (!strcmp("isolated", postfix
))
117 return a
->s
? a
->s
: a
->c
;
118 if (!strcmp("initial", postfix
))
119 return a
->i
? a
->i
: a
->c
;
120 if (!strcmp("medial", postfix
))
121 return a
->m
? a
->m
: a
->c
;
122 if (!strcmp("final", postfix
))
123 return a
->f
? a
->f
: a
->c
;
129 static int trfn_name(char *dst
, char *src
)
136 if (src
[1] && strchr(src
, '.'))
137 return 1; /* ignore opentype features for now */
138 while (*src
&& *src
!= '.') {
142 while (*src
&& *src
!= '_' && *src
!= '.')
146 strcpy(dst
, agl_map(ch
));
147 for (i
= 0; i
< LEN(agl_exceptions
); i
++)
148 if (!strcmp(agl_exceptions
[i
][0], dst
))
149 strcpy(dst
, agl_exceptions
[i
][1]);
150 dst
= strchr(dst
, '\0');
151 } else if (ch
[0] == 'u' && ch
[1] == 'n' && ch
[2] == 'i') {
152 for (i
= 0; strlen(ch
+ 3 + 4 * i
) >= 4; i
++)
153 pututf8(&dst
, hexval(ch
+ 3 + 4 * i
, 4));
154 } else if (ch
[0] == 'u' && ch
[1] && strchr(HEXDIGS
, tolower(ch
[1]))) {
155 pututf8(&dst
, hexval(ch
+ 1, 6));
156 } else if (achar_map(ch
)) {
157 pututf8(&dst
, achar_map(ch
));
165 static void trfn_lig(char *c
)
168 for (i
= 0; i
< LEN(ligs
); i
++)
169 if (!strcmp(ligs
[i
], c
))
170 sprintf(strchr(trfn_ligs
, '\0'), "%s ", c
);
173 static int trfn_type(char *c
)
175 struct ctype
*t
= tab_get(tab_ctyp
, c
);
176 return t
? t
->type
: 3;
179 void trfn_char(char *c
, char *n
, int wid
, int typ
)
184 if (trfn_name(uc
, c
))
186 if (strchr(uc
, ' ')) { /* space not allowed in character names */
187 if (!trfn_swid
&& !strcmp(" ", uc
))
195 if (n
&& atoi(n
) >= 0 && atoi(n
) < 256)
197 if (!n
&& !uc
[1] && uc
[0] >= 32 && uc
[0] <= 125)
198 sprintf(pos
, "%d", uc
[0]);
199 sbuf_printf(&sbuf_char
, "%s\t%d\t%d\t%s\n", uc
, WX(wid
), typ
, pos
);
200 a
= tab_get(tab_alts
, uc
);
202 sbuf_printf(&sbuf_char
, "%s\t\"\n", *a
++);
205 void trfn_kern(char *c1
, char *c2
, int x
)
207 char g1
[GNLEN
], g2
[GNLEN
];
208 if (!trfn_name(g1
, c1
) && !trfn_name(g2
, c2
) && abs(WX(x
)) > WX(20))
209 if (!strchr(g1
, ' ') && !strchr(g2
, ' '))
210 sbuf_printf(&sbuf_kern
, "%s\t%s\t%d\n", g1
, g2
, WX(x
));
213 void trfn_trfont(char *name
)
216 strcpy(trfn_trname
, name
);
219 void trfn_psfont(char *name
)
222 strcpy(trfn_psname
, name
);
225 void trfn_print(void)
228 printf("name %s\n", trfn_trname
);
230 printf("fontname %s\n", trfn_psname
);
231 printf("spacewidth %d\n", trfn_swid
);
232 printf("ligatures %s 0\n", trfn_ligs
);
234 printf("%s", sbuf_buf(&sbuf_char
));
235 printf("kernpairs\n");
236 printf("%s", sbuf_buf(&sbuf_kern
));
239 void trfn_init(int res
)
242 trfn_div
= 7200 / res
;
243 agl_read("glyphlist.txt");
244 sbuf_init(&sbuf_char
);
245 sbuf_init(&sbuf_kern
);
246 tab_alts
= tab_alloc(LEN(alts
));
247 tab_ctyp
= tab_alloc(LEN(ctype
));
248 for (i
= 0; i
< LEN(alts
); i
++)
249 tab_put(tab_alts
, alts
[i
][0], alts
[i
] + 1);
250 for (i
= 0; i
< LEN(ctype
); i
++)
251 tab_put(tab_ctyp
, ctype
[i
].ch
, &ctype
[i
]);
256 sbuf_done(&sbuf_char
);
257 sbuf_done(&sbuf_kern
);