2 * PostScript driver font functions
4 * Copyright 1998 Huw D M Davies
10 #include "debugtools.h"
14 DEFAULT_DEBUG_CHANNEL(psdrv)
18 /***********************************************************************
19 * PSDRV_FONT_SelectObject
21 HFONT16 PSDRV_FONT_SelectObject( DC * dc, HFONT16 hfont,
24 HFONT16 prevfont = dc->w.hFont;
25 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
26 LOGFONT16 *lf = &(font->logfont);
27 BOOL bd = FALSE, it = FALSE;
31 char FaceName[LF_FACESIZE];
34 TRACE("FaceName = '%s' Height = %d Italic = %d Weight = %d\n",
35 lf->lfFaceName, lf->lfHeight, lf->lfItalic, lf->lfWeight);
41 if(lf->lfWeight > 550)
43 strcpy(FaceName, lf->lfFaceName);
45 if(FaceName[0] == '\0') {
46 switch(lf->lfPitchAndFamily & 0xf0) {
51 strcpy(FaceName, "Times");
54 strcpy(FaceName, "Helvetica");
57 strcpy(FaceName, "Courier");
60 strcpy(FaceName, "Symbol");
65 if(FaceName[0] == '\0') {
66 switch(lf->lfPitchAndFamily & 0x0f) {
68 strcpy(FaceName, "Times");
71 strcpy(FaceName, "Courier");
76 TRACE("Trying to find facename '%s'\n", FaceName);
78 /* Look for a matching font family */
79 for(family = physDev->pi->Fonts; family; family = family->next) {
80 if(!strcmp(FaceName, family->FamilyName))
84 /* Fallback for Window's font families to common PostScript families */
85 if(!strcmp(FaceName, "Arial"))
86 strcpy(FaceName, "Helvetica");
87 else if(!strcmp(FaceName, "System"))
88 strcpy(FaceName, "Helvetica");
89 else if(!strcmp(FaceName, "Times New Roman"))
90 strcpy(FaceName, "Times");
91 for(family = physDev->pi->Fonts; family; family = family->next) {
92 if(!strcmp(FaceName, family->FamilyName))
96 /* If all else fails, use the first font defined for the printer */
98 family = physDev->pi->Fonts;
100 TRACE("Got family '%s'\n", family->FamilyName);
102 for(afmle = family->afmlist; afmle; afmle = afmle->next) {
103 if( (bd == (afmle->afm->Weight == FW_BOLD)) &&
104 (it == (afmle->afm->ItalicAngle != 0.0)) )
108 afmle = family->afmlist; /* not ideal */
112 physDev->font.afm = afm;
113 physDev->font.tm.tmHeight = YLSTODS(dc, lf->lfHeight);
114 if(physDev->font.tm.tmHeight < 0) {
115 physDev->font.tm.tmHeight *= - (afm->FullAscender - afm->Descender) /
116 (afm->Ascender - afm->Descender);
117 TRACE("Fixed -ve height to %ld\n", physDev->font.tm.tmHeight);
119 physDev->font.size = physDev->font.tm.tmHeight * 1000.0 /
120 (afm->FullAscender - afm->Descender);
121 physDev->font.scale = physDev->font.size / 1000.0;
122 physDev->font.escapement = lf->lfEscapement;
123 physDev->font.tm.tmAscent = afm->FullAscender * physDev->font.scale;
124 physDev->font.tm.tmDescent = -afm->Descender * physDev->font.scale;
125 physDev->font.tm.tmInternalLeading = (afm->FullAscender - afm->Ascender)
126 * physDev->font.scale;
127 physDev->font.tm.tmExternalLeading = (1000.0 - afm->FullAscender)
128 * physDev->font.scale; /* ?? */
129 physDev->font.tm.tmAveCharWidth = afm->CharWidths[120] * /* x */
131 physDev->font.tm.tmMaxCharWidth = afm->CharWidths[77] * /* M */
133 physDev->font.tm.tmWeight = afm->Weight;
134 physDev->font.tm.tmItalic = afm->ItalicAngle != 0.0;
135 physDev->font.tm.tmUnderlined = lf->lfUnderline;
136 physDev->font.tm.tmStruckOut = lf->lfStrikeOut;
137 physDev->font.tm.tmFirstChar = 32;
138 physDev->font.tm.tmLastChar = 251;
139 physDev->font.tm.tmDefaultChar = 128;
140 physDev->font.tm.tmBreakChar = 32;
141 physDev->font.tm.tmPitchAndFamily = afm->IsFixedPitch ? 0 :
143 physDev->font.tm.tmPitchAndFamily |= TMPF_DEVICE;
144 physDev->font.tm.tmCharSet = ANSI_CHARSET;
145 physDev->font.tm.tmOverhang = 0;
146 physDev->font.tm.tmDigitizedAspectX = dc->w.devCaps->logPixelsY;
147 physDev->font.tm.tmDigitizedAspectY = dc->w.devCaps->logPixelsX;
149 physDev->font.set = FALSE;
151 TRACE("Selected PS font '%s' size %d weight %ld.\n",
152 physDev->font.afm->FontName, physDev->font.size,
153 physDev->font.tm.tmWeight );
154 TRACE("H = %ld As = %ld Des = %ld IL = %ld EL = %ld\n",
155 physDev->font.tm.tmHeight, physDev->font.tm.tmAscent,
156 physDev->font.tm.tmDescent, physDev->font.tm.tmInternalLeading,
157 physDev->font.tm.tmExternalLeading);
162 /***********************************************************************
163 * PSDRV_GetTextMetrics
165 BOOL PSDRV_GetTextMetrics(DC *dc, TEXTMETRICA *metrics)
167 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
169 memcpy(metrics, &(physDev->font.tm), sizeof(physDev->font.tm));
173 /***********************************************************************
174 * PSDRV_UnicodeToANSI
176 char PSDRV_UnicodeToANSI(int u)
181 case 0x2013: /* endash */
183 case 0x2014: /* emdash */
185 case 0x2018: /* quoteleft */
187 case 0x2019: /* quoteright */
189 case 0x201c: /* quotedblleft */
191 case 0x201d: /* quotedblright */
193 case 0x2022: /* bullet */
196 WARN("Umapped unicode char U%04x\n", u);
200 /***********************************************************************
201 * PSDRV_GetTextExtentPoint
203 BOOL PSDRV_GetTextExtentPoint( DC *dc, LPCWSTR str, INT count,
206 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
210 size->cy = YDSTOLS(dc, physDev->font.tm.tmHeight);
213 for(i = 0; i < count && str[i]; i++) {
214 char c = PSDRV_UnicodeToANSI(str[i]);
215 width += physDev->font.afm->CharWidths[(int)(unsigned char)c];
216 /* TRACE(psdrv, "Width after %dth char '%c' = %f\n", i, str[i], width);*/
218 width *= physDev->font.scale;
219 TRACE("Width after scale (%f) is %f\n", physDev->font.scale, width);
220 size->cx = XDSTOLS(dc, width);
226 /***********************************************************************
229 BOOL PSDRV_GetCharWidth( DC *dc, UINT firstChar, UINT lastChar,
232 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
235 TRACE("first = %d last = %d\n", firstChar, lastChar);
237 if(lastChar > 0xff) return FALSE;
238 for( i = firstChar; i <= lastChar; i++ )
239 *buffer++ = physDev->font.afm->CharWidths[i] * physDev->font.scale;
245 /***********************************************************************
248 BOOL PSDRV_SetFont( DC *dc )
250 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
251 BOOL ReEncode = FALSE;
253 PSDRV_WriteSetColor(dc, &physDev->font.color);
254 if(physDev->font.set) return TRUE;
256 if(physDev->font.afm->EncodingScheme &&
257 !strcmp(physDev->font.afm->EncodingScheme, "AdobeStandardEncoding"))
260 PSDRV_WriteReencodeFont(dc);
261 PSDRV_WriteSetFont(dc, ReEncode);
262 physDev->font.set = TRUE;
267 /***********************************************************************
268 * PSDRV_GetFontMetric
270 static UINT PSDRV_GetFontMetric(HDC hdc, AFM *pafm, NEWTEXTMETRIC16 *pTM,
271 ENUMLOGFONTEX16 *pLF, INT16 size)
274 DC *dc = DC_GetDCPtr( hdc );
275 float scale = size / (pafm->FullAscender - pafm->Descender);
277 if (!dc) return FALSE;
279 memset( pLF, 0, sizeof(*pLF) );
280 memset( pTM, 0, sizeof(*pTM) );
282 #define plf ((LPLOGFONT16)pLF)
283 plf->lfHeight = pTM->tmHeight = size;
284 plf->lfWidth = pTM->tmAveCharWidth = pafm->CharWidths[120] * scale;
285 plf->lfWeight = pTM->tmWeight = pafm->Weight;
286 plf->lfItalic = pTM->tmItalic = pafm->ItalicAngle != 0.0;
287 plf->lfUnderline = pTM->tmUnderlined = 0;
288 plf->lfStrikeOut = pTM->tmStruckOut = 0;
289 plf->lfCharSet = pTM->tmCharSet = ANSI_CHARSET;
291 /* convert pitch values */
293 pTM->tmPitchAndFamily = pafm->IsFixedPitch ? 0 : TMPF_FIXED_PITCH;
294 pTM->tmPitchAndFamily |= TMPF_DEVICE;
295 plf->lfPitchAndFamily = 0;
297 lstrcpynA( plf->lfFaceName, pafm->FamilyName, LF_FACESIZE );
300 pTM->tmAscent = pafm->FullAscender * scale;
301 pTM->tmDescent = -pafm->Descender * scale;
302 pTM->tmInternalLeading = (pafm->FullAscender - pafm->Ascender) * scale;
303 pTM->tmMaxCharWidth = pafm->CharWidths[77] * scale;
304 pTM->tmDigitizedAspectX = dc->w.devCaps->logPixelsY;
305 pTM->tmDigitizedAspectY = dc->w.devCaps->logPixelsX;
307 *(INT*)&pTM->tmFirstChar = 32;
309 GDI_ReleaseObj( hdc );
310 /* return font type */
311 return DEVICE_FONTTYPE;
315 /***********************************************************************
316 * PSDRV_EnumDeviceFonts
318 BOOL PSDRV_EnumDeviceFonts( HDC hdc, LPLOGFONT16 plf,
319 DEVICEFONTENUMPROC proc, LPARAM lp )
326 PSDRV_PDEVICE *physDev;
328 DC *dc = DC_GetDCPtr( hdc );
329 if (!dc) return FALSE;
331 physDev = (PSDRV_PDEVICE *)dc->physDev;
332 /* FIXME!! should reevaluate dc->physDev after every callback */
333 GDI_ReleaseObj( hdc );
335 if( plf->lfFaceName[0] ) {
336 TRACE("lfFaceName = '%s'\n", plf->lfFaceName);
337 for(family = physDev->pi->Fonts; family; family = family->next) {
338 if(!strncmp(plf->lfFaceName, family->FamilyName,
339 strlen(family->FamilyName)))
343 for(afmle = family->afmlist; afmle; afmle = afmle->next) {
344 TRACE("Got '%s'\n", afmle->afm->FontName);
345 if( (b = (*proc)( &lf, &tm,
346 PSDRV_GetFontMetric( hdc, afmle->afm, &tm, &lf, 200 ),
354 TRACE("lfFaceName = NULL\n");
355 for(family = physDev->pi->Fonts; family; family = family->next) {
356 afmle = family->afmlist;
357 TRACE("Got '%s'\n", afmle->afm->FontName);
358 if( (b = (*proc)( &lf, &tm,
359 PSDRV_GetFontMetric( hdc, afmle->afm, &tm, &lf, 200 ),