9 #define LEN(a) ((sizeof(a) / sizeof((a)[0])))
10 #define HEXDIGS "0123456789ABCDEF"
11 #define NCHAR 8 /* number of characters per glyph */
12 #define GNLEN 64 /* glyph name length */
14 /* for buffering the output */
15 static struct sbuf
*sbuf_char
; /* character definitions */
16 /* handling ligatures */
17 static char mkfn_ligs
[8192]; /* font ligatures */
18 static char mkfn_ligs2
[8192]; /* font ligatures, whose length is two */
20 static int mkfn_asc
; /* minimum height of glyphs with ascender */
21 static int mkfn_desc
; /* minimum depth of glyphs with descender */
23 static struct tab
*tab_agl
; /* adobe glyph list table */
24 static struct tab
*tab_alts
; /* character aliases table */
26 static int utf8len(int c
)
28 if (c
> 0 && c
<= 0x7f)
43 static int utf8get(char **src
)
48 if (~((unsigned char) **src
) & 0xc0)
49 return (unsigned char) *(*src
)++;
50 while (l
< 6 && (unsigned char) *s
& (0x40 >> l
))
52 result
= (0x3f >> l
) & (unsigned char) *s
++;
54 result
= (result
<< 6) | ((unsigned char) *s
++ & 0x3f);
59 static void utf8put(char **d
, int c
)
63 *(*d
)++ = 0xf0 | (c
>> 18);
65 } else if (c
> 0x7ff) {
66 *(*d
)++ = 0xe0 | (c
>> 12);
68 } else if (c
> 0x7f) {
69 *(*d
)++ = 0xc0 | (c
>> 6);
72 *(*d
)++ = c
> 0 ? c
: ' ';
75 *(*d
)++ = 0x80 | ((c
>> (l
* 6)) & 0x3f);
79 static int hexval(char *s
, int len
)
84 for (i
= 0; i
< len
; i
++) {
85 if (s
[i
] && strchr(digs
, s
[i
]))
86 n
= n
* 16 + (strchr(digs
, s
[i
]) - digs
);
90 return i
< 4 ? -1 : n
;
93 static int agl_map(char *d
, char *s
)
95 char *u
= tab_get(tab_agl
, s
); /* unicode code point like "FB8E" */
101 utf8put(&d
, hexval(u
, 6));
108 static int achar_map(char *name
)
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
);
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
;
130 static int achar_shape(int c
, int pjoin
, int njoin
)
133 for (i
= 0; i
< LEN(achars
); i
++) {
134 struct achar
*a
= &achars
[i
];
136 if (!pjoin
&& !njoin
)
139 return a
->i
? a
->i
: a
->c
;
141 return a
->m
? a
->m
: a
->c
;
143 return a
->f
? a
->f
: a
->c
;
149 static void ashape(char *str
, char *ext
)
154 int bjoin
= !strcmp(".medi", ext
) || !strcmp(".fina", ext
);
155 int ejoin
= !strcmp(".medi", ext
) || !strcmp(".init", ext
);
156 for (l
= 0; l
< NCHAR
&& *src
; l
++)
157 s
[l
] = utf8get(&src
);
158 for (i
= 0; i
< l
; i
++)
159 s
[i
] = achar_shape(s
[i
], i
> 0 || bjoin
, i
< l
- 1 || ejoin
);
160 for (i
= 0; i
< l
; i
++)
164 /* find the utf-8 name of src with the given unicode codepoint */
165 static int trfn_name(char *dst
, char *src
, int codepoint
)
172 utf8put(&dst
, codepoint
);
175 if (!src
|| src
[0] == '.')
177 while (*src
&& *src
!= '.') {
181 while (*src
&& *src
!= '_' && *src
!= '.')
184 if (!agl_map(d
, ch
)) {
186 } else if (ch
[0] == 'u' && ch
[1] == 'n' &&
187 ch
[2] == 'i' && hexval(ch
+ 3, 4) > 0) {
188 for (i
= 0; strlen(ch
+ 3 + 4 * i
) >= 4; i
++)
189 utf8put(&d
, hexval(ch
+ 3 + 4 * i
, 4));
190 } else if (ch
[0] == 'u' && hexval(ch
+ 1, 4) > 0) {
191 utf8put(&d
, hexval(ch
+ 1, 6));
192 } else if (achar_map(ch
)) {
193 utf8put(&d
, achar_map(ch
));
199 return *src
&& strcmp(src
, ".medi") && strcmp(src
, ".fina") &&
200 strcmp(src
, ".init") && strcmp(src
, ".isol");
203 static void trfn_aglexceptions(char *dst
)
206 for (i
= 0; i
< LEN(agl_exceptions
); i
++)
207 if (!strcmp(agl_exceptions
[i
][0], dst
))
208 strcpy(dst
, agl_exceptions
[i
][1]);
211 static void trfn_ligput(char *c
)
213 char *dst
= strlen(c
) == 2 ? mkfn_ligs2
: mkfn_ligs
;
214 sprintf(strchr(dst
, '\0'), "%s ", c
);
217 static void trfn_lig(char *c
)
220 for (i
= 0; i
< LEN(agl_exceptions
); i
++)
221 if (!strcmp(agl_exceptions
[i
][1], c
))
223 if (c
[0] && c
[1] && strlen(c
) > utf8len((unsigned char) c
[0])) {
226 for (i
= 0; i
< LEN(ligs_utf8
); i
++)
227 if (!strcmp(ligs_utf8
[i
][0], c
))
228 trfn_ligput(ligs_utf8
[i
][1]);
232 static int trfn_type(char *s
, int lly
, int ury
)
235 int c
= !s
[0] || s
[1] ? 0 : (unsigned char) *s
;
236 if (c
== 't' && !mkfn_asc
)
238 if ((c
== 'g' || c
== 'j' || c
== 'p' || c
== 'q' || c
== 'y') &&
239 (!mkfn_desc
|| mkfn_desc
< lly
))
241 if (!mkfn_desc
|| !mkfn_asc
) {
242 if (c
> 0 && c
< 128)
243 return ctype_ascii
[c
];
246 if (!mkfn_desc
|| lly
<= mkfn_desc
)
248 if (!mkfn_asc
|| ury
>= mkfn_asc
)
253 /* n is the position and u is the unicode codepoint */
254 void mkfn_char(char *psname
, int n
, int u
, int wid
,
255 int llx
, int lly
, int urx
, int ury
)
257 char uc
[GNLEN
]; /* mapping unicode character */
258 char **a_tr
; /* troff character names */
259 char pos
[GNLEN
] = ""; /* postscript character position/name */
260 int typ
; /* character type */
261 /* initializing character attributes */
262 if (trfn_name(uc
, psname
, u
))
264 trfn_aglexceptions(uc
);
265 if (mkfn_pos
&& n
>= 0 && n
< 256)
266 sprintf(pos
, "%d", n
);
267 if (mkfn_pos
&& n
< 0 && !uc
[1] && uc
[0] >= 32 && uc
[0] <= 125)
268 if (!strchr(psname
, '.'))
269 sprintf(pos
, "%d", uc
[0]);
270 typ
= trfn_type(!strchr(psname
, '.') ? uc
: "", lly
, ury
);
271 if (!mkfn_swid
&& (!strcmp(" ", uc
) || !strcmp(" ", uc
)))
273 /* printing troff charset */
274 if (isspace((unsigned char) uc
[0]) || strchr(uc
, ' '))
275 strcpy(uc
, "---"); /* space not allowed in char names */
276 if (strcmp("---", uc
))
278 sbuf_printf(sbuf_char
, "char %s\t%d", uc
, wid
);
279 if (mkfn_bbox
&& (llx
|| lly
|| urx
|| ury
))
280 sbuf_printf(sbuf_char
, ",%d,%d,%d,%d", llx
, lly
, urx
, ury
);
281 sbuf_printf(sbuf_char
, "\t%d\t%s\t%s\n", typ
, psname
, pos
);
282 a_tr
= tab_get(tab_alts
, uc
);
283 while (a_tr
&& *a_tr
)
284 sbuf_printf(sbuf_char
, "char %s\t\"\n", *a_tr
++);
287 void mkfn_kern(char *c1
, char *c2
, int x
)
289 if (x
&& abs(x
) >= mkfn_kmin
)
291 printf("kern %s\t%s\t%d\n", c1
, c2
, x
);
294 /* print spacewidth and ligature lines */
295 void trfn_header(void)
297 printf("spacewidth %d\n", mkfn_swid
);
299 printf("ligatures %s%s0\n", mkfn_ligs
, mkfn_ligs2
);
302 /* print character definitions */
303 void trfn_cdefs(void)
305 fputs(sbuf_buf(sbuf_char
), stdout
);
311 sbuf_char
= sbuf_make();
312 tab_agl
= tab_alloc(LEN(agl
));
313 for (i
= 0; i
< LEN(agl
); i
++)
314 tab_put(tab_agl
, agl
[i
][0], agl
[i
][1]);
315 tab_alts
= tab_alloc(LEN(alts
));
316 for (i
= 0; i
< LEN(alts
); i
++)
317 tab_put(tab_alts
, alts
[i
][0], alts
[i
] + 1);
322 sbuf_free(sbuf_char
);