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 if (physDev->pi->FontSubTableSize != 0)
81 for (i = 0; i < physDev->pi->FontSubTableSize; ++i)
83 if (!strcasecmp (FaceName,
84 physDev->pi->FontSubTable[i].pValueName))
86 TRACE ("substituting facename '%s' for '%s'\n",
87 (LPSTR) physDev->pi->FontSubTable[i].pData, FaceName);
88 if (strlen ((LPSTR) physDev->pi->FontSubTable[i].pData) <
91 (LPSTR) physDev->pi->FontSubTable[i].pData);
93 WARN ("Facename '%s' is too long; ignoring substitution\n",
94 (LPSTR) physDev->pi->FontSubTable[i].pData);
100 TRACE("Trying to find facename '%s'\n", FaceName);
102 /* Look for a matching font family */
103 for(family = physDev->pi->Fonts; family; family = family->next) {
104 if(!strcasecmp(FaceName, family->FamilyName))
108 /* Fallback for Window's font families to common PostScript families */
109 if(!strcmp(FaceName, "Arial"))
110 strcpy(FaceName, "Helvetica");
111 else if(!strcmp(FaceName, "System"))
112 strcpy(FaceName, "Helvetica");
113 else if(!strcmp(FaceName, "Times New Roman"))
114 strcpy(FaceName, "Times");
115 else if(!strcmp(FaceName, "Courier New"))
116 strcpy(FaceName, "Courier");
118 for(family = physDev->pi->Fonts; family; family = family->next) {
119 if(!strcmp(FaceName, family->FamilyName))
123 /* If all else fails, use the first font defined for the printer */
125 family = physDev->pi->Fonts;
127 TRACE("Got family '%s'\n", family->FamilyName);
129 for(afmle = family->afmlist; afmle; afmle = afmle->next) {
130 if( (bd == (afmle->afm->Weight == FW_BOLD)) &&
131 (it == (afmle->afm->ItalicAngle != 0.0)) )
135 afmle = family->afmlist; /* not ideal */
139 physDev->font.afm = afm;
140 physDev->font.tm.tmHeight = INTERNAL_YWSTODS(dc, lf->lfHeight);
141 if(physDev->font.tm.tmHeight < 0) {
142 physDev->font.tm.tmHeight *= - (afm->FullAscender - afm->Descender) /
143 (afm->Ascender - afm->Descender);
144 TRACE("Fixed -ve height to %ld\n", physDev->font.tm.tmHeight);
146 physDev->font.size = physDev->font.tm.tmHeight * 1000.0 /
147 (afm->FullAscender - afm->Descender);
148 physDev->font.scale = physDev->font.size / 1000.0;
149 physDev->font.escapement = lf->lfEscapement;
150 physDev->font.tm.tmAscent = afm->FullAscender * physDev->font.scale;
151 physDev->font.tm.tmDescent = -afm->Descender * physDev->font.scale;
152 physDev->font.tm.tmInternalLeading = (afm->FullAscender - afm->Ascender)
153 * physDev->font.scale;
154 physDev->font.tm.tmExternalLeading = (1000.0 - afm->FullAscender)
155 * physDev->font.scale; /* ?? */
156 physDev->font.tm.tmAveCharWidth = afm->CharWidths[120] * /* x */
158 physDev->font.tm.tmMaxCharWidth = afm->CharWidths[77] * /* M */
160 physDev->font.tm.tmWeight = afm->Weight;
161 physDev->font.tm.tmItalic = afm->ItalicAngle != 0.0;
162 physDev->font.tm.tmUnderlined = lf->lfUnderline;
163 physDev->font.tm.tmStruckOut = lf->lfStrikeOut;
164 physDev->font.tm.tmFirstChar = 32;
165 physDev->font.tm.tmLastChar = 251;
166 physDev->font.tm.tmDefaultChar = 128;
167 physDev->font.tm.tmBreakChar = 32;
168 physDev->font.tm.tmPitchAndFamily = afm->IsFixedPitch ? 0 :
170 physDev->font.tm.tmPitchAndFamily |= TMPF_DEVICE;
171 physDev->font.tm.tmCharSet = ANSI_CHARSET;
172 physDev->font.tm.tmOverhang = 0;
173 physDev->font.tm.tmDigitizedAspectX = dc->devCaps->logPixelsY;
174 physDev->font.tm.tmDigitizedAspectY = dc->devCaps->logPixelsX;
176 physDev->font.set = FALSE;
178 TRACE("Selected PS font '%s' size %d weight %ld.\n",
179 physDev->font.afm->FontName, physDev->font.size,
180 physDev->font.tm.tmWeight );
181 TRACE("H = %ld As = %ld Des = %ld IL = %ld EL = %ld\n",
182 physDev->font.tm.tmHeight, physDev->font.tm.tmAscent,
183 physDev->font.tm.tmDescent, physDev->font.tm.tmInternalLeading,
184 physDev->font.tm.tmExternalLeading);
189 /***********************************************************************
190 * PSDRV_GetTextMetrics
192 BOOL PSDRV_GetTextMetrics(DC *dc, TEXTMETRICW *metrics)
194 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
196 memcpy(metrics, &(physDev->font.tm), sizeof(physDev->font.tm));
200 /***********************************************************************
201 * PSDRV_UnicodeToANSI
203 char PSDRV_UnicodeToANSI(int u)
208 case 0x2013: /* endash */
210 case 0x2014: /* emdash */
212 case 0x2018: /* quoteleft */
214 case 0x2019: /* quoteright */
216 case 0x201c: /* quotedblleft */
218 case 0x201d: /* quotedblright */
220 case 0x2022: /* bullet */
223 WARN("Umapped unicode char U%04x\n", u);
227 /***********************************************************************
228 * PSDRV_GetTextExtentPoint
230 BOOL PSDRV_GetTextExtentPoint( DC *dc, LPCWSTR str, INT count,
233 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
239 for(i = 0; i < count && str[i]; i++) {
240 char c = PSDRV_UnicodeToANSI(str[i]);
241 width += physDev->font.afm->CharWidths[(int)(unsigned char)c];
242 /* TRACE(psdrv, "Width after %dth char '%c' = %f\n", i, str[i], width);*/
244 width *= physDev->font.scale;
245 TRACE("Width after scale (%f) is %f\n", physDev->font.scale, width);
247 size->cx = GDI_ROUND((FLOAT)width * dc->xformVport2World.eM11);
248 size->cy = GDI_ROUND((FLOAT)physDev->font.tm.tmHeight * dc->xformVport2World.eM22);
254 /***********************************************************************
257 BOOL PSDRV_GetCharWidth( DC *dc, UINT firstChar, UINT lastChar,
260 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
263 TRACE("first = %d last = %d\n", firstChar, lastChar);
265 if(lastChar > 0xff) return FALSE;
266 for( i = firstChar; i <= lastChar; i++ )
267 *buffer++ = physDev->font.afm->CharWidths[i] * physDev->font.scale;
273 /***********************************************************************
276 BOOL PSDRV_SetFont( DC *dc )
278 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
279 BOOL ReEncode = FALSE;
281 PSDRV_WriteSetColor(dc, &physDev->font.color);
282 if(physDev->font.set) return TRUE;
284 if(physDev->font.afm->EncodingScheme &&
285 !strcmp(physDev->font.afm->EncodingScheme, "AdobeStandardEncoding"))
288 PSDRV_WriteReencodeFont(dc);
289 PSDRV_WriteSetFont(dc, ReEncode);
290 physDev->font.set = TRUE;
295 /***********************************************************************
296 * PSDRV_GetFontMetric
298 static UINT PSDRV_GetFontMetric(HDC hdc, AFM *pafm, NEWTEXTMETRICEXW *pTM,
299 ENUMLOGFONTEXW *pLF, INT16 size)
302 DC *dc = DC_GetDCPtr( hdc );
303 float scale = size / (pafm->FullAscender - pafm->Descender);
305 if (!dc) return FALSE;
307 memset( pLF, 0, sizeof(*pLF) );
308 memset( pTM, 0, sizeof(*pTM) );
310 #define plf ((LPLOGFONTW)pLF)
311 #define ptm ((LPNEWTEXTMETRICW)pTM)
312 plf->lfHeight = ptm->tmHeight = size;
313 plf->lfWidth = ptm->tmAveCharWidth = pafm->CharWidths[120] * scale;
314 plf->lfWeight = ptm->tmWeight = pafm->Weight;
315 plf->lfItalic = ptm->tmItalic = pafm->ItalicAngle != 0.0;
316 plf->lfUnderline = ptm->tmUnderlined = 0;
317 plf->lfStrikeOut = ptm->tmStruckOut = 0;
318 plf->lfCharSet = ptm->tmCharSet = ANSI_CHARSET;
320 /* convert pitch values */
322 ptm->tmPitchAndFamily = pafm->IsFixedPitch ? 0 : TMPF_FIXED_PITCH;
323 ptm->tmPitchAndFamily |= TMPF_DEVICE;
324 plf->lfPitchAndFamily = 0;
326 MultiByteToWideChar(CP_ACP, 0, pafm->FamilyName, -1,
327 plf->lfFaceName, LF_FACESIZE);
330 ptm->tmAscent = pafm->FullAscender * scale;
331 ptm->tmDescent = -pafm->Descender * scale;
332 ptm->tmInternalLeading = (pafm->FullAscender - pafm->Ascender) * scale;
333 ptm->tmMaxCharWidth = pafm->CharWidths[77] * scale;
334 ptm->tmDigitizedAspectX = dc->devCaps->logPixelsY;
335 ptm->tmDigitizedAspectY = dc->devCaps->logPixelsX;
337 *(INT*)&ptm->tmFirstChar = 32;
339 GDI_ReleaseObj( hdc );
340 /* return font type */
342 return DEVICE_FONTTYPE;
346 /***********************************************************************
347 * PSDRV_EnumDeviceFonts
349 BOOL PSDRV_EnumDeviceFonts( HDC hdc, LPLOGFONTW plf,
350 DEVICEFONTENUMPROC proc, LPARAM lp )
357 PSDRV_PDEVICE *physDev;
358 char FaceName[LF_FACESIZE];
359 DC *dc = DC_GetDCPtr( hdc );
360 if (!dc) return FALSE;
362 physDev = (PSDRV_PDEVICE *)dc->physDev;
363 /* FIXME!! should reevaluate dc->physDev after every callback */
364 GDI_ReleaseObj( hdc );
366 if( plf->lfFaceName[0] ) {
367 WideCharToMultiByte(CP_ACP, 0, plf->lfFaceName, -1,
368 FaceName, sizeof(FaceName), NULL, NULL);
369 TRACE("lfFaceName = '%s'\n", FaceName);
370 for(family = physDev->pi->Fonts; family; family = family->next) {
371 if(!strncmp(FaceName, family->FamilyName,
372 strlen(family->FamilyName)))
376 for(afmle = family->afmlist; afmle; afmle = afmle->next) {
377 TRACE("Got '%s'\n", afmle->afm->FontName);
378 if( (b = (*proc)( &lf, &tm,
379 PSDRV_GetFontMetric( hdc, afmle->afm, &tm, &lf, 200 ),
387 TRACE("lfFaceName = NULL\n");
388 for(family = physDev->pi->Fonts; family; family = family->next) {
389 afmle = family->afmlist;
390 TRACE("Got '%s'\n", afmle->afm->FontName);
391 if( (b = (*proc)( &lf, &tm,
392 PSDRV_GetFontMetric( hdc, afmle->afm, &tm, &lf, 200 ),