afm.c 7.76 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1
/*
2 3 4
 *	Font metric functions common to Type 1 (AFM) and TrueType font files.
 *  	Functions specific to Type 1 and TrueType fonts are in type1afm.c and
 *  	truetype.c respectively.
Alexandre Julliard's avatar
Alexandre Julliard committed
5 6
 *
 *	Copyright 1998  Huw D M Davies
7
 *  	Copyright 2001  Ian Pilcher
8 9 10 11 12 13 14 15 16 17 18 19 20
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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
Alexandre Julliard's avatar
Alexandre Julliard committed
22 23
 */

24 25
#include "config.h"

Alexandre Julliard's avatar
Alexandre Julliard committed
26
#include <string.h>
27

Alexandre Julliard's avatar
Alexandre Julliard committed
28
#include "psdrv.h"
29
#include "wine/debug.h"
30

31
WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
Alexandre Julliard's avatar
Alexandre Julliard committed
32 33

/* ptr to fonts for which we have afm files */
Alexandre Julliard's avatar
Alexandre Julliard committed
34
FONTFAMILY *PSDRV_AFMFontList = NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
35 36


Alexandre Julliard's avatar
Alexandre Julliard committed
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
/***********************************************************
 *
 *	PSDRV_FreeAFMList
 *
 * Frees the family and afmlistentry structures in list head
 */
void PSDRV_FreeAFMList( FONTFAMILY *head )
{
    AFMLISTENTRY *afmle, *nexta;
    FONTFAMILY *family, *nextf;

    for(nextf = family = head; nextf; family = nextf) {
        for(nexta = afmle = family->afmlist; nexta; afmle = nexta) {
	    nexta = afmle->next;
	    HeapFree( PSDRV_Heap, 0, afmle );
	}
        nextf = family->next;
	HeapFree( PSDRV_Heap, 0, family );
    }
    return;
}


/***********************************************************
 *
 *	PSDRV_FindAFMinList
 * Returns ptr to an AFM if name (which is a PS font name) exists in list
 * headed by head.
 */
66
const AFM *PSDRV_FindAFMinList(FONTFAMILY *head, LPCSTR name)
Alexandre Julliard's avatar
Alexandre Julliard committed
67 68 69 70 71 72 73 74 75 76 77 78 79
{
    FONTFAMILY *family;
    AFMLISTENTRY *afmle;

    for(family = head; family; family = family->next) {
        for(afmle = family->afmlist; afmle; afmle = afmle->next) {
	    if(!strcmp(afmle->afm->FontName, name))
	        return afmle->afm;
	}
    }
    return NULL;
}

Alexandre Julliard's avatar
Alexandre Julliard committed
80 81 82 83
/***********************************************************
 *
 *	PSDRV_AddAFMtoList
 *
84 85 86 87 88
 *  Adds an afm to the list whose head is pointed to by head. Creates new
 *  family node if necessary and always creates a new AFMLISTENTRY.
 *
 *  Returns FALSE for memory allocation error; returns TRUE, but sets *p_added
 *  to FALSE, for duplicate.
Alexandre Julliard's avatar
Alexandre Julliard committed
89
 */
