Font updates for OS/2
[wxWidgets.git] / src / os2 / fontutil.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: msw/fontutil.cpp
3 // Purpose: font-related helper functions for wxMSW
4 // Author: Modified by David Webster for OS/2
5 // Modified by:
6 // Created: 01.03.00
7 // RCS-ID: $Id$
8 // Copyright: (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
11 #define DEBUG_PRINTF(NAME) { static int raz=0; \
12 printf( #NAME " %i\n",raz); fflush(stdout); \
13 raz++; \
14 }
15
16 // ============================================================================
17 // declarations
18 // ============================================================================
19
20 // ----------------------------------------------------------------------------
21 // headers
22 // ----------------------------------------------------------------------------
23
24 #ifdef __GNUG__
25 #pragma implementation "fontutil.h"
26 #endif
27
28 // For compilers that support precompilation, includes "wx.h".
29 #include "wx/wxprec.h"
30
31 #ifndef WX_PRECOMP
32 #include "wx/string.h"
33 #include "wx/log.h"
34 #include "wx/intl.h"
35 #endif //WX_PRECOMP
36
37 #include "wx/os2/private.h"
38
39 #include "wx/fontutil.h"
40 #include "wx/fontmap.h"
41
42 #include "wx/tokenzr.h"
43
44 // ============================================================================
45 // implementation
46 // ============================================================================
47
48 // ----------------------------------------------------------------------------
49 // wxNativeEncodingInfo
50 // ----------------------------------------------------------------------------
51
52 // convert to/from the string representation: format is
53 // encodingid;facename[;charset]
54
55 bool wxNativeEncodingInfo::FromString(
56 const wxString& rsStr
57 )
58 {
59 wxStringTokenizer vTokenizer(rsStr, _T(";"));
60 wxString sEncid = vTokenizer.GetNextToken();
61 long lEnc;
62
63 if (!sEncid.ToLong(&lEnc))
64 return FALSE;
65 encoding = (wxFontEncoding)lEnc;
66 facename = vTokenizer.GetNextToken();
67 if (!facename)
68 return FALSE;
69
70 wxString sTmp = vTokenizer.GetNextToken();
71
72 if (!sTmp)
73 {
74 charset = 850;
75 }
76 else
77 {
78 if ( wxSscanf(sTmp, _T("%u"), &charset) != 1 )
79 {
80 // should be a number!
81 return FALSE;
82 }
83 }
84 return TRUE;
85 } // end of wxNativeEncodingInfo::FromString
86
87 wxString wxNativeEncodingInfo::ToString() const
88 {
89 wxString sStr;
90
91 sStr << (long)encoding << _T(';') << facename;
92
93 if (charset != 850)
94 {
95 sStr << _T(';') << charset;
96 }
97 return sStr;
98 } // end of wxNativeEncodingInfo::ToString
99
100 // ----------------------------------------------------------------------------
101 // helper functions
102 // ----------------------------------------------------------------------------
103
104 bool wxGetNativeFontEncoding(
105 wxFontEncoding vEncoding
106 , wxNativeEncodingInfo* pInfo
107 )
108 {
109 wxCHECK_MSG(pInfo, FALSE, _T("bad pointer in wxGetNativeFontEncoding") );
110 if (vEncoding == wxFONTENCODING_DEFAULT)
111 {
112 vEncoding = wxFont::GetDefaultEncoding();
113 }
114 switch (vEncoding)
115 {
116 case wxFONTENCODING_ISO8859_1:
117 case wxFONTENCODING_ISO8859_15:
118 case wxFONTENCODING_CP1250:
119 pInfo->charset = 1250;
120 break;
121
122 case wxFONTENCODING_ISO8859_2:
123 case wxFONTENCODING_CP1252:
124 pInfo->charset = 1252;
125 break;
126
127 case wxFONTENCODING_ISO8859_4:
128 case wxFONTENCODING_ISO8859_10:
129 pInfo->charset = 921; // what is baltic?
130 break;
131
132 case wxFONTENCODING_ISO8859_5:
133 case wxFONTENCODING_CP1251:
134 pInfo->charset = 1251;
135 break;
136
137 case wxFONTENCODING_ISO8859_6:
138 pInfo->charset = 864;
139 break;
140
141 case wxFONTENCODING_ISO8859_7:
142 pInfo->charset = 869;
143 break;
144
145 case wxFONTENCODING_ISO8859_8:
146 pInfo->charset = 862;
147 break;
148
149 case wxFONTENCODING_ISO8859_9:
150 pInfo->charset = 857;
151 break;
152
153 case wxFONTENCODING_ISO8859_11:
154 pInfo->charset = 874; // what is thai
155 break;
156
157 case wxFONTENCODING_CP437:
158 pInfo->charset = 437;
159 break;
160
161 default:
162 wxFAIL_MSG(wxT("unsupported encoding"));
163 // fall through
164
165 case wxFONTENCODING_SYSTEM:
166 pInfo->charset = 850;
167 break;
168 }
169 return TRUE;
170 } // end of wxGetNativeFontEncoding
171
172 bool wxTestFontEncoding(
173 const wxNativeEncodingInfo& rInfo
174 )
175 {
176 FATTRS vLogFont;
177 HPS hPS;
178
179 hPS = ::WinGetPS(HWND_DESKTOP);
180
181 memset(&vLogFont, '\0', sizeof(FATTRS)); // all default values
182 vLogFont.usRecordLength = sizeof(FATTRS);
183 vLogFont.usCodePage = rInfo.charset;
184 vLogFont.lMaxBaselineExt = 0L; // Outline fonts should use 0
185 vLogFont.lAveCharWidth = 0L; // Outline fonts should use 0
186 vLogFont.fsFontUse = FATTR_FONTUSE_OUTLINE | // only outline fonts allowed
187 FATTR_FONTUSE_TRANSFORMABLE; // may be transformed
188
189 strncpy(vLogFont.szFacename, rInfo.facename.c_str(), sizeof(vLogFont.szFacename));
190
191 if (!::GpiCreateLogFont( hPS
192 ,NULL
193 ,1L
194 ,&vLogFont
195 ))
196 {
197 ::WinReleasePS(hPS);
198 return FALSE;
199 }
200 ::WinReleasePS(hPS);
201 return TRUE;
202 } // end of wxTestFontEncoding
203
204 // ----------------------------------------------------------------------------
205 // wxFont <-> LOGFONT conversion
206 // ----------------------------------------------------------------------------
207
208 void wxFillLogFont(
209 LOGFONT* pLogFont // OS2 GPI FATTRS
210 , PFACENAMEDESC pFaceName
211 , const wxFont* pFont
212 )
213 {
214 wxString sFace;
215 USHORT uWeight;
216 int nItalic;
217
218 pLogFont->fsSelection = 0;
219 pLogFont->fsSelection = FATTR_SEL_OUTLINE; // we will alway use only outlines
220 pFaceName->usWeightClass = 0;
221 pFaceName->flOptions = 0;
222 switch (pFont->GetFamily())
223 {
224 case wxSCRIPT:
225 sFace = _T("Script");
226 break;
227
228 case wxDECORATIVE:
229 case wxROMAN:
230 sFace = _T("Times New Roman");
231 break;
232
233 case wxTELETYPE:
234 case wxMODERN:
235 sFace = _T("Courier New");
236 break;
237
238 case wxSWISS:
239 sFace = _T("WarpSans");
240 break;
241
242 case wxDEFAULT:
243 default:
244 sFace = _T("Helv");
245 }
246
247 switch (pFont->GetWeight())
248 {
249 default:
250 wxFAIL_MSG(_T("unknown font weight"));
251 uWeight = FWEIGHT_DONT_CARE;
252 break;
253
254 case wxNORMAL:
255 uWeight = FWEIGHT_NORMAL;
256 break;
257
258 case wxLIGHT:
259 uWeight = FWEIGHT_LIGHT;
260 break;
261
262 case wxBOLD:
263 uWeight = FWEIGHT_BOLD;
264 pLogFont->fsSelection |= FATTR_SEL_BOLD;
265 break;
266
267 case wxFONTWEIGHT_MAX:
268 uWeight = FWEIGHT_ULTRA_BOLD;
269 pLogFont->fsSelection |= FATTR_SEL_BOLD;
270 break;
271 }
272 pFaceName->usWeightClass |= uWeight;
273
274 switch (pFont->GetStyle())
275 {
276 case wxITALIC:
277 case wxSLANT:
278 nItalic = FTYPE_ITALIC;
279 pLogFont->fsSelection |= FATTR_SEL_ITALIC;
280 break;
281
282 default:
283 wxFAIL_MSG(wxT("unknown font slant"));
284 // fall through
285
286 case wxNORMAL:
287 nItalic = 0;
288 break;
289 }
290 pFaceName->flOptions |= nItalic;
291 if(pFont->GetUnderlined())
292 pLogFont->fsSelection |= FATTR_SEL_UNDERSCORE;
293
294 //
295 // In PM a font's height is expressed in points. A point equals
296 // approximately 1/72 of an inch. We'll assume for now that,
297 // like Windows, that fonts are 96 dpi.
298 //
299 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
300 HDC hDC = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
301 LONG lStart = CAPS_FAMILY;
302 LONG lCount = CAPS_VERTICAL_RESOLUTION;
303 LONG alArray[CAPS_VERTICAL_RESOLUTION];
304 LONG lRes;
305 int nPpInch;
306
307
308 ::DevQueryCaps(hDC, lStart, lCount, alArray);
309 lRes = alArray[CAPS_VERTICAL_RESOLUTION-1];
310 if (lRes > 0)
311 nPpInch = (int)(lRes/39.6); // lres is in pixels per meter
312 else
313 nPpInch = 96;
314
315 int nHeight = (pFont->GetPointSize() * nPpInch/72);
316 wxString sFacename = pFont->GetFaceName();
317
318 if (!!sFacename)
319 {
320 sFace = sFacename;
321 }
322 //else: ff_face is a reasonable default facename for this font family
323
324 //
325 // Deal with encoding now
326 //
327 wxNativeEncodingInfo vInfo;
328 wxFontEncoding vEncoding = pFont->GetEncoding();
329
330 if (!wxGetNativeFontEncoding( vEncoding
331 ,&vInfo
332 ))
333 {
334 if ( !wxTheFontMapper->GetAltForEncoding( vEncoding
335 ,&vInfo
336 ))
337 {
338 //
339 // Unsupported encoding, replace with the default
340 //
341 vInfo.charset = 850;
342 }
343 }
344
345 if (!vInfo.facename.IsEmpty() )
346 {
347 //
348 // The facename determined by the encoding overrides everything else
349 //
350 sFace = vInfo.facename;
351 }
352
353 //
354 // Transfer all the data to LOGFONT
355 //
356 pLogFont->usRecordLength = sizeof(FATTRS);
357 wxStrcpy(pLogFont->szFacename, sFace.c_str());
358 pLogFont->usCodePage = vInfo.charset;
359 pLogFont->fsFontUse |= FATTR_FONTUSE_OUTLINE |
360 FATTR_FONTUSE_TRANSFORMABLE;
361 } // end of wxFillLogFont
362
363 wxFont wxCreateFontFromLogFont(
364 const LOGFONT* pLogFont
365 , const PFONTMETRICS pFM
366 , PFACENAMEDESC pFaceName
367 )
368 {
369 //
370 // Extract family from facename
371 //
372 int nFontFamily;
373
374 if (strcmp(pLogFont->szFacename, "Times New Roman") == 0)
375 nFontFamily = wxROMAN;
376 else if (strcmp(pLogFont->szFacename, "WarpSans") == 0)
377 nFontFamily = wxSWISS;
378 else if (strcmp(pLogFont->szFacename, "Script") == 0)
379 nFontFamily = wxSCRIPT;
380 else if (strcmp(pLogFont->szFacename, "Courier New") == 0)
381 nFontFamily = wxMODERN;
382 else
383 nFontFamily = wxSWISS;
384
385 //
386 // Weight and Style
387 //
388 int nFontWeight = wxNORMAL;
389
390 switch (pFaceName->usWeightClass)
391 {
392 case FWEIGHT_LIGHT:
393 nFontWeight = wxLIGHT;
394 break;
395
396 default:
397 case FWEIGHT_NORMAL:
398 nFontWeight = wxNORMAL;
399 break;
400
401 case FWEIGHT_BOLD:
402 nFontWeight = wxBOLD;
403 break;
404 }
405
406 int nFontStyle;
407
408 if(pLogFont->fsSelection & FATTR_SEL_ITALIC)
409 nFontStyle = wxITALIC;
410 else
411 nFontStyle = wxNORMAL;
412
413 bool bFontUnderline = (pLogFont->fsSelection & FATTR_SEL_UNDERSCORE);
414 wxString sFontFace = pLogFont->szFacename;
415 int nFontPoints = pFM->lEmHeight;
416 wxFontEncoding vFontEncoding;
417
418 switch (pLogFont->usCodePage)
419 {
420 default:
421 wxFAIL_MSG(wxT("unsupported charset"));
422 // fall through
423
424 case 850:
425 vFontEncoding = wxFONTENCODING_CP1252;
426 break;
427
428 case 1250:
429 vFontEncoding = wxFONTENCODING_CP1250;
430 break;
431
432 case 921:
433 vFontEncoding = wxFONTENCODING_CP1257;
434 break;
435
436 case 866:
437 vFontEncoding = wxFONTENCODING_CP1251;
438 break;
439
440 case 864:
441 vFontEncoding = wxFONTENCODING_CP1256;
442 break;
443
444 case 869:
445 vFontEncoding = wxFONTENCODING_CP1253;
446 break;
447
448 case 862:
449 vFontEncoding = wxFONTENCODING_CP1255;
450 break;
451
452 case 857:
453 vFontEncoding = wxFONTENCODING_CP1254;
454 break;
455
456 case 874:
457 vFontEncoding = wxFONTENCODING_CP437;
458 break;
459
460 case 437:
461 vFontEncoding = wxFONTENCODING_CP437;
462 break;
463 }
464
465 return wxFont( nFontPoints
466 ,nFontFamily
467 ,nFontStyle
468 ,nFontWeight
469 ,bFontUnderline
470 ,sFontFace
471 ,vFontEncoding
472 );
473 } // end of wxCreateFontFromLogFont
474
475 int wxGpiStrcmp(
476 char* s0
477 , char* s1
478 )
479 { int l0;
480 int l1;
481 int l;
482 int d;
483 int d1;
484 int i;
485 int rc;
486
487 rc = 0;
488 if(s0 == NULL)
489 {
490 if(s1 == NULL)
491 return 0;
492 else
493 return 32;
494 }
495 else if(s1 == NULL)
496 return 32;
497
498 l0 = strlen(s0);
499 l1 = strlen(s1);
500 l = l0;
501 if(l0 != l1)
502 {
503 rc++;
504 if(l1 < l0)
505 l = l1;
506 }
507 for(i=0;i<l;i++)
508 {
509 d = s0[i]-s1[i];
510 if(!d)
511 continue;
512 d1 = toupper(s0[i]) - toupper(s1[i]);
513 if(!d1)
514 continue;
515 rc += abs(d);
516 }
517 return rc;
518 }
519