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 NCHAR 8 /* number of characters per glyph */
14 #define GNLEN 64 /* glyph name length */
15 #define AGLLEN 8192 /* adobe glyphlist length */
16 #define NSUBS 2048 /* number of substitutions */
17 #define NPSAL 32 /* number of substitutions per glyph */
19 static struct sbuf sbuf_char
; /* characters */
20 static struct sbuf sbuf_kern
; /* kerning pairs */
21 static int trfn_div
; /* divisor of widths */
22 static int trfn_swid
; /* space width */
23 static int trfn_special
; /* special flag */
24 static int trfn_kmin
; /* minimum kerning value */
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 /* glyph substition */
29 static char subs_src
[NSUBS
][GNLEN
];
30 static char subs_dst
[NSUBS
][GNLEN
];
33 /* adobe glyphlist mapping */
34 static char agl_key
[AGLLEN
][GNLEN
];
35 static char agl_val
[AGLLEN
][GNLEN
];
39 static struct tab
*tab_agl
;
40 static struct tab
*tab_alts
;
41 static struct tab
*tab_ctyp
;
43 static int utf8len(int c
)
45 if (c
> 0 && c
<= 0x7f)
60 static int utf8get(char **src
)
65 if (~((unsigned char) **src
) & 0xc0)
66 return (unsigned char) *(*src
)++;
67 while (l
< 6 && (unsigned char) *s
& (0x40 >> l
))
69 result
= (0x3f >> l
) & (unsigned char) *s
++;
71 result
= (result
<< 6) | ((unsigned char) *s
++ & 0x3f);
76 static void utf8put(char **d
, int c
)
80 *(*d
)++ = 0xf0 | (c
>> 18);
82 } else if (c
> 0x7ff) {
83 *(*d
)++ = 0xe0 | (c
>> 12);
85 } else if (c
> 0x7f) {
86 *(*d
)++ = 0xc0 | (c
>> 6);
89 *(*d
)++ = c
> 0 ? c
: ' ';
93 *(*d
)++ = 0x80 | ((c
>> (l
* 6)) & 0x3f);
97 static int hexval(char *s
, int len
)
102 for (i
= 0; i
< len
; i
++) {
103 if (s
[i
] && strchr(digs
, tolower(s
[i
])))
104 n
= n
* 16 + (strchr(digs
, tolower(s
[i
])) - digs
);
108 return len
== 1 ? n
<< 4 : n
;
111 static int agl_read(char *path
)
113 FILE *fin
= fopen(path
, "r");
120 while (fgets(ln
, sizeof(ln
), fin
)) {
122 if (ln
[0] == '#' || !s
)
129 utf8put(&d
, hexval(s
, 6));
133 strcpy(agl_key
[agl_n
], ln
);
134 strcpy(agl_val
[agl_n
], val
);
138 tab_agl
= tab_alloc(agl_n
);
139 for (i
= 0; i
< agl_n
; i
++)
140 tab_put(tab_agl
, agl_key
[i
], agl_val
[i
]);
144 static char *agl_map(char *s
)
146 return tab_get(tab_agl
, s
);
149 static int achar_map(char *name
)
152 for (i
= 0; i
< LEN(achars
); i
++) {
153 struct achar
*a
= &achars
[i
];
154 if (!strncmp(a
->name
, name
, strlen(a
->name
))) {
155 char *postfix
= name
+ strlen(a
->name
);
158 if (!strcmp("isolated", postfix
))
159 return a
->s
? a
->s
: a
->c
;
160 if (!strcmp("initial", postfix
))
161 return a
->i
? a
->i
: a
->c
;
162 if (!strcmp("medial", postfix
))
163 return a
->m
? a
->m
: a
->c
;
164 if (!strcmp("final", postfix
))
165 return a
->f
? a
->f
: a
->c
;
171 static int achar_shape(int c
, int pjoin
, int njoin
)
174 for (i
= 0; i
< LEN(achars
); i
++) {
175 struct achar
*a
= &achars
[i
];
177 if (!pjoin
&& !njoin
)
180 return a
->i
? a
->i
: a
->c
;
182 return a
->m
? a
->m
: a
->c
;
184 return a
->f
? a
->f
: a
->c
;
190 static void ashape(char *str
, char *ext
)
195 int bjoin
= !strcmp(".medi", ext
) || !strcmp(".fina", ext
);
196 int ejoin
= !strcmp(".medi", ext
) || !strcmp(".init", ext
);
197 for (l
= 0; l
< NCHAR
&& *src
; l
++)
198 s
[l
] = utf8get(&src
);
199 for (i
= 0; i
< l
; i
++)
200 s
[i
] = achar_shape(s
[i
], i
> 0 || bjoin
, i
< l
- 1 || ejoin
);
201 for (i
= 0; i
< l
; i
++)
205 void trfn_sub(char *c1
, char *c2
)
207 if (subs_n
< NSUBS
&& !strchr(c1
, '.')) {
208 strcpy(subs_src
[subs_n
], c1
);
209 strcpy(subs_dst
[subs_n
], c2
);
214 /* return the list of postscript glyph aliases of character c */
215 static void trfn_subs(char *c
, char **a
)
219 /* adding c itself to the list of aliases only if not substituded */
220 for (i
= 0; i
< subs_n
; i
++)
221 if (!strcmp(c
, subs_src
[i
]))
223 dot
= strrchr(c
, '.');
224 if (!subs
&& (!dot
|| !strcmp(".isol", dot
) || !strcmp(".init", dot
) ||
225 !strcmp(".fina", dot
) || !strcmp(".medi", dot
)))
227 /* adding aliases added via trfn_subs() */
228 for (i
= 0; i
< subs_n
; i
++)
229 if (!strcmp(c
, subs_dst
[i
]))
234 static int trfn_name(char *dst
, char *src
)
240 if (!src
|| src
[0] == '.')
242 while (*src
&& *src
!= '.') {
246 while (*src
&& *src
!= '_' && *src
!= '.')
250 strcpy(d
, agl_map(ch
));
251 for (i
= 0; i
< LEN(agl_exceptions
); i
++)
252 if (!strcmp(agl_exceptions
[i
][0], d
))
253 strcpy(d
, agl_exceptions
[i
][1]);
255 } else if (ch
[0] == 'u' && ch
[1] == 'n' && ch
[2] == 'i') {
256 for (i
= 0; strlen(ch
+ 3 + 4 * i
) >= 4; i
++)
257 utf8put(&d
, hexval(ch
+ 3 + 4 * i
, 4));
258 } else if (ch
[0] == 'u' && ch
[1] && strchr(HEXDIGS
, tolower(ch
[1]))) {
259 utf8put(&d
, hexval(ch
+ 1, 6));
260 } else if (achar_map(ch
)) {
261 utf8put(&d
, achar_map(ch
));
270 static void trfn_lig(char *c
)
273 if (c
[0] && c
[1] && strlen(c
) > utf8len((unsigned char) c
[0])) {
274 sprintf(strchr(trfn_ligs
, '\0'), "%s ", c
);
277 for (i
= 0; i
< LEN(ligs
); i
++)
278 if (!strcmp(ligs
[i
], c
))
279 sprintf(strchr(trfn_ligs
, '\0'), "%s ", c
);
282 static int trfn_type(char *c
)
284 struct ctype
*t
= tab_get(tab_ctyp
, c
);
285 return t
? t
->type
: 3;
288 void trfn_char(char *psname
, char *n
, int wid
, int typ
)
290 char uc
[GNLEN
]; /* mapping unicode character */
291 char *a_ps
[NPSAL
] = {NULL
}; /* postscript glyph substitutions */
292 char **a_tr
; /* troff character names */
293 char pos
[GNLEN
] = ""; /* postscript character position/name */
294 int i_ps
= 0; /* current name in a_ps */
295 /* initializing character attributes */
296 if (trfn_name(uc
, psname
))
298 if (n
&& atoi(n
) >= 0 && atoi(n
) < 256)
300 if (!n
&& !strchr(psname
, '.') && !uc
[1] && uc
[0] >= 32 && uc
[0] <= 125)
301 sprintf(pos
, "%d", uc
[0]);
303 typ
= trfn_type(!strchr(psname
, '.') ? uc
: "");
304 /* printing troff charset */
305 trfn_subs(psname
, a_ps
);
306 for (i_ps
= 0; !i_ps
|| a_ps
[i_ps
]; i_ps
++) {
307 if (trfn_name(uc
, a_ps
[i_ps
]))
309 if (strchr(uc
, ' ')) { /* space not allowed in char names */
310 if (!trfn_swid
&& !strcmp(" ", uc
))
314 if (strcmp("---", uc
))
316 sbuf_printf(&sbuf_char
, "char %s\t%d\t%d\t%s\t%s\n",
317 uc
, WX(wid
), typ
, psname
, pos
);
318 a_tr
= tab_get(tab_alts
, uc
);
319 while (a_tr
&& *a_tr
)
320 sbuf_printf(&sbuf_char
, "char %s\t\"\n", *a_tr
++);
324 void trfn_kern(char *c1
, char *c2
, int x
)
326 if (WX(x
) && abs(WX(x
)) >= WX(trfn_kmin
))
327 sbuf_printf(&sbuf_kern
, "kern %s\t%s\t%d\n", c1
, c2
, WX(x
));
330 void trfn_trfont(char *name
)
333 strcpy(trfn_trname
, name
);
336 void trfn_psfont(char *name
)
339 strcpy(trfn_psname
, name
);
342 void trfn_print(void)
345 printf("name %s\n", trfn_trname
);
347 printf("fontname %s\n", trfn_psname
);
348 printf("spacewidth %d\n", trfn_swid
);
349 printf("ligatures %s0\n", trfn_ligs
);
352 printf("%s", sbuf_buf(&sbuf_char
));
353 printf("%s", sbuf_buf(&sbuf_kern
));
356 void trfn_init(int res
, int spc
, int kmin
)
359 trfn_div
= 7200 / res
;
362 if (agl_read("glyphlist.txt"))
363 fprintf(stderr
, "mktrfn: could not open glyphlist.txt\n");
364 sbuf_init(&sbuf_char
);
365 sbuf_init(&sbuf_kern
);
366 tab_alts
= tab_alloc(LEN(alts
));
367 tab_ctyp
= tab_alloc(LEN(ctype
));
368 for (i
= 0; i
< LEN(alts
); i
++)
369 tab_put(tab_alts
, alts
[i
][0], alts
[i
] + 1);
370 for (i
= 0; i
< LEN(ctype
); i
++)
371 tab_put(tab_ctyp
, ctype
[i
].ch
, &ctype
[i
]);
376 sbuf_done(&sbuf_char
);
377 sbuf_done(&sbuf_kern
);