Separated stuff for shv background contextmenu to separate file.
[wine.git] / graphics / psdrv / font.c
blobe3f9b0c699934c216608a8f878439feb1c365f38
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"
12 DEFAULT_DEBUG_CHANNEL(psdrv)
16 /***********************************************************************
17 * PSDRV_FONT_SelectObject
19 HFONT16 PSDRV_FONT_SelectObject( DC * dc, HFONT16 hfont,
20 FONTOBJ *font )
22 HFONT16 prevfont = dc->w.hFont;
23 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
24 LOGFONT16 *lf = &(font->logfont);
25 BOOL bd = FALSE, it = FALSE;
26 AFMLISTENTRY *afmle;
27 AFM *afm;
28 FONTFAMILY *family;
29 char FaceName[LF_FACESIZE];
32 TRACE("FaceName = '%s' Height = %d Italic = %d Weight = %d\n",
33 lf->lfFaceName, lf->lfHeight, lf->lfItalic, lf->lfWeight);
35 dc->w.hFont = hfont;
37 if(lf->lfItalic)
38 it = TRUE;
39 if(lf->lfWeight > 550)
40 bd = TRUE;
41 strcpy(FaceName, lf->lfFaceName);
43 if(FaceName[0] == '\0') {
44 switch(lf->lfPitchAndFamily & 0xf0) {
45 case FF_DONTCARE:
46 break;
47 case FF_ROMAN:
48 case FF_SCRIPT:
49 strcpy(FaceName, "Times");
50 break;
51 case FF_SWISS:
52 strcpy(FaceName, "Helvetica");
53 break;
54 case FF_MODERN:
55 strcpy(FaceName, "Courier");
56 break;
57 case FF_DECORATIVE:
58 strcpy(FaceName, "Symbol");
59 break;
63 if(FaceName[0] == '\0') {
64 switch(lf->lfPitchAndFamily & 0x0f) {
65 case VARIABLE_PITCH:
66 strcpy(FaceName, "Times");
67 break;
68 default:
69 strcpy(FaceName, "Courier");
70 break;
74 TRACE("Trying to find facename '%s'\n", FaceName);
76 for(family = physDev->pi->Fonts; family; family = family->next) {
77 if(!strcmp(FaceName, family->FamilyName))
78 break;
80 if(!family)
81 family = physDev->pi->Fonts;
83 TRACE("Got family '%s'\n", family->FamilyName);
85 for(afmle = family->afmlist; afmle; afmle = afmle->next) {
86 if( (bd == (afmle->afm->Weight == FW_BOLD)) &&
87 (it == (afmle->afm->ItalicAngle != 0.0)) )
88 break;
90 if(!afmle)
91 afmle = family->afmlist; /* not ideal */
93 afm = afmle->afm;
95 physDev->font.afm = afm;
96 physDev->font.tm.tmHeight = YLSTODS(dc, lf->lfHeight);
97 if(physDev->font.tm.tmHeight < 0) {
98 physDev->font.tm.tmHeight *= - (afm->FullAscender - afm->Descender) /
99 (afm->Ascender - afm->Descender);
100 TRACE("Fixed -ve height to %ld\n", physDev->font.tm.tmHeight);
102 physDev->font.size = physDev->font.tm.tmHeight * 1000.0 /
103 (afm->FullAscender - afm->Descender);
104 physDev->font.scale = physDev->font.size / 1000.0;
105 physDev->font.escapement = lf->lfEscapement;
106 physDev->font.tm.tmAscent = afm->FullAscender * physDev->font.scale;
107 physDev->font.tm.tmDescent = -afm->Descender * physDev->font.scale;
108 physDev->font.tm.tmInternalLeading = (afm->FullAscender - afm->Ascender)
109 * physDev->font.scale;
110 physDev->font.tm.tmExternalLeading = (1000.0 - afm->FullAscender)
111 * physDev->font.scale; /* ?? */
112 physDev->font.tm.tmAveCharWidth = afm->CharWidths[120] * /* x */
113 physDev->font.scale;
114 physDev->font.tm.tmMaxCharWidth = afm->CharWidths[77] * /* M */
115 physDev->font.scale;
116 physDev->font.tm.tmWeight = afm->Weight;
117 physDev->font.tm.tmItalic = afm->ItalicAngle != 0.0;
118 physDev->font.tm.tmUnderlined = lf->lfUnderline;
119 physDev->font.tm.tmStruckOut = lf->lfStrikeOut;
120 physDev->font.tm.tmFirstChar = 32;
121 physDev->font.tm.tmLastChar = 251;
122 physDev->font.tm.tmDefaultChar = 128;
123 physDev->font.tm.tmBreakChar = 32;
124 physDev->font.tm.tmPitchAndFamily = afm->IsFixedPitch ? 0 :
125 TMPF_FIXED_PITCH;
126 physDev->font.tm.tmPitchAndFamily |= TMPF_DEVICE;
127 physDev->font.tm.tmCharSet = ANSI_CHARSET;
128 physDev->font.tm.tmOverhang = 0;
129 physDev->font.tm.tmDigitizedAspectX = dc->w.devCaps->logPixelsY;
130 physDev->font.tm.tmDigitizedAspectY = dc->w.devCaps->logPixelsX;
132 physDev->font.set = FALSE;
134 TRACE("Selected PS font '%s' size %d weight %ld.\n",
135 physDev->font.afm->FontName, physDev->font.size,
136 physDev->font.tm.tmWeight );
137 TRACE("H = %ld As = %ld Des = %ld IL = %ld EL = %ld\n",
138 physDev->font.tm.tmHeight, physDev->font.tm.tmAscent,
139 physDev->font.tm.tmDescent, physDev->font.tm.tmInternalLeading,
140 physDev->font.tm.tmExternalLeading);
142 return prevfont;
145 /***********************************************************************
146 * PSDRV_GetTextMetrics
148 BOOL PSDRV_GetTextMetrics(DC *dc, TEXTMETRICA *metrics)
150 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
152 memcpy(metrics, &(physDev->font.tm), sizeof(physDev->font.tm));
153 return TRUE;
157 /***********************************************************************
158 * PSDRV_GetTextExtentPoint
160 BOOL PSDRV_GetTextExtentPoint( DC *dc, LPCSTR str, INT count,
161 LPSIZE size )
163 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
164 INT i;
165 float width;
167 size->cy = YDSTOLS(dc, physDev->font.tm.tmHeight);
168 width = 0.0;
170 for(i = 0; i < count && str[i]; i++) {
171 width += physDev->font.afm->CharWidths[ *((unsigned char *)str + i) ];
172 /* TRACE(psdrv, "Width after %dth char '%c' = %f\n", i, str[i], width);*/
174 width *= physDev->font.scale;
175 TRACE("Width after scale (%f) is %f\n", physDev->font.scale, width);
176 size->cx = XDSTOLS(dc, width);
178 return TRUE;
182 /***********************************************************************
183 * PSDRV_GetCharWidth
185 BOOL PSDRV_GetCharWidth( DC *dc, UINT firstChar, UINT lastChar,
186 LPINT buffer )
188 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
189 UINT i;
191 TRACE("first = %d last = %d\n", firstChar, lastChar);
193 if(lastChar > 0xff) return FALSE;
194 for( i = firstChar; i <= lastChar; i++ )
195 *buffer++ = physDev->font.afm->CharWidths[i] * physDev->font.scale;
197 return TRUE;
201 /***********************************************************************
202 * PSDRV_SetFont
204 BOOL PSDRV_SetFont( DC *dc )
206 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
207 BOOL ReEncode = FALSE;
209 PSDRV_WriteSetColor(dc, &physDev->font.color);
210 if(physDev->font.set) return TRUE;
212 if(physDev->font.afm->EncodingScheme &&
213 !strcmp(physDev->font.afm->EncodingScheme, "AdobeStandardEncoding"))
214 ReEncode = TRUE;
215 if(ReEncode)
216 PSDRV_WriteReencodeFont(dc);
217 PSDRV_WriteSetFont(dc, ReEncode);
218 physDev->font.set = TRUE;
219 return TRUE;
223 /***********************************************************************
224 * PSDRV_GetFontMetric
226 static UINT PSDRV_GetFontMetric(DC *dc, AFM *pafm, NEWTEXTMETRIC16 *pTM,
227 ENUMLOGFONTEX16 *pLF, INT16 size)
230 float scale = size / (pafm->FullAscender - pafm->Descender);
231 memset( pLF, 0, sizeof(*pLF) );
232 memset( pTM, 0, sizeof(*pTM) );
234 #define plf ((LPLOGFONT16)pLF)
235 plf->lfHeight = pTM->tmHeight = size;
236 plf->lfWidth = pTM->tmAveCharWidth = pafm->CharWidths[120] * scale;
237 plf->lfWeight = pTM->tmWeight = pafm->Weight;
238 plf->lfItalic = pTM->tmItalic = pafm->ItalicAngle != 0.0;
239 plf->lfUnderline = pTM->tmUnderlined = 0;
240 plf->lfStrikeOut = pTM->tmStruckOut = 0;
241 plf->lfCharSet = pTM->tmCharSet = ANSI_CHARSET;
243 /* convert pitch values */
245 pTM->tmPitchAndFamily = pafm->IsFixedPitch ? 0 : TMPF_FIXED_PITCH;
246 pTM->tmPitchAndFamily |= TMPF_DEVICE;
247 plf->lfPitchAndFamily = 0;
249 strncpy( plf->lfFaceName, pafm->FamilyName, LF_FACESIZE );
250 #undef plf
252 pTM->tmAscent = pafm->FullAscender * scale;
253 pTM->tmDescent = -pafm->Descender * scale;
254 pTM->tmInternalLeading = (pafm->FullAscender - pafm->Ascender) * scale;
255 pTM->tmMaxCharWidth = pafm->CharWidths[77] * scale;
256 pTM->tmDigitizedAspectX = dc->w.devCaps->logPixelsY;
257 pTM->tmDigitizedAspectY = dc->w.devCaps->logPixelsX;
259 *(INT*)&pTM->tmFirstChar = 32;
261 /* return font type */
263 return DEVICE_FONTTYPE;
267 /***********************************************************************
268 * PSDRV_EnumDeviceFonts
270 BOOL PSDRV_EnumDeviceFonts( DC* dc, LPLOGFONT16 plf,
271 DEVICEFONTENUMPROC proc, LPARAM lp )
273 ENUMLOGFONTEX16 lf;
274 NEWTEXTMETRIC16 tm;
275 BOOL b, bRet = 0;
276 AFMLISTENTRY *afmle;
277 FONTFAMILY *family;
278 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
280 if( plf->lfFaceName[0] ) {
281 TRACE("lfFaceName = '%s'\n", plf->lfFaceName);
282 for(family = physDev->pi->Fonts; family; family = family->next) {
283 if(!strncmp(plf->lfFaceName, family->FamilyName,
284 strlen(family->FamilyName)))
285 break;
287 if(family) {
288 for(afmle = family->afmlist; afmle; afmle = afmle->next) {
289 TRACE("Got '%s'\n", afmle->afm->FontName);
290 if( (b = (*proc)( (LPENUMLOGFONT16)&lf, &tm,
291 PSDRV_GetFontMetric( dc, afmle->afm, &tm, &lf, 200 ),
292 lp )) )
293 bRet = b;
294 else break;
297 } else {
299 TRACE("lfFaceName = NULL\n");
300 for(family = physDev->pi->Fonts; family; family = family->next) {
301 afmle = family->afmlist;
302 TRACE("Got '%s'\n", afmle->afm->FontName);
303 if( (b = (*proc)( (LPENUMLOGFONT16)&lf, &tm,
304 PSDRV_GetFontMetric( dc, afmle->afm, &tm, &lf, 200 ),
305 lp )) )
306 bRet = b;
307 else break;
310 return bRet;