winmm: Avoid explicitly casting the pointer returned from Heap(Re)Alloc.
[wine.git] / dlls / wineps.drv / afm.c
blob0f3f89b5f5c71df7677fae1968a4ff81f6c4fd08
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.
6 * Copyright 1998 Huw D M Davies
7 * Copyright 2001 Ian Pilcher
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.
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.
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
24 #include <string.h>
25 #include <stdlib.h>
27 #include "psdrv.h"
28 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
32 /* ptr to fonts for which we have afm files */
33 FONTFAMILY *PSDRV_AFMFontList = NULL;
36 /***********************************************************
38 * PSDRV_FreeAFMList
40 * Frees the family and afmlistentry structures in list head
42 void PSDRV_FreeAFMList( FONTFAMILY *head )
44 AFMLISTENTRY *afmle, *nexta;
45 FONTFAMILY *family, *nextf;
47 for(nextf = family = head; nextf; family = nextf) {
48 for(nexta = afmle = family->afmlist; nexta; afmle = nexta) {
49 nexta = afmle->next;
50 HeapFree( PSDRV_Heap, 0, afmle );
52 nextf = family->next;
53 HeapFree( PSDRV_Heap, 0, family );
55 return;
59 /***********************************************************
61 * PSDRV_FindAFMinList
62 * Returns ptr to an AFM if name (which is a PS font name) exists in list
63 * headed by head.
65 const AFM *PSDRV_FindAFMinList(FONTFAMILY *head, LPCSTR name)
67 FONTFAMILY *family;
68 AFMLISTENTRY *afmle;
70 for(family = head; family; family = family->next) {
71 for(afmle = family->afmlist; afmle; afmle = afmle->next) {
72 if(!strcmp(afmle->afm->FontName, name))
73 return afmle->afm;
76 return NULL;
79 /***********************************************************
81 * PSDRV_AddAFMtoList
83 * Adds an afm to the list whose head is pointed to by head. Creates new
84 * family node if necessary and always creates a new AFMLISTENTRY.
86 * Returns FALSE for memory allocation error; returns TRUE, but sets *p_added
87 * to FALSE, for duplicate.
89 BOOL PSDRV_AddAFMtoList(FONTFAMILY **head, const AFM *afm, BOOL *p_added)
91 FONTFAMILY *family = *head;
92 FONTFAMILY **insert = head;
93 AFMLISTENTRY *tmpafmle, *newafmle;
95 newafmle = HeapAlloc(PSDRV_Heap, HEAP_ZERO_MEMORY,
96 sizeof(*newafmle));
97 if (newafmle == NULL)
98 return FALSE;
100 newafmle->afm = afm;
102 while(family) {
103 if(!wcscmp(family->FamilyName, afm->FamilyName))
104 break;
105 insert = &(family->next);
106 family = family->next;
109 if(!family) {
110 family = HeapAlloc(PSDRV_Heap, HEAP_ZERO_MEMORY,
111 sizeof(*family));
112 if (family == NULL) {
113 HeapFree(PSDRV_Heap, 0, newafmle);
114 return FALSE;
116 *insert = family;
117 if (!(family->FamilyName = HeapAlloc(PSDRV_Heap, 0, (wcslen(afm->FamilyName)+1)*sizeof(WCHAR) ))) {
118 HeapFree(PSDRV_Heap, 0, family);
119 HeapFree(PSDRV_Heap, 0, newafmle);
120 return FALSE;
122 wcscpy( family->FamilyName, afm->FamilyName );
123 family->afmlist = newafmle;
124 *p_added = TRUE;
125 return TRUE;
127 else {
128 tmpafmle = family->afmlist;
129 while (tmpafmle) {
130 if (!strcmp(tmpafmle->afm->FontName, afm->FontName)) {
131 WARN("Ignoring duplicate FontName '%s'\n", afm->FontName);
132 HeapFree(PSDRV_Heap, 0, newafmle);
133 *p_added = FALSE;
134 return TRUE; /* not a fatal error */
136 tmpafmle = tmpafmle->next;
140 tmpafmle = family->afmlist;
141 while(tmpafmle->next)
142 tmpafmle = tmpafmle->next;
144 tmpafmle->next = newafmle;
146 *p_added = TRUE;
147 return TRUE;
151 /***********************************************************
153 * PSDRV_DumpFontList
156 static void PSDRV_DumpFontList(void)
158 FONTFAMILY *family;
159 AFMLISTENTRY *afmle;
161 for(family = PSDRV_AFMFontList; family; family = family->next) {
162 TRACE("Family %s\n", debugstr_w(family->FamilyName));
163 for(afmle = family->afmlist; afmle; afmle = afmle->next)
165 #if 0
166 INT i;
167 #endif
169 TRACE("\tFontName '%s' (%i glyphs) - %s encoding:\n",
170 afmle->afm->FontName, afmle->afm->NumofMetrics,
171 debugstr_w(afmle->afm->EncodingScheme));
173 /* Uncomment to regenerate font data; see afm2c.c */
175 /* PSDRV_AFM2C(afmle->afm); */
177 #if 0
178 for (i = 0; i < afmle->afm->NumofMetrics; ++i)
180 TRACE("\t\tU+%.4lX; C %i; N '%s'\n", afmle->afm->Metrics[i].UV,
181 afmle->afm->Metrics[i].C, afmle->afm->Metrics[i].N->sz);
183 #endif
186 return;
189 /******************************************************************************
190 * PSDRV_UVMetrics
192 * Find the AFMMETRICS for a given UV. Returns NULL if the font does not
193 * have a glyph for the given UV.
195 static int __cdecl MetricsByUV(const void *a, const void *b)
197 return (int)(((const AFMMETRICS *)a)->UV - ((const AFMMETRICS *)b)->UV);
200 static const AFMMETRICS *PSDRV_UVMetrics(LONG UV, const AFM *afm)
202 AFMMETRICS key;
205 * Ugly work-around for symbol fonts. Wine is sending characters which
206 * belong in the Unicode private use range (U+F020 - U+F0FF) as ASCII
207 * characters (U+0020 - U+00FF).
210 if ((afm->Metrics->UV & 0xff00) == 0xf000 && UV < 0x100)
211 UV |= 0xf000;
213 key.UV = UV;
214 return bsearch(&key, afm->Metrics, afm->NumofMetrics, sizeof(AFMMETRICS), MetricsByUV);
217 /*******************************************************************************
218 * PSDRV_CalcAvgCharWidth
220 * Calculate WinMetrics.sAvgCharWidth for a Type 1 font. Can also be used on
221 * TrueType fonts, if font designer set OS/2:xAvgCharWidth to zero.
223 * Tries to use formula in TrueType specification; falls back to simple mean
224 * if any lowercase latin letter (or space) is not present.
226 static inline SHORT MeanCharWidth(const AFM *afm)
228 float w = 0.0;
229 int i;
231 for (i = 0; i < afm->NumofMetrics; ++i)
232 w += afm->Metrics[i].WX;
234 w /= afm->NumofMetrics;
236 return (SHORT)(w + 0.5);
239 static const struct { LONG UV; int weight; } UVweight[] =
241 { 0x0061, 64 }, { 0x0062, 14 }, { 0x0063, 27 }, { 0x0064, 35 },
242 { 0x0065, 100 }, { 0x0066, 20 }, { 0x0067, 14 }, { 0x0068, 42 },
243 { 0x0069, 63 }, { 0x006a, 3 }, { 0x006b, 6 }, { 0x006c, 35 },
244 { 0x006d, 20 }, { 0x006e, 56 }, { 0x006f, 56 }, { 0x0070, 17 },
245 { 0x0071, 4 }, { 0x0072, 49 }, { 0x0073, 56 }, { 0x0074, 71 },
246 { 0x0075, 31 }, { 0x0076, 10 }, { 0x0077, 18 }, { 0x0078, 3 },
247 { 0x0079, 18 }, { 0x007a, 2 }, { 0x0020, 166 }
250 SHORT PSDRV_CalcAvgCharWidth(const AFM *afm)
252 float w = 0.0;
253 int i;
255 for (i = 0; i < ARRAY_SIZE(UVweight); ++i)
257 const AFMMETRICS *afmm;
259 afmm = PSDRV_UVMetrics(UVweight[i].UV, afm);
260 if (!afmm)
261 return MeanCharWidth(afm);
263 w += afmm->WX * (float)(UVweight[i].weight);
266 w /= 1000.0;
268 return (SHORT)(w + 0.5);
272 /*******************************************************************************
273 * AddBuiltinAFMs
277 static BOOL AddBuiltinAFMs(void)
279 const AFM *const *afm = PSDRV_BuiltinAFMs;
281 while (*afm != NULL)
283 BOOL added;
285 if (PSDRV_AddAFMtoList(&PSDRV_AFMFontList, *afm, &added) == FALSE)
286 return FALSE;
288 if (added == FALSE)
289 TRACE("Ignoring built-in font %s\n", (*afm)->FontName);
291 ++afm;
294 return TRUE;
298 /***********************************************************
300 * PSDRV_GetFontMetrics
302 * Parses all afm files listed in the
303 * HKEY_CURRENT_USER\\Software\\Wine\\Fonts registry key.
304 * Adds built-in data last, so it can be overridden by
305 * user-supplied AFM or TTF files.
307 * If this function fails, PSDRV_Init will destroy PSDRV_Heap, so don't worry
308 * about freeing all the memory that's been allocated.
311 BOOL PSDRV_GetFontMetrics(void)
313 if (PSDRV_GlyphListInit() != 0)
314 return FALSE;
316 if (PSDRV_GetType1Metrics() == FALSE)
317 return FALSE;
319 if (AddBuiltinAFMs() == FALSE)
320 return FALSE;
322 PSDRV_IndexGlyphList(); /* Enable fast searching of glyph names */
324 PSDRV_DumpFontList();
326 return TRUE;