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 int trfn_special
; /* special flag */
21 static char trfn_ligs
[1024]; /* font ligatures */
22 static char trfn_trname
[256]; /* font troff name */
23 static char trfn_psname
[256]; /* font ps name */
25 /* adobe glyphlist mapping */
26 static char agl_key
[AGLLEN
][GNLEN
];
27 static char agl_val
[AGLLEN
][GNLEN
];
31 static struct tab
*tab_agl
;
32 static struct tab
*tab_alts
;
33 static struct tab
*tab_ctyp
;
35 static void pututf8(char **d
, int c
)
39 *(*d
)++ = 0xf0 | (c
>> 18);
41 } else if (c
> 0x7ff) {
42 *(*d
)++ = 0xe0 | (c
>> 12);
44 } else if (c
> 0x7f) {
45 *(*d
)++ = 0xc0 | (c
>> 6);
48 *(*d
)++ = c
> 0 ? c
: ' ';
52 *(*d
)++ = 0x80 | ((c
>> (l
* 6)) & 0x3f);
56 static int hexval(char *s
, int len
)
61 for (i
= 0; i
< len
; i
++) {
62 if (s
[i
] && strchr(digs
, tolower(s
[i
])))
63 n
= n
* 16 + (strchr(digs
, tolower(s
[i
])) - digs
);
67 return len
== 1 ? n
<< 4 : n
;
70 static int agl_read(char *path
)
72 FILE *fin
= fopen(path
, "r");
79 while (fgets(ln
, sizeof(ln
), fin
)) {
81 if (ln
[0] == '#' || !s
)
88 pututf8(&d
, hexval(s
, 6));
92 strcpy(agl_key
[agl_n
], ln
);
93 strcpy(agl_val
[agl_n
], val
);
97 tab_agl
= tab_alloc(agl_n
);
98 for (i
= 0; i
< agl_n
; i
++)
99 tab_put(tab_agl
, agl_key
[i
], agl_val
[i
]);
103 static char *agl_map(char *s
)
105 return tab_get(tab_agl
, s
);
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 trfn_name(char *dst
, char *src
)
137 if (src
[1] && strchr(src
, '.'))
138 return 1; /* ignore opentype features for now */
139 while (*src
&& *src
!= '.') {
143 while (*src
&& *src
!= '_' && *src
!= '.')
147 strcpy(dst
, agl_map(ch
));
148 for (i
= 0; i
< LEN(agl_exceptions
); i
++)
149 if (!strcmp(agl_exceptions
[i
][0], dst
))
150 strcpy(dst
, agl_exceptions
[i
][1]);
151 dst
= strchr(dst
, '\0');
152 } else if (ch
[0] == 'u' && ch
[1] == 'n' && ch
[2] == 'i') {
153 for (i
= 0; strlen(ch
+ 3 + 4 * i
) >= 4; i
++)
154 pututf8(&dst
, hexval(ch
+ 3 + 4 * i
, 4));
155 } else if (ch
[0] == 'u' && ch
[1] && strchr(HEXDIGS
, tolower(ch
[1]))) {
156 pututf8(&dst
, hexval(ch
+ 1, 6));
157 } else if (achar_map(ch
)) {
158 pututf8(&dst
, achar_map(ch
));
166 static void trfn_lig(char *c
)
169 for (i
= 0; i
< LEN(ligs
); i
++)
170 if (!strcmp(ligs
[i
], c
))
171 sprintf(strchr(trfn_ligs
, '\0'), "%s ", c
);
174 static int trfn_type(char *c
)
176 struct ctype
*t
= tab_get(tab_ctyp
, c
);
177 return t
? t
->type
: 3;
180 void trfn_char(char *c
, char *n
, int wid
, int typ
)
185 if (trfn_name(uc
, c
))
187 if (strchr(uc
, ' ')) { /* space not allowed in character names */
188 if (!trfn_swid
&& !strcmp(" ", uc
))
196 if (n
&& atoi(n
) >= 0 && atoi(n
) < 256)
198 if (!n
&& !uc
[1] && uc
[0] >= 32 && uc
[0] <= 125)
199 sprintf(pos
, "%d", uc
[0]);
200 sbuf_printf(&sbuf_char
, "%s\t%d\t%d\t%s\n", uc
, WX(wid
), typ
, pos
);
201 a
= tab_get(tab_alts
, uc
);
203 sbuf_printf(&sbuf_char
, "%s\t\"\n", *a
++);
206 void trfn_kern(char *c1
, char *c2
, int x
)
208 char g1
[GNLEN
], g2
[GNLEN
];
209 if (!trfn_name(g1
, c1
) && !trfn_name(g2
, c2
) && abs(WX(x
)) > WX(20))
210 if (!strchr(g1
, ' ') && !strchr(g2
, ' '))
211 sbuf_printf(&sbuf_kern
, "%s\t%s\t%d\n", g1
, g2
, WX(x
));
214 void trfn_trfont(char *name
)
217 strcpy(trfn_trname
, name
);
220 void trfn_psfont(char *name
)
223 strcpy(trfn_psname
, name
);
226 void trfn_print(void)
229 printf("name %s\n", trfn_trname
);
231 printf("fontname %s\n", trfn_psname
);
232 printf("spacewidth %d\n", trfn_swid
);
233 printf("ligatures %s 0\n", trfn_ligs
);
237 printf("%s", sbuf_buf(&sbuf_char
));
238 printf("kernpairs\n");
239 printf("%s", sbuf_buf(&sbuf_kern
));
242 void trfn_init(int res
, int spc
)
245 trfn_div
= 7200 / res
;
247 if (agl_read("glyphlist.txt"))
248 fprintf(stderr
, "mktrfn: could not open glyphlist.txt\n");
249 sbuf_init(&sbuf_char
);
250 sbuf_init(&sbuf_kern
);
251 tab_alts
= tab_alloc(LEN(alts
));
252 tab_ctyp
= tab_alloc(LEN(ctype
));
253 for (i
= 0; i
< LEN(alts
); i
++)
254 tab_put(tab_alts
, alts
[i
][0], alts
[i
] + 1);
255 for (i
= 0; i
< LEN(ctype
); i
++)
256 tab_put(tab_ctyp
, ctype
[i
].ch
, &ctype
[i
]);
261 sbuf_done(&sbuf_char
);
262 sbuf_done(&sbuf_kern
);