90
BOOL PSDRV_AddAFMtoList(FONTFAMILY **head, const AFM *afm, BOOL *p_added)
Alexandre Julliard's avatar
Alexandre Julliard committed
91
{
Alexandre Julliard's avatar
Alexandre Julliard committed
92 93 94 95 96 97
    FONTFAMILY *family = *head;
    FONTFAMILY **insert = head;
    AFMLISTENTRY *tmpafmle, *newafmle;

    newafmle = HeapAlloc(PSDRV_Heap, HEAP_ZERO_MEMORY,
			   sizeof(*newafmle));
98 99
    if (newafmle == NULL)
    	return FALSE;
100

Alexandre Julliard's avatar
Alexandre Julliard committed
101
    newafmle->afm = afm;
Alexandre Julliard's avatar
Alexandre Julliard committed
102 103 104 105 106 107 108

    while(family) {
        if(!strcmp(family->FamilyName, afm->FamilyName))
	    break;
	insert = &(family->next);
	family = family->next;
    }
109

Alexandre Julliard's avatar
Alexandre Julliard committed
110
    if(!family) {
Alexandre Julliard's avatar
Alexandre Julliard committed
111
        family = HeapAlloc(PSDRV_Heap, HEAP_ZERO_MEMORY,
Alexandre Julliard's avatar
Alexandre Julliard committed
112
			   sizeof(*family));
113 114 115 116
	if (family == NULL) {
	    HeapFree(PSDRV_Heap, 0, newafmle);
	    return FALSE;
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
117
	*insert = family;
118
	if (!(family->FamilyName = HeapAlloc(PSDRV_Heap, 0, strlen(afm->FamilyName)+1 ))) {
119 120 121 122
	    HeapFree(PSDRV_Heap, 0, family);
	    HeapFree(PSDRV_Heap, 0, newafmle);
	    return FALSE;
	}
123
	strcpy( family->FamilyName, afm->FamilyName );
Alexandre Julliard's avatar
Alexandre Julliard committed
124
	family->afmlist = newafmle;
125
	*p_added = TRUE;
126
	return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
127
    }
128 129 130 131 132 133
    else {
    	tmpafmle = family->afmlist;
	while (tmpafmle) {
	    if (!strcmp(tmpafmle->afm->FontName, afm->FontName)) {
	    	WARN("Ignoring duplicate FontName '%s'\n", afm->FontName);
		HeapFree(PSDRV_Heap, 0, newafmle);
134
		*p_added = FALSE;
135 136 137 138 139
		return TRUE;	    	    	    /* not a fatal error */
	    }
	    tmpafmle = tmpafmle->next;
	}
    }
140

Alexandre Julliard's avatar
Alexandre Julliard committed
141 142 143
    tmpafmle = family->afmlist;
    while(tmpafmle->next)
        tmpafmle = tmpafmle->next;
Alexandre Julliard's avatar
Alexandre Julliard committed
144

Alexandre Julliard's avatar
Alexandre Julliard committed
145
    tmpafmle->next = newafmle;
Alexandre Julliard's avatar
Alexandre Julliard committed
146

147
    *p_added = TRUE;
148
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
149
}
Alexandre Julliard's avatar
Alexandre Julliard committed
150

Alexandre Julliard's avatar
Alexandre Julliard committed
151 152 153 154 155 156 157 158

/***********************************************************
 *
 *	PSDRV_DumpFontList
 *
 */
static void PSDRV_DumpFontList(void)
{
159 160
    FONTFAMILY      *family;
    AFMLISTENTRY    *afmle;
Alexandre Julliard's avatar
Alexandre Julliard committed
161 162

    for(family = PSDRV_AFMFontList; family; family = family->next) {
163
        TRACE("Family '%s'\n", family->FamilyName);
164 165
	for(afmle = family->afmlist; afmle; afmle = afmle->next)
	{
166
#if 0
167
	    INT i;
168
#endif
169

170 171 172
	    TRACE("\tFontName '%s' (%i glyphs) - '%s' encoding:\n",
	    	    afmle->afm->FontName, afmle->afm->NumofMetrics,
		    afmle->afm->EncodingScheme);
173

174
	    /* Uncomment to regenerate font data; see afm2c.c */
175

176
	    /* PSDRV_AFM2C(afmle->afm); */
177

178
#if 0
179 180 181 182 183
	    for (i = 0; i < afmle->afm->NumofMetrics; ++i)
	    {
	    	TRACE("\t\tU+%.4lX; C %i; N '%s'\n", afmle->afm->Metrics[i].UV,
		    	afmle->afm->Metrics[i].C, afmle->afm->Metrics[i].N->sz);
	    }
184
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
185 186 187 188 189 190
	}
    }
    return;
}


191 192 193 194 195 196 197 198 199
/*******************************************************************************
 *  PSDRV_CalcAvgCharWidth
 *
 *  Calculate WinMetrics.sAvgCharWidth for a Type 1 font.  Can also be used on
 *  TrueType fonts, if font designer set OS/2:xAvgCharWidth to zero.
 *
 *  Tries to use formula in TrueType specification; falls back to simple mean
 *  if any lowercase latin letter (or space) is not present.
 */
200
static inline SHORT MeanCharWidth(const AFM *afm)
201 202 203
{
    float   w = 0.0;
    int     i;
204

205 206
    for (i = 0; i < afm->NumofMetrics; ++i)
    	w += afm->Metrics[i].WX;
207

208
    w /= afm->NumofMetrics;
209

210 211 212 213 214 215 216 217 218 219 220 221 222
    return (SHORT)(w + 0.5);
}

static const struct { LONG UV; int weight; } UVweight[27] =
{
    { 0x0061,  64 }, { 0x0062,  14 }, { 0x0063,  27 }, { 0x0064,  35 },
    { 0x0065, 100 }, { 0x0066,  20 }, { 0x0067,  14 }, { 0x0068,  42 },
    { 0x0069,  63 }, { 0x006a,   3 }, { 0x006b,   6 }, { 0x006c,  35 },
    { 0x006d,  20 }, { 0x006e,  56 }, { 0x006f,  56 }, { 0x0070,  17 },
    { 0x0071,   4 }, { 0x0072,  49 }, { 0x0073,  56 }, { 0x0074,  71 },
    { 0x0075,  31 }, { 0x0076,  10 }, { 0x0077,  18 }, { 0x0078,   3 },
    { 0x0079,  18 }, { 0x007a,   2 }, { 0x0020, 166 }
};
223

224 225 226 227
SHORT PSDRV_CalcAvgCharWidth(const AFM *afm)
{
    float   w = 0.0;
    int     i;
228

229 230 231
    for (i = 0; i < 27; ++i)
    {
    	const AFMMETRICS    *afmm;
232

233 234 235
	afmm = PSDRV_UVMetrics(UVweight[i].UV, afm);
	if (afmm->UV != UVweight[i].UV)     /* UVMetrics returns first glyph */
	    return MeanCharWidth(afm);	    /*   in font if UV is missing    */
236

237 238
	w += afmm->WX * (float)(UVweight[i].weight);
    }
239

240
    w /= 1000.0;
241

242 243 244
    return (SHORT)(w + 0.5);
}

245

246 247 248 249
/*******************************************************************************
 *  AddBuiltinAFMs
 *
 */
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 263
	if (added == FALSE)
	    TRACE("Ignoring built-in font %s\n", (*afm)->FontName);
264

265
	++afm;
266
    }
