1 /*
2 * ttfaux.c
3 *
4 * This file is part of the ttf2pk package.
5 *
6 * Copyright 1997-1999, 2000, 2002, 2003 by
7 * Frederic Loyer <loyer@ensta.fr>
8 * Werner Lemberg <wl@gnu.org>
9 */
10
11 #ifdef HAVE_CONFIG_H
12 #include <config.h>
13 #endif
14
15 #include <string.h>
16 #include <stdlib.h>
17
18 #include <ft2build.h>
19 #include FT_FREETYPE_H
20 #include FT_OUTLINE_H
21 #include FT_BBOX_H
22
23 #include "ttf2tfm.h"
24 #include "newobj.h"
25 #include "ligkern.h"
26 #include "ttfenc.h"
27 #include "tfmaux.h"
28 #include "errormsg.h"
29 #include "ttfaux.h"
30 #include "filesrch.h"
31 #include "ftlib.h"
32
33
34 char *real_ttfname;
35
36 int flags = FT_LOAD_DEFAULT|FT_LOAD_NO_SCALE;
37
38 FT_BBox bbox;
39
40
41 static void
readttf_kern(Font * fnt)42 readttf_kern(Font *fnt)
43 {
44 kern *nk;
45 ttfinfo *ti, *tj;
46 FT_Error error;
47 FT_Vector akerning;
48
49 for (ti = fnt->charlist; ti; ti = ti->next)
50 {
51 kern head;
52 kern *tail = &head;
53 head.next = NULL;
54 for (tj = fnt->charlist; tj; tj = tj->next)
55 {
56 if ((error = FT_Get_Kerning(face, ti->glyphindex, tj->glyphindex,
57 FT_KERNING_UNSCALED, &akerning)))
58 oops("Cannot get kerning vector (error code = 0x%x).", error);
59
60 if (akerning.x)
61 {
62 nk = newkern();
63 nk->succ = tj->adobename;
64 nk->delta = transform(akerning.x * 1000 / fnt->units_per_em, 0,
65 fnt->efactor, fnt->slant);
66 #if 0
67 nk->next = ti->kerns;
68 ti->kerns = nk;
69 #else
70 /* We append the new kern to reproduce the old .vpl file */
71 tail->next = nk;
72 tail = nk;
73 #endif
74 }
75 }
76 ti->kerns = head.next;
77 }
78 }
79
80
81 void
readttf(Font * fnt,Boolean quiet,Boolean only_range)82 readttf(Font *fnt, Boolean quiet, Boolean only_range)
83 {
84 FT_Error error;
85 ttfinfo *ti, *Ti;
86 long Num, index;
87 unsigned int i, j;
88 long k, max_k;
89 int index_array[257];
90
91 static Boolean initialized = False;
92
93
94 /*
95 * We allocate a placeholder boundary and the `.notdef' character.
96 */
97
98 if (!only_range)
99 {
100 ti = newchar(fnt);
101 ti->charcode = -1;
102 ti->adobename = ".notdef";
103
104 ti = newchar(fnt);
105 ti->charcode = -1;
106 ti->adobename = "||"; /* boundary character name */
107 }
108
109 /*
110 * Initialize FreeType engine.
111 */
112
113 if (!initialized)
114 {
115 /*
116 * We use a dummy glyph size of 10pt.
117 */
118 dpi = 92;
119 ptsize = 10 * 64;
120
121 real_ttfname = TeX_search_ttf_file(&(fnt->ttfname));
122 if (!real_ttfname)
123 oops("Cannot find `%s'.", fnt->ttfname);
124
125 FTopen(real_ttfname, fnt, True, True);
126
127 initialized = True;
128 }
129
130 if (!quiet)
131 {
132 if (only_range)
133 printf("\n\n%s:\n", fnt->fullname);
134 printf("\n");
135 printf("Glyph Code Glyph Name ");
136 printf("Width llx lly urx ury\n");
137 printf("----------------------------------------");
138 printf("---------------------------------\n");
139 }
140
141 /*
142 * We load only glyphs with a valid cmap entry. Nevertheless, for
143 * the default mapping, we use the first 256 glyphs addressed by
144 * ascending code points, followed by glyphs not in the cmap.
145 *
146 * If we compute a range, we take the character codes given in
147 * the fnt->sf_code array.
148 *
149 * If the -N flag is set, no cmap is used at all. Instead, the
150 * first 256 glyphs (with a valid PS name) are used for the default
151 * mapping.
152 */
153
154 if (!only_range)
155 for (i = 0; i < 257; i++)
156 index_array[i] = 0;
157 else
158 for (i = 0; i < 256; i++)
159 fnt->inencptrs[i] = 0;
160
161 j = 0;
162 if (fnt->PSnames == Only)
163 max_k = face->num_glyphs - 1;
164 else
165 max_k = only_range ? 0xFF : 0x16FFFF;
166
167 for (k = 0; k <= max_k; k++)
168 {
169 char buff[128];
170 const char *an;
171
172
173 if (fnt->PSnames != Only)
174 {
175 if (only_range)
176 {
177 index = fnt->sf_code[k];
178 if (index < 0)
179 continue;
180 j = k;
181 }
182 else
183 index = k;
184
185 Num = FT_Get_Char_Index(face, index);
186
187 /* now we try to get a vertical glyph form */
188 if (has_gsub)
189 Num = Get_Vert(Num);
190
191 if (Num < 0)
192 oops("Failure on cmap mapping from %s.", fnt->ttfname);
193 if (Num == 0)
194 continue;
195 if (!only_range)
196 if (Num <= 256)
197 index_array[Num] = 1;
198 }
199 else
200 {
201 Num = k;
202 index = 0;
203 }
204
205 error = FT_Load_Glyph(face, Num, flags);
206 if (!error)
207 {
208 if (fnt->efactor != 1.0 || fnt->slant != 0.0 )
209 FT_Outline_Transform(&face->glyph->outline, &matrix1);
210 if (fnt->rotate)
211 FT_Outline_Transform(&face->glyph->outline, &matrix2);
212 error = FT_Outline_Get_BBox(&face->glyph->outline, &bbox); /* we need the non-
213 grid-fitted bbox */
214 }
215 if (!error)
216 {
217 if (fnt->PSnames)
218 {
219 (void)FT_Get_Glyph_Name(face, Num, buff, 128);
220 an = newstring(buff);
221 }
222 else
223 an = code_to_adobename(index);
224
225 /* ignore characters not usable for typesetting with TeX */
226
227 if (strcmp(an, ".notdef") == 0)
228 continue;
229 if (strcmp(an, ".null") == 0)
230 continue;
231 if (strcmp(an, "nonmarkingreturn") == 0)
232 continue;
233
234 ti = newchar(fnt);
235 ti->charcode = index;
236 ti->glyphindex = Num;
237 ti->adobename = an;
238 ti->llx = bbox.xMin * 1000 / fnt->units_per_em;
239 ti->lly = bbox.yMin * 1000 / fnt->units_per_em;
240 ti->urx = bbox.xMax * 1000 / fnt->units_per_em;
241 ti->ury = bbox.yMax * 1000 / fnt->units_per_em;
242
243 ti->fntnum = fnt->subfont_num;
244
245 /*
246 * We must now shift the rotated character both horizontally
247 * and vertically. The vertical amount is 25% by default.
248 */
249
250 if (fnt->rotate)
251 {
252 ti->llx += (face->glyph->metrics.vertBearingY - bbox.xMin) *
253 1000 / fnt->units_per_em;
254 ti->lly -= 1000 * fnt->y_offset;
255 ti->urx += (face->glyph->metrics.vertBearingY - bbox.xMin) *
256 1000 / fnt->units_per_em;
257 ti->ury -= 1000 * fnt->y_offset;
258 }
259
260 /*
261 * We need to avoid negative heights or depths. They break accents
262 * in math mode, among other things.
263 */
264
265 if (ti->lly > 0)
266 ti->lly = 0;
267 if (ti->ury < 0)
268 ti->ury = 0;
269 if (fnt->rotate)
270 ti->width = face->glyph->metrics.vertAdvance * 1000 / fnt->units_per_em;
271 else
272 ti->width = transform(face->glyph->metrics.horiAdvance * 1000 / fnt->units_per_em,
273 0, fnt->efactor, fnt->slant);
274
275 if (!quiet)
276 printf("%5ld %05lx %-25s %5d % 5d,% 5d -- % 5d,% 5d\n",
277 Num, index, ti->adobename,
278 ti->width,
279 ti->llx, ti->lly, ti->urx, ti->ury);
280
281 if (j < 256)
282 {
283 fnt->inencptrs[j] = ti;
284 ti->incode = j;
285 }
286 j++;
287 }
288 }
289
290 /*
291 * Now we load glyphs without a cmap entry, provided some slots are
292 * still free -- we skip this if we have to compute a range or use
293 * PS names.
294 */
295
296 if (!only_range && !fnt->PSnames)
297 {
298 for (i = 1; i <= face->num_glyphs; i++)
299 {
300 const char *an;
301
302
303 if (index_array[i] == 0)
304 {
305 error = FT_Load_Glyph(face, i, flags);
306 if (!error)
307 error = FT_Outline_Get_BBox(&face->glyph->outline, &bbox);
308 if (!error)
309 {
310 an = code_to_adobename(i | 0x1000000);
311
312 ti = newchar(fnt);
313 ti->charcode = i | 0x1000000;
314 ti->glyphindex = i;
315 ti->adobename = an;
316 ti->llx = bbox.xMin * 1000 / fnt->units_per_em;
317 ti->lly = bbox.yMin * 1000 / fnt->units_per_em;
318 ti->urx = bbox.xMax * 1000 / fnt->units_per_em;
319 ti->ury = bbox.yMax * 1000 / fnt->units_per_em;
320
321 if (ti->lly > 0)
322 ti->lly = 0;
323 if (ti->ury < 0)
324 ti->ury = 0;
325 ti->width = transform(face->glyph->metrics.horiAdvance*1000 / fnt->units_per_em,
326 0, fnt->efactor, fnt->slant);
327
328 if (!quiet)
329 printf("%5d %-25s %5d % 5d,% 5d -- % 5d,% 5d\n",
330 i, ti->adobename,
331 ti->width,
332 ti->llx, ti->lly, ti->urx, ti->ury);
333
334 if (j < 256)
335 {
336 fnt->inencptrs[j] = ti;
337 ti->incode = j;
338 }
339 else
340 break;
341 j++;
342 }
343 }
344 }
345 }
346
347 /* Finally, we construct a `Germandbls' glyph if necessary */
348
349 if (!only_range)
350 {
351 if (NULL == findadobe("Germandbls", fnt->charlist) &&
352 NULL != (Ti = findadobe("S", fnt->charlist)))
353 {
354 pcc *np, *nq;
355
356
357 ti = newchar(fnt);
358 ti->charcode = face->num_glyphs | 0x1000000;
359 ti->glyphindex = face->num_glyphs;
360 ti->adobename = "Germandbls";
361 ti->width = Ti->width << 1;
362 ti->llx = Ti->llx;
363 ti->lly = Ti->lly;
364 ti->urx = Ti->width + Ti->urx;
365 ti->ury = Ti->ury;
366 ti->kerns = Ti->kerns;
367
368 np = newpcc();
369 np->partname = "S";
370 nq = newpcc();
371 nq->partname = "S";
372 nq->xoffset = Ti->width;
373 np->next = nq;
374 ti->pccs = np;
375 ti->constructed = True;
376
377 if (!quiet)
378 printf("* %-25s %5d % 5d,% 5d -- % 5d,% 5d\n",
379 ti->adobename,
380 ti->width,
381 ti->llx, ti->lly, ti->urx, ti->ury);
382 }
383 }
384
385 /* kerning between subfonts isn't available */
386 if (!only_range)
387 readttf_kern(fnt);
388 }
389
390
391 /* end */
392