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