267

268 269 270 271
    return TRUE;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
272 273 274 275
/***********************************************************
 *
 *	PSDRV_GetFontMetrics
 *
276 277 278
 * Parses all afm files listed in [afmdirs] and [TrueType Font Directories]
 * sections of Wine configuration file.  Adds built-in data last, so it can
 * be overridden by user-supplied AFM or TTF files.
279 280 281
 *
 * If this function fails, PSDRV_Init will destroy PSDRV_Heap, so don't worry
 * about freeing all the memory that's been allocated.
Alexandre Julliard's avatar
Alexandre Julliard committed
282
 */
283

284
BOOL PSDRV_GetFontMetrics(void)
Alexandre Julliard's avatar
Alexandre Julliard committed
285
{
286
    if (PSDRV_GlyphListInit() != 0)
287
    	return FALSE;
288

289
    if (PSDRV_GetType1Metrics() == FALSE)
290
    	return FALSE;
291

292
#ifdef HAVE_FREETYPE
293 294 295 296
    if (PSDRV_GetTrueTypeMetrics() == FALSE)
    	return FALSE;
#endif

297 298
    if (AddBuiltinAFMs() == FALSE)
    	return FALSE;
299

300
    PSDRV_IndexGlyphList(); 	    /* Enable fast searching of glyph names */
301

Alexandre Julliard's avatar
Alexandre Julliard committed
302
    PSDRV_DumpFontList();
303

Alexandre Julliard's avatar
Alexandre Julliard committed
304 305
    return TRUE;
}