gdiplus: Implement GdipSetPathGradientBlend, with tests.
[wine/multimedia.git] / dlls / wineps.drv / afm.c
blobe07187e3901a56565ffd8f80cda924cd95651a3b
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 "config.h"
26 #include <string.h>
28 #include "psdrv.h"
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
33 /* ptr to fonts for which we have afm files */
34 DECLSPEC_HIDDEN FONTFAMILY *PSDRV_AFMFontList = NULL;
37 /***********************************************************
39 * PSDRV_FreeAFMList
41 * Frees the family and afmlistentry structures in list head
43 void PSDRV_FreeAFMList( FONTFAMILY *head )
45 AFMLISTENTRY *afmle, *nexta;
46 FONTFAMILY *family, *nextf;
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 );
53 nextf = family->next;
54 HeapFree( PSDRV_Heap, 0, family );
56 return;
60 /***********************************************************
62 * PSDRV_FindAFMinList
63 * Returns ptr to an AFM if name (which is a PS font name) exists in list
64 * headed by head.
66 const AFM *PSDRV_FindAFMinList(FONTFAMILY *head, LPCSTR name)
68 FONTFAMILY *family;
69 AFMLISTENTRY *afmle;
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;
77 return NULL;
80 /***********************************************************
82 * PSDRV_AddAFMtoList
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.
87 * Returns FALSE for memory allocation error; returns TRUE, but sets *p_added
88 * to FALSE, for duplicate.
90 BOOL PSDRV_AddAFMtoList(FONTFAMILY **head, const AFM *afm, BOOL *p_added)
92 FONTFAMILY *family = *head;
93 FONTFAMILY **insert = head;
94 AFMLISTENTRY *tmpafmle, *newafmle;
96 newafmle = HeapAlloc(PSDRV_Heap, HEAP_ZERO_MEMORY,
97 sizeof(*newafmle));
98 if (newafmle == NULL)
99 return FALSE;
101 newafmle->afm = afm;
103 while(family) {
104 if(!strcmp(family->FamilyName, afm->FamilyName))
105 break;
106 insert = &(family->next);
107 family = family->next;
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;
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;
123 strcpy( family->FamilyName, afm->FamilyName );
124 family->afmlist = newafmle;
125 *p_added = TRUE;
126 return TRUE;
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 */
137 tmpafmle = tmpafmle->next;
141 tmpafmle = family->afmlist;
142 while(tmpafmle->next)
143 tmpafmle = tmpafmle->next;
145 tmpafmle->next = newafmle;
147 *p_added = TRUE;
148 return TRUE;
152 /***********************************************************
154 * PSDRV_DumpFontList
157 static void PSDRV_DumpFontList(void)
159 FONTFAMILY *family;
160 AFMLISTENTRY *afmle;
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)
166 #if 0
167 INT i;
168 #endif
170 TRACE("\tFontName '%s' (%i glyphs) - '%s' encoding:\n",
171 afmle->afm->FontName, afmle->afm->NumofMetrics,
172 afmle->afm->EncodingScheme);
174 /* Uncomment to regenerate font data; see afm2c.c */
176 /* PSDRV_AFM2C(afmle->afm); */
178 #if 0
179 for (i = 0; i < afmle->afm->NumofMetrics; ++i)
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);
184 #endif
187 return;
191 /*******************************************************************************
192 * PSDRV_CalcAvgCharWidth
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.
197 * Tries to use formula in TrueType specification; falls back to simple mean
198 * if any lowercase latin letter (or space) is not present.
200 static inline SHORT MeanCharWidth(const AFM *afm)
202 float w = 0.0;
203 int i;
205 for (i = 0; i < afm->NumofMetrics; ++i)
206 w += afm->Metrics[i].WX;
208 w /= afm->NumofMetrics;
210 return (SHORT)(w + 0.5);
213 static const struct { LONG UV; int weight; } UVweight[27] =
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 }
224 SHORT PSDRV_CalcAvgCharWidth(const AFM *afm)
226 float w = 0.0;
227 int i;
229 for (i = 0; i < 27; ++i)
231 const AFMMETRICS *afmm;
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 */
237 w += afmm->WX * (float)(UVweight[i].weight);
240 w /= 1000.0;
242 return (SHORT)(w + 0.5);
246 /*******************************************************************************
247 * AddBuiltinAFMs
251 static BOOL AddBuiltinAFMs(void)
253 const AFM *const *afm = PSDRV_BuiltinAFMs;
255 while (*afm != NULL)
257 BOOL added;
259 if (PSDRV_AddAFMtoList(&PSDRV_AFMFontList, *afm, &added) == FALSE)
260 return FALSE;
262 if (added == FALSE)
263 TRACE("Ignoring built-in font %s\n", (*afm)->FontName);
265 ++afm;
268 return TRUE;
272 /***********************************************************
274 * PSDRV_GetFontMetrics
276 * Parses all afm files listed in the
277 * HKEY_CURRENT_USER\\Software\\Wine\\Fonts registry key.
278 * Adds built-in data last, so it can be overridden by
279 * user-supplied AFM or TTF files.
281 * If this function fails, PSDRV_Init will destroy PSDRV_Heap, so don't worry
282 * about freeing all the memory that's been allocated.
285 BOOL PSDRV_GetFontMetrics(void)
287 if (PSDRV_GlyphListInit() != 0)
288 return FALSE;
290 if (PSDRV_GetType1Metrics() == FALSE)
291 return FALSE;
293 if (AddBuiltinAFMs() == FALSE)
294 return FALSE;
296 PSDRV_IndexGlyphList(); /* Enable fast searching of glyph names */
298 PSDRV_DumpFontList();
300 return TRUE;