2 * PostScript driver font functions
4 * Copyright 1998 Huw D M Davies
10 #include "debugtools.h"
14 DEFAULT_DEBUG_CHANNEL(psdrv);
17 /***********************************************************************
18 * PSDRV_FONT_SelectObject
20 HFONT16 PSDRV_FONT_SelectObject( DC * dc, HFONT16 hfont,
23 HFONT16 prevfont = dc->hFont;
24 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
25 LOGFONTW *lf = &(font->logfont);
26 BOOL bd = FALSE, it = FALSE;
30 char FaceName[LF_FACESIZE];
33 TRACE("FaceName = '%s' Height = %ld Italic = %d Weight = %ld\n",
34 debugstr_w(lf->lfFaceName), lf->lfHeight, lf->lfItalic,
41 if(lf->lfWeight > 550)
43 WideCharToMultiByte(CP_ACP, 0, lf->lfFaceName, -1,
44 FaceName, sizeof(FaceName), NULL, NULL);
46 if(FaceName[0] == '\0') {
47 switch(lf->lfPitchAndFamily & 0xf0) {
52 strcpy(FaceName, "Times");
55 strcpy(FaceName, "Helvetica");
58 strcpy(FaceName, "Courier");
61 strcpy(FaceName, "Symbol");
66 if(FaceName[0] == '\0') {
67 switch(lf->lfPitchAndFamily & 0x0f) {
69 strcpy(FaceName, "Times");
72 strcpy(FaceName, "Courier");
77 TRACE("Trying to find facename '%s'\n", FaceName);
79 /* Look for a matching font family */
80 for(family = physDev->pi->Fonts; family; family = family->next) {
81 if(!strcasecmp(FaceName, family->FamilyName))
85 /* Fallback for Window's font families to common PostScript families */
86 if(!strcmp(FaceName, "Arial"))
87 strcpy(FaceName, "Helvetica");
88 else if(!strcmp(FaceName, "System"))
89 strcpy(FaceName, "Helvetica");
90 else if(!strcmp(FaceName, "Times New Roman"))
91 strcpy(FaceName, "Times");
92 else if(!strcmp(FaceName, "Courier New"))
93 strcpy(FaceName, "Courier");
95 for(family = physDev->pi->Fonts; family; family = family->next) {
96 if(!strcmp(FaceName, family->FamilyName))
100 /* If all else fails, use the first font defined for the printer */
102 family = physDev->pi->Fonts;
104 TRACE("Got family '%s'\n", family->FamilyName);
106 for(afmle = family->afmlist; afmle; afmle = afmle->next) {
107 if( (bd == (afmle->afm->Weight == FW_BOLD)) &&
108 (it == (afmle->afm->ItalicAngle != 0.0)) )
112 afmle = family->afmlist; /* not ideal */
116 physDev->font.afm = afm;
117 physDev->font.tm.tmHeight = INTERNAL_YWSTODS(dc, lf->lfHeight);
118 if(physDev->font.tm.tmHeight < 0) {
119 physDev->font.tm.tmHeight *= - (afm->FullAscender - afm->Descender) /
120 (afm->Ascender - afm->Descender);
121 TRACE("Fixed -ve height to %ld\n", physDev->font.tm.tmHeight);
123 physDev->font.size = physDev->font.tm.tmHeight * 1000.0 /
124 (afm->FullAscender - afm->Descender);
125 physDev->font.scale = physDev->font.size / 1000.0;
126 physDev->font.escapement = lf->lfEscapement;
127 physDev->font.tm.tmAscent = afm->FullAscender * physDev->font.scale;
128 physDev->font.tm.tmDescent = -afm->Descender * physDev->font.scale;
129 physDev->font.tm.tmInternalLeading = (afm->FullAscender - afm->Ascender)
130 * physDev->font.scale;
131 physDev->font.tm.tmExternalLeading = (1000.0 - afm->FullAscender)
132 * physDev->font.scale; /* ?? */
133 physDev->font.tm.tmAveCharWidth = afm->CharWidths[120] * /* x */
135 physDev->font.tm.tmMaxCharWidth = afm->CharWidths[77] * /* M */
137 physDev->font.tm.tmWeight = afm->Weight;
138 physDev->font.tm.tmItalic = afm->ItalicAngle != 0.0;
139 physDev->font.tm.tmUnderlined = lf->lfUnderline;
140 physDev->font.tm.tmStruckOut = lf->lfStrikeOut;
141 physDev->font.tm.tmFirstChar = 32;
142 physDev->font.tm.tmLastChar = 251;
143 physDev->font.tm.tmDefaultChar = 128;
144 physDev->font.tm.tmBreakChar = 32;
145 physDev->font.tm.tmPitchAndFamily = afm->IsFixedPitch ? 0 :
147 physDev->font.tm.tmPitchAndFamily |= TMPF_DEVICE;
148 physDev->font.tm.tmCharSet = ANSI_CHARSET;
149 physDev->font.tm.tmOverhang = 0;
150 physDev->font.tm.tmDigitizedAspectX = dc->devCaps->logPixelsY;
151 physDev->font.tm.tmDigitizedAspectY = dc->devCaps->logPixelsX;
153 physDev->font.set = FALSE;
155 TRACE("Selected PS font '%s' size %d weight %ld.\n",
156 physDev->font.afm->FontName, physDev->font.size,
157 physDev->font.tm.tmWeight );
158 TRACE("H = %ld As = %ld Des = %ld IL = %ld EL = %ld\n",
159 physDev->font.tm.tmHeight, physDev->font.tm.tmAscent,
160 physDev->font.tm.tmDescent, physDev->font.tm.tmInternalLeading,
161 physDev->font.tm.tmExternalLeading);
166 /***********************************************************************
167 * PSDRV_GetTextMetrics
169 BOOL PSDRV_GetTextMetrics(DC *dc, TEXTMETRICW *metrics)
171 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
173 memcpy(metrics, &(physDev->font.tm), sizeof(physDev->font.tm));
177 /***********************************************************************
178 * PSDRV_UnicodeToANSI
180 char PSDRV_UnicodeToANSI(int u)
185 case 0x2013: /* endash */
187 case 0x2014: /* emdash */
189 case 0x2018: /* quoteleft */
191 case 0x2019: /* quoteright */
193 case 0x201c: /* quotedblleft */
195 case 0x201d: /* quotedblright */
197 case 0x2022: /* bullet */
200 WARN("Umapped unicode char U%04x\n", u);
204 /***********************************************************************
205 * PSDRV_GetTextExtentPoint
207 BOOL PSDRV_GetTextExtentPoint( DC *dc, LPCWSTR str, INT count,
210 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
216 for(i = 0; i < count && str[i]; i++) {
217 char c = PSDRV_UnicodeToANSI(str[i]);
218 width += physDev->font.afm->CharWidths[(int)(unsigned char)c];
219 /* TRACE(psdrv, "Width after %dth char '%c' = %f\n", i, str[i], width);*/
221 width *= physDev->font.scale;
222 TRACE("Width after scale (%f) is %f\n", physDev->font.scale, width);
224 size->cx = GDI_ROUND((FLOAT)width * dc->xformVport2World.eM11);
225 size->cy = GDI_ROUND((FLOAT)physDev->font.tm.tmHeight * dc->xformVport2World.eM22);
231 /***********************************************************************
234 BOOL PSDRV_GetCharWidth( DC *dc, UINT firstChar, UINT lastChar,
237 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
240 TRACE("first = %d last = %d\n", firstChar, lastChar);
242 if(lastChar > 0xff) return FALSE;
243 for( i = firstChar; i <= lastChar; i++ )
244 *buffer++ = physDev->font.afm->CharWidths[i] * physDev->font.scale;
250 /***********************************************************************
253 BOOL PSDRV_SetFont( DC *dc )
255 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
256 BOOL ReEncode = FALSE;
258 PSDRV_WriteSetColor(dc, &physDev->font.color);
259 if(physDev->font.set) return TRUE;
261 if(physDev->font.afm->EncodingScheme &&
262 !strcmp(physDev->font.afm->EncodingScheme, "AdobeStandardEncoding"))
265 PSDRV_WriteReencodeFont(dc);
266 PSDRV_WriteSetFont(dc, ReEncode);
267 physDev->font.set = TRUE;
272 /***********************************************************************
273 * PSDRV_GetFontMetric
275 static UINT PSDRV_GetFontMetric(HDC hdc, AFM *pafm, NEWTEXTMETRICEXW *pTM,
276 ENUMLOGFONTEXW *pLF, INT16 size)
279 DC *dc = DC_GetDCPtr( hdc );
280 float scale = size / (pafm->FullAscender - pafm->Descender);
282 if (!dc) return FALSE;
284 memset( pLF, 0, sizeof(*pLF) );
285 memset( pTM, 0, sizeof(*pTM) );
287 #define plf ((LPLOGFONTW)pLF)
288 #define ptm ((LPNEWTEXTMETRICW)pTM)
289 plf->lfHeight = ptm->tmHeight = size;
290 plf->lfWidth = ptm->tmAveCharWidth = pafm->CharWidths[120] * scale;
291 plf->lfWeight = ptm->tmWeight = pafm->Weight;
292 plf->lfItalic = ptm->tmItalic = pafm->ItalicAngle != 0.0;
293 plf->lfUnderline = ptm->tmUnderlined = 0;
294 plf->lfStrikeOut = ptm->tmStruckOut = 0;
295 plf->lfCharSet = ptm->tmCharSet = ANSI_CHARSET;
297 /* convert pitch values */
299 ptm->tmPitchAndFamily = pafm->IsFixedPitch ? 0 : TMPF_FIXED_PITCH;
300 ptm->tmPitchAndFamily |= TMPF_DEVICE;
301 plf->lfPitchAndFamily = 0;
303 MultiByteToWideChar(CP_ACP, 0, pafm->FamilyName, -1,
304 plf->lfFaceName, LF_FACESIZE);
307 ptm->tmAscent = pafm->FullAscender * scale;
308 ptm->tmDescent = -pafm->Descender * scale;
309 ptm->tmInternalLeading = (pafm->FullAscender - pafm->Ascender) * scale;
310 ptm->tmMaxCharWidth = pafm->CharWidths[77] * scale;
311 ptm->tmDigitizedAspectX = dc->devCaps->logPixelsY;
312 ptm->tmDigitizedAspectY = dc->devCaps->logPixelsX;
314 *(INT*)&ptm->tmFirstChar = 32;
316 GDI_ReleaseObj( hdc );
317 /* return font type */
319 return DEVICE_FONTTYPE;
323 /***********************************************************************
324 * PSDRV_EnumDeviceFonts
326 BOOL PSDRV_EnumDeviceFonts( HDC hdc, LPLOGFONTW plf,
327 DEVICEFONTENUMPROC proc, LPARAM lp )
334 PSDRV_PDEVICE *physDev;
335 char FaceName[LF_FACESIZE];
336 DC *dc = DC_GetDCPtr( hdc );
337 if (!dc) return FALSE;
339 physDev = (PSDRV_PDEVICE *)dc->physDev;
340 /* FIXME!! should reevaluate dc->physDev after every callback */
341 GDI_ReleaseObj( hdc );
343 if( plf->lfFaceName[0] ) {
344 WideCharToMultiByte(CP_ACP, 0, plf->lfFaceName, -1,
345 FaceName, sizeof(FaceName), NULL, NULL);
346 TRACE("lfFaceName = '%s'\n", FaceName);
347 for(family = physDev->pi->Fonts; family; family = family->next) {
348 if(!strncmp(FaceName, family->FamilyName,
349 strlen(family->FamilyName)))
353 for(afmle = family->afmlist; afmle; afmle = afmle->next) {
354 TRACE("Got '%s'\n", afmle->afm->FontName);
355 if( (b = (*proc)( &lf, &tm,
356 PSDRV_GetFontMetric( hdc, afmle->afm, &tm, &lf, 200 ),
364 TRACE("lfFaceName = NULL\n");
365 for(family = physDev->pi->Fonts; family; family = family->next) {
366 afmle = family->afmlist;
367 TRACE("Got '%s'\n", afmle->afm->FontName);
368 if( (b = (*proc)( &lf, &tm,
369 PSDRV_GetFontMetric( hdc, afmle->afm, &tm, &lf, 200 ),