11 #define WX(w) (((w) < 0 ? (w) - trfn_div / 20 : (w) + trfn_div / 20) * (long) 10 / 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 x 10 */
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 int trfn_noligs
; /* suppress ligatures */
26 static int trfn_pos
; /* include glyph positions */
27 static char trfn_ligs
[8192]; /* font ligatures */
28 static char trfn_ligs2
[8192]; /* font ligatures, whose length is two */
29 static char trfn_trname
[256]; /* font troff name */
30 static char trfn_psname
[256]; /* font ps name */
31 static char trfn_path
[4096]; /* font path */
33 static int trfn_asc
; /* minimum height of glyphs with ascender */
34 static int trfn_desc
; /* minimum depth of glyphs with descender */
37 static struct tab
*tab_agl
; /* adobe glyph list table */
38 static struct tab
*tab_alts
; /* character aliases table */
40 static int utf8len(int c
)
42 if (c
> 0 && c
<= 0x7f)
57 static int utf8get(char **src
)
62 if (~((unsigned char) **src
) & 0xc0)
63 return (unsigned char) *(*src
)++;
64 while (l
< 6 && (unsigned char) *s
& (0x40 >> l
))
66 result
= (0x3f >> l
) & (unsigned char) *s
++;
68 result
= (result
<< 6) | ((unsigned char) *s
++ & 0x3f);
73 static void utf8put(char **d
, int c
)
77 *(*d
)++ = 0xf0 | (c
>> 18);
79 } else if (c
> 0x7ff) {
80 *(*d
)++ = 0xe0 | (c
>> 12);
82 } else if (c
> 0x7f) {
83 *(*d
)++ = 0xc0 | (c
>> 6);
86 *(*d
)++ = c
> 0 ? c
: ' ';
89 *(*d
)++ = 0x80 | ((c
>> (l
* 6)) & 0x3f);
93 static int hexval(char *s
, int len
)
98 for (i
= 0; i
< len
; i
++) {
99 if (s
[i
] && strchr(digs
, s
[i
]))
100 n
= n
* 16 + (strchr(digs
, s
[i
]) - digs
);
104 return i
< 4 ? -1 : n
;
107 static int agl_map(char *d
, char *s
)
109 char *u
= tab_get(tab_agl
, s
); /* unicode code point like "FB8E" */
115 utf8put(&d
, hexval(u
, 6));
122 static int achar_map(char *name
)
125 for (i
= 0; i
< LEN(achars
); i
++) {
126 struct achar
*a
= &achars
[i
];
127 if (!strncmp(a
->name
, name
, strlen(a
->name
))) {
128 char *postfix
= name
+ strlen(a
->name
);
131 if (!strcmp("isolated", postfix
))
132 return a
->s
? a
->s
: a
->c
;
133 if (!strcmp("initial", postfix
))
134 return a
->i
? a
->i
: a
->c
;
135 if (!strcmp("medial", postfix
))
136 return a
->m
? a
->m
: a
->c
;
137 if (!strcmp("final", postfix
))
138 return a
->f
? a
->f
: a
->c
;
144 static int achar_shape(int c
, int pjoin
, int njoin
)
147 for (i
= 0; i
< LEN(achars
); i
++) {
148 struct achar
*a
= &achars
[i
];
150 if (!pjoin
&& !njoin
)
153 return a
->i
? a
->i
: a
->c
;
155 return a
->m
? a
->m
: a
->c
;
157 return a
->f
? a
->f
: a
->c
;
163 static void ashape(char *str
, char *ext
)
168 int bjoin
= !strcmp(".medi", ext
) || !strcmp(".fina", ext
);
169 int ejoin
= !strcmp(".medi", ext
) || !strcmp(".init", ext
);
170 for (l
= 0; l
< NCHAR
&& *src
; l
++)
171 s
[l
] = utf8get(&src
);
172 for (i
= 0; i
< l
; i
++)
173 s
[i
] = achar_shape(s
[i
], i
> 0 || bjoin
, i
< l
- 1 || ejoin
);
174 for (i
= 0; i
< l
; i
++)
178 /* find the utf-8 name of src with the given unicode codepoint */
179 static int trfn_name(char *dst
, char *src
, int codepoint
)
186 utf8put(&dst
, codepoint
);
189 if (!src
|| src
[0] == '.')
191 while (*src
&& *src
!= '.') {
195 while (*src
&& *src
!= '_' && *src
!= '.')
198 if (!agl_map(d
, ch
)) {
200 } else if (ch
[0] == 'u' && ch
[1] == 'n' &&
201 ch
[2] == 'i' && hexval(ch
+ 3, 4) > 0) {
202 for (i
= 0; strlen(ch
+ 3 + 4 * i
) >= 4; i
++)
203 utf8put(&d
, hexval(ch
+ 3 + 4 * i
, 4));
204 } else if (ch
[0] == 'u' && hexval(ch
+ 1, 4) > 0) {
205 utf8put(&d
, hexval(ch
+ 1, 6));
206 } else if (achar_map(ch
)) {
207 utf8put(&d
, achar_map(ch
));
213 return *src
&& strcmp(src
, ".medi") && strcmp(src
, ".fina") &&
214 strcmp(src
, ".init") && strcmp(src
, ".isol");
217 static void trfn_aglexceptions(char *dst
)
220 for (i
= 0; i
< LEN(agl_exceptions
); i
++)
221 if (!strcmp(agl_exceptions
[i
][0], dst
))
222 strcpy(dst
, agl_exceptions
[i
][1]);
225 static void trfn_ligput(char *c
)
227 char *dst
= strlen(c
) == 2 ? trfn_ligs2
: trfn_ligs
;
228 sprintf(strchr(dst
, '\0'), "%s ", c
);
231 static void trfn_lig(char *c
)
234 for (i
= 0; i
< LEN(agl_exceptions
); i
++)
235 if (!strcmp(agl_exceptions
[i
][1], c
))
237 if (c
[0] && c
[1] && strlen(c
) > utf8len((unsigned char) c
[0])) {
240 for (i
= 0; i
< LEN(ligs_utf8
); i
++)
241 if (!strcmp(ligs_utf8
[i
][0], c
))
242 trfn_ligput(ligs_utf8
[i
][1]);
246 static int trfn_type(char *s
, int lly
, int ury
)
249 int c
= !s
[0] || s
[1] ? 0 : (unsigned char) *s
;
250 if (c
== 't' && !trfn_asc
)
252 if ((c
== 'g' || c
== 'j' || c
== 'p' || c
== 'q' || c
== 'y') &&
253 (!trfn_desc
|| trfn_desc
< lly
))
255 if (!trfn_desc
|| !trfn_asc
) {
256 if (c
> 0 && c
< 128)
257 return ctype_ascii
[c
];
260 if (!trfn_desc
|| lly
<= trfn_desc
)
262 if (!trfn_asc
|| ury
>= trfn_asc
)
267 /* n is the position and u is the unicode codepoint */
268 void trfn_char(char *psname
, int n
, int u
, int wid
,
269 int llx
, int lly
, int urx
, int ury
)
271 char uc
[GNLEN
]; /* mapping unicode character */
272 char **a_tr
; /* troff character names */
273 char pos
[GNLEN
] = ""; /* postscript character position/name */
274 int typ
; /* character type */
275 /* initializing character attributes */
276 if (trfn_name(uc
, psname
, u
))
278 trfn_aglexceptions(uc
);
279 if (trfn_pos
&& n
>= 0 && n
< 256)
280 sprintf(pos
, "%d", n
);
281 if (trfn_pos
&& n
< 0 && !uc
[1] && uc
[0] >= 32 && uc
[0] <= 125)
282 if (!strchr(psname
, '.'))
283 sprintf(pos
, "%d", uc
[0]);
284 typ
= trfn_type(!strchr(psname
, '.') ? uc
: "", lly
, ury
);
285 if (!trfn_swid
&& (!strcmp(" ", uc
) || !strcmp(" ", uc
)))
287 /* printing troff charset */
288 if (strchr(uc
, ' ')) /* space not allowed in char names */
290 if (strcmp("---", uc
))
292 sbuf_printf(sbuf_char
, "char %s\t%d", uc
, WX(wid
));
293 if (trfn_bbox
&& (llx
|| lly
|| urx
|| ury
))
294 sbuf_printf(sbuf_char
, ",%d,%d,%d,%d",
295 WX(llx
), WX(lly
), WX(urx
), WX(ury
));
296 sbuf_printf(sbuf_char
, "\t%d\t%s\t%s\n", typ
, psname
, pos
);
297 a_tr
= tab_get(tab_alts
, uc
);
298 while (a_tr
&& *a_tr
)
299 sbuf_printf(sbuf_char
, "char %s\t\"\n", *a_tr
++);
302 void trfn_kern(char *c1
, char *c2
, int x
)
304 if (WX(x
) && abs(WX(x
)) >= trfn_kmin
)
305 sbuf_printf(sbuf_kern
, "kern %s\t%s\t%d\n", c1
, c2
, WX(x
));
308 void trfn_trfont(char *name
)
311 strcpy(trfn_trname
, name
);
314 void trfn_psfont(char *name
)
317 strcpy(trfn_psname
, name
);
320 void trfn_pspath(char *name
)
323 strcpy(trfn_path
, name
);
326 void trfn_print(void)
329 printf("name %s\n", trfn_trname
);
331 printf("fontname %s\n", trfn_psname
);
333 printf("fontpath %s\n", trfn_path
);
334 printf("spacewidth %d\n", trfn_swid
);
336 printf("ligatures %s%s0\n", trfn_ligs
, trfn_ligs2
);
339 fputs(sbuf_buf(sbuf_char
), stdout
);
340 fputs(sbuf_buf(sbuf_kern
), stdout
);
343 void trfn_init(int res
, int spc
, int kmin
, int bbox
, int ligs
, int pos
)
346 trfn_div
= 72000 / res
;
352 sbuf_char
= sbuf_make();
353 sbuf_kern
= sbuf_make();
354 tab_agl
= tab_alloc(LEN(agl
));
355 for (i
= 0; i
< LEN(agl
); i
++)
356 tab_put(tab_agl
, agl
[i
][0], agl
[i
][1]);
357 tab_alts
= tab_alloc(LEN(alts
));
358 for (i
= 0; i
< LEN(alts
); i
++)
359 tab_put(tab_alts
, alts
[i
][0], alts
[i
] + 1);
364 sbuf_free(sbuf_char
);
365 sbuf_free(sbuf_kern
);