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