font.c 10.5 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1
/*
Alexandre Julliard's avatar
Alexandre Julliard committed
2
 *	PostScript driver font functions
Alexandre Julliard's avatar
Alexandre Julliard committed
3 4 5 6 7
 *
 *	Copyright 1998  Huw D M Davies
 *
 */
#include <string.h>
8
#include "winspool.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
9
#include "psdrv.h"
10
#include "debugtools.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
11

12 13
DEFAULT_DEBUG_CHANNEL(psdrv)

Alexandre Julliard's avatar
Alexandre Julliard committed
14 15 16 17 18 19 20 21 22 23 24


/***********************************************************************
 *           PSDRV_FONT_SelectObject
 */
HFONT16 PSDRV_FONT_SelectObject( DC * dc, HFONT16 hfont,
                                        FONTOBJ *font )
{
    HFONT16 prevfont = dc->w.hFont;
    PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
    LOGFONT16 *lf = &(font->logfont);
25
    BOOL bd = FALSE, it = FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
26
    AFMLISTENTRY *afmle;
Alexandre Julliard's avatar
Alexandre Julliard committed
27
    AFM *afm;
Alexandre Julliard's avatar
Alexandre Julliard committed
28
    FONTFAMILY *family;
Alexandre Julliard's avatar
Alexandre Julliard committed
29 30 31
    char FaceName[LF_FACESIZE];


32
    TRACE("FaceName = '%s' Height = %d Italic = %d Weight = %d\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
33 34 35 36 37 38 39 40
	  lf->lfFaceName, lf->lfHeight, lf->lfItalic, lf->lfWeight);

    dc->w.hFont = hfont;

    if(lf->lfItalic)
        it = TRUE;
    if(lf->lfWeight > 550)
        bd = TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
41
    strcpy(FaceName, lf->lfFaceName);
Alexandre Julliard's avatar
Alexandre Julliard committed
42 43 44 45 46 47 48
    
    if(FaceName[0] == '\0') {
        switch(lf->lfPitchAndFamily & 0xf0) {
	case FF_DONTCARE:
	    break;
	case FF_ROMAN:
	case FF_SCRIPT:
Alexandre Julliard's avatar
Alexandre Julliard committed
49
	    strcpy(FaceName, "Times");
Alexandre Julliard's avatar
Alexandre Julliard committed
50 51
	    break;
	case FF_SWISS:
Alexandre Julliard's avatar
Alexandre Julliard committed
52
	    strcpy(FaceName, "Helvetica");
Alexandre Julliard's avatar
Alexandre Julliard committed
53 54
	    break;
	case FF_MODERN:
Alexandre Julliard's avatar
Alexandre Julliard committed
55
	    strcpy(FaceName, "Courier");
Alexandre Julliard's avatar
Alexandre Julliard committed
56 57
	    break;
	case FF_DECORATIVE:
Alexandre Julliard's avatar
Alexandre Julliard committed
58
	    strcpy(FaceName, "Symbol");
Alexandre Julliard's avatar
Alexandre Julliard committed
59 60 61 62 63 64 65
	    break;
	}
    }

    if(FaceName[0] == '\0') {
        switch(lf->lfPitchAndFamily & 0x0f) {
	case VARIABLE_PITCH:
Alexandre Julliard's avatar
Alexandre Julliard committed
66
	    strcpy(FaceName, "Times");
Alexandre Julliard's avatar
Alexandre Julliard committed
67 68
	    break;
	default:
Alexandre Julliard's avatar
Alexandre Julliard committed
69
	    strcpy(FaceName, "Courier");
Alexandre Julliard's avatar
Alexandre Julliard committed
70 71 72 73
	    break;
	}
    }

74
    TRACE("Trying to find facename '%s'\n", FaceName);
Alexandre Julliard's avatar
Alexandre Julliard committed
75

76
    /* Look for a matching font family */
Alexandre Julliard's avatar
Alexandre Julliard committed
77
    for(family = physDev->pi->Fonts; family; family = family->next) {
Alexandre Julliard's avatar
Alexandre Julliard committed
78
        if(!strcmp(FaceName, family->FamilyName))
Alexandre Julliard's avatar
Alexandre Julliard committed
79 80
	    break;
    }
81 82 83 84 85 86 87 88 89 90 91 92 93 94
    if(!family) {
	/* Fallback for Window's font families to common PostScript families */
	if(!strcmp(FaceName, "Arial"))
	    strcpy(FaceName, "Helvetica");
	else if(!strcmp(FaceName, "System"))
	    strcpy(FaceName, "Helvetica");
	else if(!strcmp(FaceName, "Times New Roman"))
	    strcpy(FaceName, "Times");
	for(family = physDev->pi->Fonts; family; family = family->next) {
	    if(!strcmp(FaceName, family->FamilyName))
		break;
	}
    }
    /* If all else fails, use the first font defined for the printer */
Alexandre Julliard's avatar
Alexandre Julliard committed
95
    if(!family)
Alexandre Julliard's avatar
Alexandre Julliard committed
96
        family = physDev->pi->Fonts;
Alexandre Julliard's avatar
Alexandre Julliard committed
97

98
    TRACE("Got family '%s'\n", family->FamilyName);
Alexandre Julliard's avatar
Alexandre Julliard committed
99

Alexandre Julliard's avatar
Alexandre Julliard committed
100 101 102
    for(afmle = family->afmlist; afmle; afmle = afmle->next) {
        if( (bd == (afmle->afm->Weight == FW_BOLD)) && 
	    (it == (afmle->afm->ItalicAngle != 0.0)) )
Alexandre Julliard's avatar
Alexandre Julliard committed
103 104
	        break;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
105 106
    if(!afmle)
        afmle = family->afmlist; /* not ideal */
Alexandre Julliard's avatar
Alexandre Julliard committed
107
    
Alexandre Julliard's avatar
Alexandre Julliard committed
108 109
    afm = afmle->afm;

Alexandre Julliard's avatar
Alexandre Julliard committed
110
    physDev->font.afm = afm;
Alexandre Julliard's avatar
Alexandre Julliard committed
111 112 113 114
    physDev->font.tm.tmHeight = YLSTODS(dc, lf->lfHeight);
    if(physDev->font.tm.tmHeight < 0) {
        physDev->font.tm.tmHeight *= - (afm->FullAscender - afm->Descender) /
				       (afm->Ascender - afm->Descender);
115
	TRACE("Fixed -ve height to %ld\n", physDev->font.tm.tmHeight);
Alexandre Julliard's avatar
Alexandre Julliard committed
116
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
117 118 119
    physDev->font.size = physDev->font.tm.tmHeight * 1000.0 /
				(afm->FullAscender - afm->Descender);
    physDev->font.scale = physDev->font.size / 1000.0;
Alexandre Julliard's avatar
Alexandre Julliard committed
120
    physDev->font.escapement = lf->lfEscapement;
Alexandre Julliard's avatar
Alexandre Julliard committed
121
    physDev->font.tm.tmAscent = afm->FullAscender * physDev->font.scale;
Alexandre Julliard's avatar
Alexandre Julliard committed
122
    physDev->font.tm.tmDescent = -afm->Descender * physDev->font.scale;
Alexandre Julliard's avatar
Alexandre Julliard committed
123 124 125 126
    physDev->font.tm.tmInternalLeading = (afm->FullAscender - afm->Ascender)
						* physDev->font.scale;
    physDev->font.tm.tmExternalLeading = (1000.0 - afm->FullAscender)
						* physDev->font.scale; /* ?? */
Alexandre Julliard's avatar
Alexandre Julliard committed
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
    physDev->font.tm.tmAveCharWidth = afm->CharWidths[120] * /* x */
                                                   physDev->font.scale;
    physDev->font.tm.tmMaxCharWidth = afm->CharWidths[77] * /* M */
                                           physDev->font.scale;
    physDev->font.tm.tmWeight = afm->Weight;
    physDev->font.tm.tmItalic = afm->ItalicAngle != 0.0;
    physDev->font.tm.tmUnderlined = lf->lfUnderline;
    physDev->font.tm.tmStruckOut = lf->lfStrikeOut;
    physDev->font.tm.tmFirstChar = 32;
    physDev->font.tm.tmLastChar = 251;
    physDev->font.tm.tmDefaultChar = 128;
    physDev->font.tm.tmBreakChar = 32;
    physDev->font.tm.tmPitchAndFamily = afm->IsFixedPitch ? 0 :
                                          TMPF_FIXED_PITCH;
    physDev->font.tm.tmPitchAndFamily |= TMPF_DEVICE;
    physDev->font.tm.tmCharSet = ANSI_CHARSET;
    physDev->font.tm.tmOverhang = 0;
    physDev->font.tm.tmDigitizedAspectX = dc->w.devCaps->logPixelsY;
    physDev->font.tm.tmDigitizedAspectY = dc->w.devCaps->logPixelsX;

    physDev->font.set = FALSE;

149
    TRACE("Selected PS font '%s' size %d weight %ld.\n", 
Alexandre Julliard's avatar
Alexandre Julliard committed
150 151
	  physDev->font.afm->FontName, physDev->font.size,
	  physDev->font.tm.tmWeight );
152
    TRACE("H = %ld As = %ld Des = %ld IL = %ld EL = %ld\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
153 154 155 156
	  physDev->font.tm.tmHeight, physDev->font.tm.tmAscent,
	  physDev->font.tm.tmDescent, physDev->font.tm.tmInternalLeading,
	  physDev->font.tm.tmExternalLeading);

Alexandre Julliard's avatar
Alexandre Julliard committed
157 158 159 160 161 162
    return prevfont;
}

/***********************************************************************
 *           PSDRV_GetTextMetrics
 */
163
BOOL PSDRV_GetTextMetrics(DC *dc, TEXTMETRICA *metrics)
Alexandre Julliard's avatar
Alexandre Julliard committed
164 165 166 167 168 169 170
{
    PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;

    memcpy(metrics, &(physDev->font.tm), sizeof(physDev->font.tm));
    return TRUE;
}

171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
/***********************************************************************
 *           PSDRV_UnicodeToANSI
 */
char PSDRV_UnicodeToANSI(int u)
{
    if((u & 0xff) == u)
        return u;
    switch(u) {
    case 0x2013: /* endash */
        return 0x96;
    case 0x2014: /* emdash */
        return 0x97;
    case 0x2018: /* quoteleft */
        return 0x91;
    case 0x2019: /* quoteright */
        return 0x92;
    case 0x201c: /* quotedblleft */
       return 0x93;
    case 0x201d: /* quotedblright */
        return 0x94;
    case 0x2022: /* bullet */
        return 0x95;
    default:
        WARN("Umapped unicode char U%04x\n", u);
	return 0xff;
    }
}
Alexandre Julliard's avatar
Alexandre Julliard committed
198 199 200
/***********************************************************************
 *           PSDRV_GetTextExtentPoint
 */
201
BOOL PSDRV_GetTextExtentPoint( DC *dc, LPCWSTR str, INT count,
202
                                  LPSIZE size )
Alexandre Julliard's avatar
Alexandre Julliard committed
203 204
{
    PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
205
    INT i;
Alexandre Julliard's avatar
Alexandre Julliard committed
206 207 208 209 210
    float width;

    size->cy = YDSTOLS(dc, physDev->font.tm.tmHeight);
    width = 0.0;

Alexandre Julliard's avatar
Alexandre Julliard committed
211
    for(i = 0; i < count && str[i]; i++) {
212 213
        char c = PSDRV_UnicodeToANSI(str[i]);
        width += physDev->font.afm->CharWidths[(int)(unsigned char)c];
Alexandre Julliard's avatar
Alexandre Julliard committed
214
/*	TRACE(psdrv, "Width after %dth char '%c' = %f\n", i, str[i], width);*/
Alexandre Julliard's avatar
Alexandre Julliard committed
215
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
216
    width *= physDev->font.scale;
217
    TRACE("Width after scale (%f) is %f\n", physDev->font.scale, width);
Alexandre Julliard's avatar
Alexandre Julliard committed
218 219 220 221 222 223
    size->cx = XDSTOLS(dc, width);

    return TRUE;
}


224 225 226
/***********************************************************************
 *           PSDRV_GetCharWidth
 */
227 228
BOOL PSDRV_GetCharWidth( DC *dc, UINT firstChar, UINT lastChar,
			   LPINT buffer )
229 230
{
    PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
231
    UINT i;
232

233
    TRACE("first = %d last = %d\n", firstChar, lastChar);
234

235
    if(lastChar > 0xff) return FALSE;
236 237 238 239 240 241 242
    for( i = firstChar; i <= lastChar; i++ )
        *buffer++ = physDev->font.afm->CharWidths[i] * physDev->font.scale;

    return TRUE;
}

    
Alexandre Julliard's avatar
Alexandre Julliard committed
243 244 245
/***********************************************************************
 *           PSDRV_SetFont
 */
246
BOOL PSDRV_SetFont( DC *dc )
Alexandre Julliard's avatar
Alexandre Julliard committed
247 248
{
    PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
249
    BOOL ReEncode = FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
250

Alexandre Julliard's avatar
Alexandre Julliard committed
251
    PSDRV_WriteSetColor(dc, &physDev->font.color);
Alexandre Julliard's avatar
Alexandre Julliard committed
252 253
    if(physDev->font.set) return TRUE;

Alexandre Julliard's avatar
Alexandre Julliard committed
254 255 256 257 258 259
    if(physDev->font.afm->EncodingScheme && 
       !strcmp(physDev->font.afm->EncodingScheme, "AdobeStandardEncoding"))
        ReEncode = TRUE;
    if(ReEncode)
        PSDRV_WriteReencodeFont(dc);
    PSDRV_WriteSetFont(dc, ReEncode);
Alexandre Julliard's avatar
Alexandre Julliard committed
260 261 262 263 264 265 266 267
    physDev->font.set = TRUE;
    return TRUE;
}


/***********************************************************************
 *           PSDRV_GetFontMetric
 */
268
static UINT PSDRV_GetFontMetric(DC *dc, AFM *pafm, NEWTEXTMETRIC16 *pTM, 
Alexandre Julliard's avatar
Alexandre Julliard committed
269 270 271
              ENUMLOGFONTEX16 *pLF, INT16 size)

{
Alexandre Julliard's avatar
Alexandre Julliard committed
272
    float scale = size / (pafm->FullAscender - pafm->Descender);
Alexandre Julliard's avatar
Alexandre Julliard committed
273 274 275 276 277
    memset( pLF, 0, sizeof(*pLF) );
    memset( pTM, 0, sizeof(*pTM) );

#define plf ((LPLOGFONT16)pLF)
    plf->lfHeight    = pTM->tmHeight       = size;
Alexandre Julliard's avatar
Alexandre Julliard committed
278
    plf->lfWidth     = pTM->tmAveCharWidth = pafm->CharWidths[120] * scale;
Alexandre Julliard's avatar
Alexandre Julliard committed
279 280 281 282 283 284 285 286 287 288 289 290
    plf->lfWeight    = pTM->tmWeight       = pafm->Weight;
    plf->lfItalic    = pTM->tmItalic       = pafm->ItalicAngle != 0.0;
    plf->lfUnderline = pTM->tmUnderlined   = 0;
    plf->lfStrikeOut = pTM->tmStruckOut    = 0;
    plf->lfCharSet   = pTM->tmCharSet      = ANSI_CHARSET;

    /* convert pitch values */

    pTM->tmPitchAndFamily = pafm->IsFixedPitch ? 0 : TMPF_FIXED_PITCH;
    pTM->tmPitchAndFamily |= TMPF_DEVICE;
    plf->lfPitchAndFamily = 0;

291
    lstrcpynA( plf->lfFaceName, pafm->FamilyName, LF_FACESIZE );
Alexandre Julliard's avatar
Alexandre Julliard committed
292 293
#undef plf

Alexandre Julliard's avatar
Alexandre Julliard committed
294 295 296 297
    pTM->tmAscent = pafm->FullAscender * scale;
    pTM->tmDescent = -pafm->Descender * scale;
    pTM->tmInternalLeading = (pafm->FullAscender - pafm->Ascender) * scale;
    pTM->tmMaxCharWidth = pafm->CharWidths[77] * scale;
Alexandre Julliard's avatar
Alexandre Julliard committed
298 299 300
    pTM->tmDigitizedAspectX = dc->w.devCaps->logPixelsY;
    pTM->tmDigitizedAspectY = dc->w.devCaps->logPixelsX;

301
    *(INT*)&pTM->tmFirstChar = 32;
Alexandre Julliard's avatar
Alexandre Julliard committed
302 303 304 305 306 307 308 309 310 311

    /* return font type */

    return DEVICE_FONTTYPE;

}

/***********************************************************************
 *           PSDRV_EnumDeviceFonts
 */
312
BOOL PSDRV_EnumDeviceFonts( DC* dc, LPLOGFONT16 plf, 
Alexandre Julliard's avatar
Alexandre Julliard committed
313 314 315 316
				        DEVICEFONTENUMPROC proc, LPARAM lp )
{
    ENUMLOGFONTEX16	lf;
    NEWTEXTMETRIC16	tm;
317
    BOOL	  	b, bRet = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
318 319 320
    AFMLISTENTRY	*afmle;
    FONTFAMILY		*family;
    PSDRV_PDEVICE	*physDev = (PSDRV_PDEVICE *)dc->physDev;
Alexandre Julliard's avatar
Alexandre Julliard committed
321 322

    if( plf->lfFaceName[0] ) {
323
        TRACE("lfFaceName = '%s'\n", plf->lfFaceName);
Alexandre Julliard's avatar
Alexandre Julliard committed
324
        for(family = physDev->pi->Fonts; family; family = family->next) {
Alexandre Julliard's avatar
Alexandre Julliard committed
325
            if(!strncmp(plf->lfFaceName, family->FamilyName, 
Alexandre Julliard's avatar
Alexandre Julliard committed
326 327 328 329
			strlen(family->FamilyName)))
	        break;
	}
	if(family) {
Alexandre Julliard's avatar
Alexandre Julliard committed
330
	    for(afmle = family->afmlist; afmle; afmle = afmle->next) {
331
	        TRACE("Got '%s'\n", afmle->afm->FontName);
332
		if( (b = (*proc)( &lf, &tm, 
Alexandre Julliard's avatar
Alexandre Julliard committed
333 334
			PSDRV_GetFontMetric( dc, afmle->afm, &tm, &lf, 200 ),
				  lp )) )
Alexandre Julliard's avatar
Alexandre Julliard committed
335 336 337 338 339 340
		     bRet = b;
		else break;
	    }
	}
    } else {

341
        TRACE("lfFaceName = NULL\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
342 343
        for(family = physDev->pi->Fonts; family; family = family->next) {
	    afmle = family->afmlist;
344
	    TRACE("Got '%s'\n", afmle->afm->FontName);
345
	    if( (b = (*proc)( &lf, &tm, 
Alexandre Julliard's avatar
Alexandre Julliard committed
346 347
		   PSDRV_GetFontMetric( dc, afmle->afm, &tm, &lf, 200 ), 
			      lp )) )
Alexandre Julliard's avatar
Alexandre Julliard committed
348 349 350 351 352 353
	        bRet = b;
	    else break;
	}
    }
    return bRet;
}