- Minor API files fixes
[wine/multimedia.git] / dlls / wineps / font.c
blobe19034759d3daaed49e7f4a598bde3cb2e1b99b0
1 /*
2 * PostScript driver font functions
4 * Copyright 1998 Huw D M Davies
6 */
7 #include <string.h>
8 #include "winspool.h"
9 #include "psdrv.h"
10 #include "debugtools.h"
11 #include "gdi.h"
12 #include "winerror.h"
14 DEFAULT_DEBUG_CHANNEL(psdrv);
17 /***********************************************************************
18 * PSDRV_FONT_SelectObject
20 HFONT16 PSDRV_FONT_SelectObject( DC * dc, HFONT16 hfont,
21 FONTOBJ *font )
23 HFONT16 prevfont = dc->hFont;
24 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
25 LOGFONT16 *lf = &(font->logfont);
26 BOOL bd = FALSE, it = FALSE;
27 AFMLISTENTRY *afmle;
28 AFM *afm;
29 FONTFAMILY *family;
30 char FaceName[LF_FACESIZE];
33 TRACE("FaceName = '%s' Height = %d Italic = %d Weight = %d\n",
34 lf->lfFaceName, lf->lfHeight, lf->lfItalic, lf->lfWeight);
36 dc->hFont = hfont;
38 if(lf->lfItalic)
39 it = TRUE;
40 if(lf->lfWeight > 550)
41 bd = TRUE;
42 strcpy(FaceName, lf->lfFaceName);
44 if(FaceName[0] == '\0') {
45 switch(lf->lfPitchAndFamily & 0xf0) {
46 case FF_DONTCARE:
47 break;
48 case FF_ROMAN:
49 case FF_SCRIPT:
50 strcpy(FaceName, "Times");
51 break;
52 case FF_SWISS:
53 strcpy(FaceName, "Helvetica");
54 break;
55 case FF_MODERN:
56 strcpy(FaceName, "Courier");
57 break;
58 case FF_DECORATIVE:
59 strcpy(FaceName, "Symbol");
60 break;
64 if(FaceName[0] == '\0') {
65 switch(lf->lfPitchAndFamily & 0x0f) {
66 case VARIABLE_PITCH:
67 strcpy(FaceName, "Times");
68 break;
69 default:
70 strcpy(FaceName, "Courier");
71 break;
75 TRACE("Trying to find facename '%s'\n", FaceName);
77 /* Look for a matching font family */
78 for(family = physDev->pi->Fonts; family; family = family->next) {
79 if(!strcasecmp(FaceName, family->FamilyName))
80 break;
82 if(!family) {
83 /* Fallback for Window's font families to common PostScript families */
84 if(!strcmp(FaceName, "Arial"))
85 strcpy(FaceName, "Helvetica");
86 else if(!strcmp(FaceName, "System"))
87 strcpy(FaceName, "Helvetica");
88 else if(!strcmp(FaceName, "Times New Roman"))
89 strcpy(FaceName, "Times");
90 else if(!strcmp(FaceName, "Courier New"))
91 strcpy(FaceName, "Courier");
93 for(family = physDev->pi->Fonts; family; family = family->next) {
94 if(!strcmp(FaceName, family->FamilyName))
95 break;
98 /* If all else fails, use the first font defined for the printer */
99 if(!family)
100 family = physDev->pi->Fonts;
102 TRACE("Got family '%s'\n", family->FamilyName);
104 for(afmle = family->afmlist; afmle; afmle = afmle->next) {
105 if( (bd == (afmle->afm->Weight == FW_BOLD)) &&
106 (it == (afmle->afm->ItalicAngle != 0.0)) )
107 break;
109 if(!afmle)
110 afmle = family->afmlist; /* not ideal */
112 afm = afmle->afm;
114 physDev->font.afm = afm;
115 physDev->font.tm.tmHeight = INTERNAL_YWSTODS(dc, lf->lfHeight);
116 if(physDev->font.tm.tmHeight < 0) {
117 physDev->font.tm.tmHeight *= - (afm->FullAscender - afm->Descender) /
118 (afm->Ascender - afm->Descender);
119 TRACE("Fixed -ve height to %ld\n", physDev->font.tm.tmHeight);
121 physDev->font.size = physDev->font.tm.tmHeight * 1000.0 /
122 (afm->FullAscender - afm->Descender);
123 physDev->font.scale = physDev->font.size / 1000.0;
124 physDev->font.escapement = lf->lfEscapement;
125 physDev->font.tm.tmAscent = afm->FullAscender * physDev->font.scale;
126 physDev->font.tm.tmDescent = -afm->Descender * physDev->font.scale;
127 physDev->font.tm.tmInternalLeading = (afm->FullAscender - afm->Ascender)
128 * physDev->font.scale;
129 physDev->font.tm.tmExternalLeading = (1000.0 - afm->FullAscender)
130 * physDev->font.scale; /* ?? */
131 physDev->font.tm.tmAveCharWidth = afm->CharWidths[120] * /* x */
132 physDev->font.scale;
133 physDev->font.tm.tmMaxCharWidth = afm->CharWidths[77] * /* M */
134 physDev->font.scale;
135 physDev->font.tm.tmWeight = afm->Weight;
136 physDev->font.tm.tmItalic = afm->ItalicAngle != 0.0;
137 physDev->font.tm.tmUnderlined = lf->lfUnderline;
138 physDev->font.tm.tmStruckOut = lf->lfStrikeOut;
139 physDev->font.tm.tmFirstChar = 32;
140 physDev->font.tm.tmLastChar = 251;
141 physDev->font.tm.tmDefaultChar = 128;
142 physDev->font.tm.tmBreakChar = 32;
143 physDev->font.tm.tmPitchAndFamily = afm->IsFixedPitch ? 0 :
144 TMPF_FIXED_PITCH;
145 physDev->font.tm.tmPitchAndFamily |= TMPF_DEVICE;
146 physDev->font.tm.tmCharSet = ANSI_CHARSET;
147 physDev->font.tm.tmOverhang = 0;
148 physDev->font.tm.tmDigitizedAspectX = dc->devCaps->logPixelsY;
149 physDev->font.tm.tmDigitizedAspectY = dc->devCaps->logPixelsX;
151 physDev->font.set = FALSE;
153 TRACE("Selected PS font '%s' size %d weight %ld.\n",
154 physDev->font.afm->FontName, physDev->font.size,
155 physDev->font.tm.tmWeight );
156 TRACE("H = %ld As = %ld Des = %ld IL = %ld EL = %ld\n",
157 physDev->font.tm.tmHeight, physDev->font.tm.tmAscent,
158 physDev->font.tm.tmDescent, physDev->font.tm.tmInternalLeading,
159 physDev->font.tm.tmExternalLeading);
161 return prevfont;
164 /***********************************************************************
165 * PSDRV_GetTextMetrics
167 BOOL PSDRV_GetTextMetrics(DC *dc, TEXTMETRICA *metrics)
169 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
171 memcpy(metrics, &(physDev->font.tm), sizeof(physDev->font.tm));
172 return TRUE;
175 /***********************************************************************
176 * PSDRV_UnicodeToANSI
178 char PSDRV_UnicodeToANSI(int u)
180 if((u & 0xff) == u)
181 return u;
182 switch(u) {
183 case 0x2013: /* endash */
184 return 0x96;
185 case 0x2014: /* emdash */
186 return 0x97;
187 case 0x2018: /* quoteleft */
188 return 0x91;
189 case 0x2019: /* quoteright */
190 return 0x92;
191 case 0x201c: /* quotedblleft */
192 return 0x93;
193 case 0x201d: /* quotedblright */
194 return 0x94;
195 case 0x2022: /* bullet */
196 return 0x95;
197 default:
198 WARN("Umapped unicode char U%04x\n", u);
199 return 0xff;
202 /***********************************************************************
203 * PSDRV_GetTextExtentPoint
205 BOOL PSDRV_GetTextExtentPoint( DC *dc, LPCWSTR str, INT count,
206 LPSIZE size )
208 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
209 INT i;
210 float width;
212 width = 0.0;
214 for(i = 0; i < count && str[i]; i++) {
215 char c = PSDRV_UnicodeToANSI(str[i]);
216 width += physDev->font.afm->CharWidths[(int)(unsigned char)c];
217 /* TRACE(psdrv, "Width after %dth char '%c' = %f\n", i, str[i], width);*/
219 width *= physDev->font.scale;
220 TRACE("Width after scale (%f) is %f\n", physDev->font.scale, width);
222 size->cx = GDI_ROUND((FLOAT)width * dc->xformVport2World.eM11);
223 size->cy = GDI_ROUND((FLOAT)physDev->font.tm.tmHeight * dc->xformVport2World.eM22);
225 return TRUE;
229 /***********************************************************************
230 * PSDRV_GetCharWidth
232 BOOL PSDRV_GetCharWidth( DC *dc, UINT firstChar, UINT lastChar,
233 LPINT buffer )
235 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
236 UINT i;
238 TRACE("first = %d last = %d\n", firstChar, lastChar);
240 if(lastChar > 0xff) return FALSE;
241 for( i = firstChar; i <= lastChar; i++ )
242 *buffer++ = physDev->font.afm->CharWidths[i] * physDev->font.scale;
244 return TRUE;
248 /***********************************************************************
249 * PSDRV_SetFont
251 BOOL PSDRV_SetFont( DC *dc )
253 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
254 BOOL ReEncode = FALSE;
256 PSDRV_WriteSetColor(dc, &physDev->font.color);
257 if(physDev->font.set) return TRUE;
259 if(physDev->font.afm->EncodingScheme &&
260 !strcmp(physDev->font.afm->EncodingScheme, "AdobeStandardEncoding"))
261 ReEncode = TRUE;
262 if(ReEncode)
263 PSDRV_WriteReencodeFont(dc);
264 PSDRV_WriteSetFont(dc, ReEncode);
265 physDev->font.set = TRUE;
266 return TRUE;
270 /***********************************************************************
271 * PSDRV_GetFontMetric
273 static UINT PSDRV_GetFontMetric(HDC hdc, AFM *pafm, NEWTEXTMETRIC16 *pTM,
274 ENUMLOGFONTEX16 *pLF, INT16 size)
277 DC *dc = DC_GetDCPtr( hdc );
278 float scale = size / (pafm->FullAscender - pafm->Descender);
280 if (!dc) return FALSE;
282 memset( pLF, 0, sizeof(*pLF) );
283 memset( pTM, 0, sizeof(*pTM) );
285 #define plf ((LPLOGFONT16)pLF)
286 plf->lfHeight = pTM->tmHeight = size;
287 plf->lfWidth = pTM->tmAveCharWidth = pafm->CharWidths[120] * scale;
288 plf->lfWeight = pTM->tmWeight = pafm->Weight;
289 plf->lfItalic = pTM->tmItalic = pafm->ItalicAngle != 0.0;
290 plf->lfUnderline = pTM->tmUnderlined = 0;
291 plf->lfStrikeOut = pTM->tmStruckOut = 0;
292 plf->lfCharSet = pTM->tmCharSet = ANSI_CHARSET;
294 /* convert pitch values */
296 pTM->tmPitchAndFamily = pafm->IsFixedPitch ? 0 : TMPF_FIXED_PITCH;
297 pTM->tmPitchAndFamily |= TMPF_DEVICE;
298 plf->lfPitchAndFamily = 0;
300 lstrcpynA( plf->lfFaceName, pafm->FamilyName, LF_FACESIZE );
301 #undef plf
303 pTM->tmAscent = pafm->FullAscender * scale;
304 pTM->tmDescent = -pafm->Descender * scale;
305 pTM->tmInternalLeading = (pafm->FullAscender - pafm->Ascender) * scale;
306 pTM->tmMaxCharWidth = pafm->CharWidths[77] * scale;
307 pTM->tmDigitizedAspectX = dc->devCaps->logPixelsY;
308 pTM->tmDigitizedAspectY = dc->devCaps->logPixelsX;
310 *(INT*)&pTM->tmFirstChar = 32;
312 GDI_ReleaseObj( hdc );
313 /* return font type */
314 return DEVICE_FONTTYPE;
318 /***********************************************************************
319 * PSDRV_EnumDeviceFonts
321 BOOL PSDRV_EnumDeviceFonts( HDC hdc, LPLOGFONT16 plf,
322 DEVICEFONTENUMPROC proc, LPARAM lp )
324 ENUMLOGFONTEX16 lf;
325 NEWTEXTMETRIC16 tm;
326 BOOL b, bRet = 0;
327 AFMLISTENTRY *afmle;
328 FONTFAMILY *family;
329 PSDRV_PDEVICE *physDev;
331 DC *dc = DC_GetDCPtr( hdc );
332 if (!dc) return FALSE;
334 physDev = (PSDRV_PDEVICE *)dc->physDev;
335 /* FIXME!! should reevaluate dc->physDev after every callback */
336 GDI_ReleaseObj( hdc );
338 if( plf->lfFaceName[0] ) {
339 TRACE("lfFaceName = '%s'\n", plf->lfFaceName);
340 for(family = physDev->pi->Fonts; family; family = family->next) {
341 if(!strncmp(plf->lfFaceName, family->FamilyName,
342 strlen(family->FamilyName)))
343 break;
345 if(family) {
346 for(afmle = family->afmlist; afmle; afmle = afmle->next) {
347 TRACE("Got '%s'\n", afmle->afm->FontName);
348 if( (b = (*proc)( &lf, &tm,
349 PSDRV_GetFontMetric( hdc, afmle->afm, &tm, &lf, 200 ),
350 lp )) )
351 bRet = b;
352 else break;
355 } else {
357 TRACE("lfFaceName = NULL\n");
358 for(family = physDev->pi->Fonts; family; family = family->next) {
359 afmle = family->afmlist;
360 TRACE("Got '%s'\n", afmle->afm->FontName);
361 if( (b = (*proc)( &lf, &tm,
362 PSDRV_GetFontMetric( hdc, afmle->afm, &tm, &lf, 200 ),
363 lp )) )
364 bRet = b;
365 else break;
368 return bRet;