Added Finnish keyboard layout.
[wine/hacks.git] / graphics / psdrv / font.c
blob61830f76cc61619bf906100b808afc427390c08e
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 "debug.h"
14 /***********************************************************************
15 * PSDRV_FONT_SelectObject
17 HFONT16 PSDRV_FONT_SelectObject( DC * dc, HFONT16 hfont,
18 FONTOBJ *font )
20 HFONT16 prevfont = dc->w.hFont;
21 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
22 LOGFONT16 *lf = &(font->logfont);
23 BOOL bd = FALSE, it = FALSE;
24 AFMLISTENTRY *afmle;
25 AFM *afm;
26 FONTFAMILY *family;
27 char FaceName[LF_FACESIZE];
30 TRACE(psdrv, "FaceName = '%s' Height = %d Italic = %d Weight = %d\n",
31 lf->lfFaceName, lf->lfHeight, lf->lfItalic, lf->lfWeight);
33 dc->w.hFont = hfont;
35 if(lf->lfItalic)
36 it = TRUE;
37 if(lf->lfWeight > 550)
38 bd = TRUE;
39 strcpy(FaceName, lf->lfFaceName);
41 if(FaceName[0] == '\0') {
42 switch(lf->lfPitchAndFamily & 0xf0) {
43 case FF_DONTCARE:
44 break;
45 case FF_ROMAN:
46 case FF_SCRIPT:
47 strcpy(FaceName, "Times");
48 break;
49 case FF_SWISS:
50 strcpy(FaceName, "Helvetica");
51 break;
52 case FF_MODERN:
53 strcpy(FaceName, "Courier");
54 break;
55 case FF_DECORATIVE:
56 strcpy(FaceName, "Symbol");
57 break;
61 if(FaceName[0] == '\0') {
62 switch(lf->lfPitchAndFamily & 0x0f) {
63 case VARIABLE_PITCH:
64 strcpy(FaceName, "Times");
65 break;
66 default:
67 strcpy(FaceName, "Courier");
68 break;
72 TRACE(psdrv, "Trying to find facename '%s'\n", FaceName);
74 for(family = physDev->pi->Fonts; family; family = family->next) {
75 if(!strcmp(FaceName, family->FamilyName))
76 break;
78 if(!family)
79 family = physDev->pi->Fonts;
81 TRACE(psdrv, "Got family '%s'\n", family->FamilyName);
83 for(afmle = family->afmlist; afmle; afmle = afmle->next) {
84 if( (bd == (afmle->afm->Weight == FW_BOLD)) &&
85 (it == (afmle->afm->ItalicAngle != 0.0)) )
86 break;
88 if(!afmle)
89 afmle = family->afmlist; /* not ideal */
91 afm = afmle->afm;
93 physDev->font.afm = afm;
94 physDev->font.tm.tmHeight = YLSTODS(dc, lf->lfHeight);
95 if(physDev->font.tm.tmHeight < 0) {
96 physDev->font.tm.tmHeight *= - (afm->FullAscender - afm->Descender) /
97 (afm->Ascender - afm->Descender);
98 TRACE(psdrv, "Fixed -ve height to %d\n", physDev->font.tm.tmHeight);
100 physDev->font.size = physDev->font.tm.tmHeight * 1000.0 /
101 (afm->FullAscender - afm->Descender);
102 physDev->font.scale = physDev->font.size / 1000.0;
103 physDev->font.escapement = lf->lfEscapement;
104 physDev->font.tm.tmAscent = afm->FullAscender * physDev->font.scale;
105 physDev->font.tm.tmDescent = -afm->Descender * physDev->font.scale;
106 physDev->font.tm.tmInternalLeading = (afm->FullAscender - afm->Ascender)
107 * physDev->font.scale;
108 physDev->font.tm.tmExternalLeading = (1000.0 - afm->FullAscender)
109 * physDev->font.scale; /* ?? */
110 physDev->font.tm.tmAveCharWidth = afm->CharWidths[120] * /* x */
111 physDev->font.scale;
112 physDev->font.tm.tmMaxCharWidth = afm->CharWidths[77] * /* M */
113 physDev->font.scale;
114 physDev->font.tm.tmWeight = afm->Weight;
115 physDev->font.tm.tmItalic = afm->ItalicAngle != 0.0;
116 physDev->font.tm.tmUnderlined = lf->lfUnderline;
117 physDev->font.tm.tmStruckOut = lf->lfStrikeOut;
118 physDev->font.tm.tmFirstChar = 32;
119 physDev->font.tm.tmLastChar = 251;
120 physDev->font.tm.tmDefaultChar = 128;
121 physDev->font.tm.tmBreakChar = 32;
122 physDev->font.tm.tmPitchAndFamily = afm->IsFixedPitch ? 0 :
123 TMPF_FIXED_PITCH;
124 physDev->font.tm.tmPitchAndFamily |= TMPF_DEVICE;
125 physDev->font.tm.tmCharSet = ANSI_CHARSET;
126 physDev->font.tm.tmOverhang = 0;
127 physDev->font.tm.tmDigitizedAspectX = dc->w.devCaps->logPixelsY;
128 physDev->font.tm.tmDigitizedAspectY = dc->w.devCaps->logPixelsX;
130 physDev->font.set = FALSE;
132 TRACE(psdrv, "Selected PS font '%s' size %d weight %d.\n",
133 physDev->font.afm->FontName, physDev->font.size,
134 physDev->font.tm.tmWeight );
135 TRACE(psdrv, "H = %d As = %d Des = %d IL = %d EL = %d\n",
136 physDev->font.tm.tmHeight, physDev->font.tm.tmAscent,
137 physDev->font.tm.tmDescent, physDev->font.tm.tmInternalLeading,
138 physDev->font.tm.tmExternalLeading);
140 return prevfont;
143 /***********************************************************************
144 * PSDRV_GetTextMetrics
146 BOOL PSDRV_GetTextMetrics(DC *dc, TEXTMETRICA *metrics)
148 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
150 memcpy(metrics, &(physDev->font.tm), sizeof(physDev->font.tm));
151 return TRUE;
155 /***********************************************************************
156 * PSDRV_GetTextExtentPoint
158 BOOL PSDRV_GetTextExtentPoint( DC *dc, LPCSTR str, INT count,
159 LPSIZE size )
161 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
162 INT i;
163 float width;
165 size->cy = YDSTOLS(dc, physDev->font.tm.tmHeight);
166 width = 0.0;
168 for(i = 0; i < count && str[i]; i++) {
169 width += physDev->font.afm->CharWidths[ *((unsigned char *)str + i) ];
170 /* TRACE(psdrv, "Width after %dth char '%c' = %f\n", i, str[i], width);*/
172 width *= physDev->font.scale;
173 TRACE(psdrv, "Width after scale (%f) is %f\n", physDev->font.scale, width);
174 size->cx = XDSTOLS(dc, width);
176 return TRUE;
180 /***********************************************************************
181 * PSDRV_GetCharWidth
183 BOOL PSDRV_GetCharWidth( DC *dc, UINT firstChar, UINT lastChar,
184 LPINT buffer )
186 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
187 UINT i;
189 TRACE(psdrv, "first = %d last = %d\n", firstChar, lastChar);
191 for( i = firstChar; i <= lastChar; i++ )
192 *buffer++ = physDev->font.afm->CharWidths[i] * physDev->font.scale;
194 return TRUE;
198 /***********************************************************************
199 * PSDRV_SetFont
201 BOOL PSDRV_SetFont( DC *dc )
203 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
204 BOOL ReEncode = FALSE;
206 PSDRV_WriteSetColor(dc, &physDev->font.color);
207 if(physDev->font.set) return TRUE;
209 if(physDev->font.afm->EncodingScheme &&
210 !strcmp(physDev->font.afm->EncodingScheme, "AdobeStandardEncoding"))
211 ReEncode = TRUE;
212 if(ReEncode)
213 PSDRV_WriteReencodeFont(dc);
214 PSDRV_WriteSetFont(dc, ReEncode);
215 physDev->font.set = TRUE;
216 return TRUE;
220 /***********************************************************************
221 * PSDRV_GetFontMetric
223 static UINT PSDRV_GetFontMetric(DC *dc, AFM *pafm, NEWTEXTMETRIC16 *pTM,
224 ENUMLOGFONTEX16 *pLF, INT16 size)
227 float scale = size / (pafm->FullAscender - pafm->Descender);
228 memset( pLF, 0, sizeof(*pLF) );
229 memset( pTM, 0, sizeof(*pTM) );
231 #define plf ((LPLOGFONT16)pLF)
232 plf->lfHeight = pTM->tmHeight = size;
233 plf->lfWidth = pTM->tmAveCharWidth = pafm->CharWidths[120] * scale;
234 plf->lfWeight = pTM->tmWeight = pafm->Weight;
235 plf->lfItalic = pTM->tmItalic = pafm->ItalicAngle != 0.0;
236 plf->lfUnderline = pTM->tmUnderlined = 0;
237 plf->lfStrikeOut = pTM->tmStruckOut = 0;
238 plf->lfCharSet = pTM->tmCharSet = ANSI_CHARSET;
240 /* convert pitch values */
242 pTM->tmPitchAndFamily = pafm->IsFixedPitch ? 0 : TMPF_FIXED_PITCH;
243 pTM->tmPitchAndFamily |= TMPF_DEVICE;
244 plf->lfPitchAndFamily = 0;
246 strncpy( plf->lfFaceName, pafm->FamilyName, LF_FACESIZE );
247 #undef plf
249 pTM->tmAscent = pafm->FullAscender * scale;
250 pTM->tmDescent = -pafm->Descender * scale;
251 pTM->tmInternalLeading = (pafm->FullAscender - pafm->Ascender) * scale;
252 pTM->tmMaxCharWidth = pafm->CharWidths[77] * scale;
253 pTM->tmDigitizedAspectX = dc->w.devCaps->logPixelsY;
254 pTM->tmDigitizedAspectY = dc->w.devCaps->logPixelsX;
256 *(INT*)&pTM->tmFirstChar = 32;
258 /* return font type */
260 return DEVICE_FONTTYPE;
264 /***********************************************************************
265 * PSDRV_EnumDeviceFonts
267 BOOL PSDRV_EnumDeviceFonts( DC* dc, LPLOGFONT16 plf,
268 DEVICEFONTENUMPROC proc, LPARAM lp )
270 ENUMLOGFONTEX16 lf;
271 NEWTEXTMETRIC16 tm;
272 BOOL b, bRet = 0;
273 AFMLISTENTRY *afmle;
274 FONTFAMILY *family;
275 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
277 if( plf->lfFaceName[0] ) {
278 TRACE(psdrv, "lfFaceName = '%s'\n", plf->lfFaceName);
279 for(family = physDev->pi->Fonts; family; family = family->next) {
280 if(!strncmp(plf->lfFaceName, family->FamilyName,
281 strlen(family->FamilyName)))
282 break;
284 if(family) {
285 for(afmle = family->afmlist; afmle; afmle = afmle->next) {
286 TRACE(psdrv, "Got '%s'\n", afmle->afm->FontName);
287 if( (b = (*proc)( (LPENUMLOGFONT16)&lf, &tm,
288 PSDRV_GetFontMetric( dc, afmle->afm, &tm, &lf, 200 ),
289 lp )) )
290 bRet = b;
291 else break;
294 } else {
296 TRACE(psdrv, "lfFaceName = NULL\n");
297 for(family = physDev->pi->Fonts; family; family = family->next) {
298 afmle = family->afmlist;
299 TRACE(psdrv, "Got '%s'\n", afmle->afm->FontName);
300 if( (b = (*proc)( (LPENUMLOGFONT16)&lf, &tm,
301 PSDRV_GetFontMetric( dc, afmle->afm, &tm, &lf, 200 ),
302 lp )) )
303 bRet = b;
304 else break;
307 return bRet;