quartz: Fix IReferenceClock::GetTime() implementation for system clock.
[wine] / dlls / wineps.drv / afm.c
1 /*
2  *      Font metric functions common to Type 1 (AFM) and TrueType font files.
3  *      Functions specific to Type 1 and TrueType fonts are in type1afm.c and
4  *      truetype.c respectively.
5  *
6  *      Copyright 1998  Huw D M Davies
7  *      Copyright 2001  Ian Pilcher
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23
24 #include "config.h"
25
26 #include <string.h>
27
28 #include "psdrv.h"
29 #include "wine/debug.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
32
33 /* ptr to fonts for which we have afm files */
34 FONTFAMILY *PSDRV_AFMFontList = NULL;
35
36
37 /***********************************************************
38  *
39  *      PSDRV_FreeAFMList
40  *
41  * Frees the family and afmlistentry structures in list head
42  */
43 void PSDRV_FreeAFMList( FONTFAMILY *head )
44 {
45     AFMLISTENTRY *afmle, *nexta;
46     FONTFAMILY *family, *nextf;
47
48     for(nextf = family = head; nextf; family = nextf) {
49         for(nexta = afmle = family->afmlist; nexta; afmle = nexta) {
50             nexta = afmle->next;
51             HeapFree( PSDRV_Heap, 0, afmle );
52         }
53         nextf = family->next;
54         HeapFree( PSDRV_Heap, 0, family );
55     }
56     return;
57 }
58
59
60 /***********************************************************
61  *
62  *      PSDRV_FindAFMinList
63  * Returns ptr to an AFM if name (which is a PS font name) exists in list
64  * headed by head.
65  */
66 const AFM *PSDRV_FindAFMinList(FONTFAMILY *head, LPCSTR name)
67 {
68     FONTFAMILY *family;
69     AFMLISTENTRY *afmle;
70
71     for(family = head; family; family = family->next) {
72         for(afmle = family->afmlist; afmle; afmle = afmle->next) {
73             if(!strcmp(afmle->afm->FontName, name))
74                 return afmle->afm;
75         }
76     }
77     return NULL;
78 }
79
80 /***********************************************************
81  *
82  *      PSDRV_AddAFMtoList
83  *
84  *  Adds an afm to the list whose head is pointed to by head. Creates new
85  *  family node if necessary and always creates a new AFMLISTENTRY.
86  *
87  *  Returns FALSE for memory allocation error; returns TRUE, but sets *p_added
88  *  to FALSE, for duplicate.
89  */
90 BOOL PSDRV_AddAFMtoList(FONTFAMILY **head, const AFM *afm, BOOL *p_added)
91 {
92     FONTFAMILY *family = *head;
93     FONTFAMILY **insert = head;
94     AFMLISTENTRY *tmpafmle, *newafmle;
95
96     newafmle = HeapAlloc(PSDRV_Heap, HEAP_ZERO_MEMORY,
97                            sizeof(*newafmle));
98     if (newafmle == NULL)
99         return FALSE;
100
101     newafmle->afm = afm;
102
103     while(family) {
104         if(!strcmp(family->FamilyName, afm->FamilyName))
105             break;
106         insert = &(family->next);
107         family = family->next;
108     }
109
110     if(!family) {
111         family = HeapAlloc(PSDRV_Heap, HEAP_ZERO_MEMORY,
112                            sizeof(*family));
113         if (family == NULL) {
114             HeapFree(PSDRV_Heap, 0, newafmle);
115             return FALSE;
116         }
117         *insert = family;
118         if (!(family->FamilyName = HeapAlloc(PSDRV_Heap, 0, strlen(afm->FamilyName)+1 ))) {
119             HeapFree(PSDRV_Heap, 0, family);
120             HeapFree(PSDRV_Heap, 0, newafmle);
121             return FALSE;
122         }
123         strcpy( family->FamilyName, afm->FamilyName );
124         family->afmlist = newafmle;
125         *p_added = TRUE;
126         return TRUE;
127     }
128     else {
129         tmpafmle = family->afmlist;
130         while (tmpafmle) {
131             if (!strcmp(tmpafmle->afm->FontName, afm->FontName)) {
132                 WARN("Ignoring duplicate FontName '%s'\n", afm->FontName);
133                 HeapFree(PSDRV_Heap, 0, newafmle);
134                 *p_added = FALSE;
135                 return TRUE;                        /* not a fatal error */
136             }
137             tmpafmle = tmpafmle->next;
138         }
139     }
140
141     tmpafmle = family->afmlist;
142     while(tmpafmle->next)
143         tmpafmle = tmpafmle->next;
144
145     tmpafmle->next = newafmle;
146
147     *p_added = TRUE;
148     return TRUE;
149 }
150
151
152 /***********************************************************
153  *
154  *      PSDRV_DumpFontList
155  *
156  */
157 static void PSDRV_DumpFontList(void)
158 {
159     FONTFAMILY      *family;
160     AFMLISTENTRY    *afmle;
161
162     for(family = PSDRV_AFMFontList; family; family = family->next) {
163         TRACE("Family '%s'\n", family->FamilyName);
164         for(afmle = family->afmlist; afmle; afmle = afmle->next)
165         {
166 #if 0
167             INT i;
168 #endif
169
170             TRACE("\tFontName '%s' (%i glyphs) - '%s' encoding:\n",
171                     afmle->afm->FontName, afmle->afm->NumofMetrics,
172                     afmle->afm->EncodingScheme);
173
174             /* Uncomment to regenerate font data; see afm2c.c */
175
176             /* PSDRV_AFM2C(afmle->afm); */
177
178 #if 0
179             for (i = 0; i < afmle->afm->NumofMetrics; ++i)
180             {
181                 TRACE("\t\tU+%.4lX; C %i; N '%s'\n", afmle->afm->Metrics[i].UV,
182                         afmle->afm->Metrics[i].C, afmle->afm->Metrics[i].N->sz);
183             }
184 #endif
185         }
186     }
187     return;
188 }
189
190
191 /*******************************************************************************
192  *  PSDRV_CalcAvgCharWidth
193  *
194  *  Calculate WinMetrics.sAvgCharWidth for a Type 1 font.  Can also be used on
195  *  TrueType fonts, if font designer set OS/2:xAvgCharWidth to zero.
196  *
197  *  Tries to use formula in TrueType specification; falls back to simple mean
198  *  if any lowercase latin letter (or space) is not present.
199  */
200 static inline SHORT MeanCharWidth(const AFM *afm)
201 {
202     float   w = 0.0;
203     int     i;
204
205     for (i = 0; i < afm->NumofMetrics; ++i)
206         w += afm->Metrics[i].WX;
207
208     w /= afm->NumofMetrics;
209
210     return (SHORT)(w + 0.5);
211 }
212
213 static const struct { LONG UV; int weight; } UVweight[27] =
214 {
215     { 0x0061,  64 }, { 0x0062,  14 }, { 0x0063,  27 }, { 0x0064,  35 },
216     { 0x0065, 100 }, { 0x0066,  20 }, { 0x0067,  14 }, { 0x0068,  42 },
217     { 0x0069,  63 }, { 0x006a,   3 }, { 0x006b,   6 }, { 0x006c,  35 },
218     { 0x006d,  20 }, { 0x006e,  56 }, { 0x006f,  56 }, { 0x0070,  17 },
219     { 0x0071,   4 }, { 0x0072,  49 }, { 0x0073,  56 }, { 0x0074,  71 },
220     { 0x0075,  31 }, { 0x0076,  10 }, { 0x0077,  18 }, { 0x0078,   3 },
221     { 0x0079,  18 }, { 0x007a,   2 }, { 0x0020, 166 }
222 };
223
224 SHORT PSDRV_CalcAvgCharWidth(const AFM *afm)
225 {
226     float   w = 0.0;
227     int     i;
228
229     for (i = 0; i < 27; ++i)
230     {
231         const AFMMETRICS    *afmm;
232
233         afmm = PSDRV_UVMetrics(UVweight[i].UV, afm);
234         if (afmm->UV != UVweight[i].UV)     /* UVMetrics returns first glyph */
235             return MeanCharWidth(afm);      /*   in font if UV is missing    */
236
237         w += afmm->WX * (float)(UVweight[i].weight);
238     }
239
240     w /= 1000.0;
241
242     return (SHORT)(w + 0.5);
243 }
244
245
246 /*******************************************************************************
247  *  AddBuiltinAFMs
248  *
249  */
250
251 static BOOL AddBuiltinAFMs(void)
252 {
253     const AFM *const    *afm = PSDRV_BuiltinAFMs;
254
255     while (*afm != NULL)
256     {
257         BOOL    added;
258
259         if (PSDRV_AddAFMtoList(&PSDRV_AFMFontList, *afm, &added) == FALSE)
260             return FALSE;
261
262         if (added == FALSE)
263             TRACE("Ignoring built-in font %s\n", (*afm)->FontName);
264
265         ++afm;
266     }
267
268     return TRUE;
269 }
270
271
272 /***********************************************************
273  *
274  *      PSDRV_GetFontMetrics
275  *
276  * Parses all afm files listed in [afmdirs] and [TrueType Font Directories]
277  * sections of Wine configuration file.  Adds built-in data last, so it can
278  * be overridden by user-supplied AFM or TTF files.
279  *
280  * If this function fails, PSDRV_Init will destroy PSDRV_Heap, so don't worry
281  * about freeing all the memory that's been allocated.
282  */
283
284 BOOL PSDRV_GetFontMetrics(void)
285 {
286     if (PSDRV_GlyphListInit() != 0)
287         return FALSE;
288
289     if (PSDRV_GetType1Metrics() == FALSE)
290         return FALSE;
291
292 #ifdef HAVE_FREETYPE
293     if (PSDRV_GetTrueTypeMetrics() == FALSE)
294         return FALSE;
295 #endif
296
297     if (AddBuiltinAFMs() == FALSE)
298         return FALSE;
299
300     PSDRV_IndexGlyphList();         /* Enable fast searching of glyph names */
301
302     PSDRV_DumpFontList();
303
304     return TRUE;
305 }