wxNativeEncoding::To/FromString now stores wxFontEncoding info as well (don't worry...
[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
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifndef WX_PRECOMP
24 #include "wx/string.h"
25 #include "wx/log.h"
26 #include "wx/intl.h"
27 #endif //WX_PRECOMP
28
29 #include "wx/os2/private.h"
30
31 #include "wx/fontutil.h"
32 #include "wx/fontmap.h"
33
34 #include "wx/tokenzr.h"
35
36 // ============================================================================
37 // implementation
38 // ============================================================================
39
40 // ----------------------------------------------------------------------------
41 // wxNativeEncodingInfo
42 // ----------------------------------------------------------------------------
43
44 // convert to/from the string representation: format is
45 // encodingid;facename[;charset]
46
47 bool wxNativeEncodingInfo::FromString(const wxString& s)
48 {
49 wxStringTokenizer tokenizer(s, _T(";"));
50
51 wxString encid = tokenizer.GetNextToken();
52 long enc;
53 if ( !encid.ToLong(&enc) )
54 return FALSE;
55 encoding = (wxFontEncoding)enc;
56
57 facename = tokenizer.GetNextToken();
58 if ( !facename )
59 return FALSE;
60
61 wxString tmp = tokenizer.GetNextToken();
62 if ( !tmp )
63 {
64 // default charset (don't use DEFAULT_CHARSET though because of subtle
65 // Windows 9x/NT differences in handling it)
66 // TODO: what is this for OS/2?
67 // charset = ANSI_CHARSET;
68 }
69 else
70 {
71 if ( wxSscanf(tmp, _T("%u"), &charset) != 1 )
72 {
73 // should be a number!
74 return FALSE;
75 }
76 }
77
78 return TRUE;
79 }
80
81 wxString wxNativeEncodingInfo::ToString() const
82 {
83 wxString s;
84
85 s << (long)encoding << _T(';') << facename;
86
87 // TODO: what is this for OS/2?
88 /*
89 if ( charset != ANSI_CHARSET )
90 {
91 s << _T(';') << charset;
92 }
93 */
94 return s;
95 }
96
97 // ----------------------------------------------------------------------------
98 // helper functions
99 // ----------------------------------------------------------------------------
100
101 bool wxGetNativeFontEncoding(wxFontEncoding encoding,
102 wxNativeEncodingInfo *info)
103 {
104 wxCHECK_MSG( info, FALSE, _T("bad pointer in wxGetNativeFontEncoding") );
105
106 if ( encoding == wxFONTENCODING_DEFAULT )
107 {
108 encoding = wxFont::GetDefaultEncoding();
109 }
110
111 switch ( encoding )
112 {
113 // TODO: fix this for OS2
114 /*
115 // although this function is supposed to return an exact match, do do
116 // some mappings here for the most common case of "standard" encoding
117 case wxFONTENCODING_SYSTEM:
118 case wxFONTENCODING_ISO8859_1:
119 case wxFONTENCODING_ISO8859_15:
120 case wxFONTENCODING_CP1252:
121 info->charset = ANSI_CHARSET;
122 break;
123
124 case wxFONTENCODING_CP1250:
125 info->charset = EASTEUROPE_CHARSET;
126 break;
127
128 case wxFONTENCODING_CP1251:
129 info->charset = RUSSIAN_CHARSET;
130 break;
131
132 case wxFONTENCODING_CP1253:
133 info->charset = GREEK_CHARSET;
134 break;
135
136 case wxFONTENCODING_CP1254:
137 info->charset = TURKISH_CHARSET;
138 break;
139
140 case wxFONTENCODING_CP1255:
141 info->charset = HEBREW_CHARSET;
142 break;
143
144 case wxFONTENCODING_CP1256:
145 info->charset = ARABIC_CHARSET;
146 break;
147
148 case wxFONTENCODING_CP1257:
149 info->charset = BALTIC_CHARSET;
150 break;
151
152 case wxFONTENCODING_CP874:
153 info->charset = THAI_CHARSET;
154 break;
155
156 case wxFONTENCODING_CP437:
157 info->charset = OEM_CHARSET;
158 break;
159 */
160 default:
161 // no way to translate this encoding into a Windows charset
162 return FALSE;
163 }
164
165 return TRUE;
166 }
167
168 bool wxTestFontEncoding(const wxNativeEncodingInfo& info)
169 {
170 // TODO:
171 /*
172 // try to create such font
173 LOGFONT lf;
174 wxZeroMemory(lf); // all default values
175
176 lf.lfCharSet = info.charset;
177 strncpy(lf.lfFaceName, info.facename, sizeof(lf.lfFaceName));
178
179 HFONT hfont = ::CreateFontIndirect(&lf);
180 if ( !hfont )
181 {
182 // no such font
183 return FALSE;
184 }
185
186 ::DeleteObject((HGDIOBJ)hfont);
187 */
188 return TRUE;
189 }
190
191 // ----------------------------------------------------------------------------
192 // wxFont <-> LOGFONT conversion
193 // ----------------------------------------------------------------------------
194
195 #if 0
196 void wxFillLogFont(LOGFONT *logFont, const wxFont *font)
197 {
198 int ff_family;
199 wxString ff_face;
200
201 switch ( font->GetFamily() )
202 {
203 case wxSCRIPT:
204 ff_family = FF_SCRIPT;
205 ff_face = _T("Script");
206 break;
207
208 case wxDECORATIVE:
209 ff_family = FF_DECORATIVE;
210 break;
211
212 case wxROMAN:
213 ff_family = FF_ROMAN;
214 ff_face = _T("Times New Roman");
215 break;
216
217 case wxTELETYPE:
218 case wxMODERN:
219 ff_family = FF_MODERN;
220 ff_face = _T("Courier New");
221 break;
222
223 case wxSWISS:
224 ff_family = FF_SWISS;
225 ff_face = _T("Arial");
226 break;
227
228 case wxDEFAULT:
229 default:
230 ff_family = FF_SWISS;
231 ff_face = _T("MS Sans Serif");
232 }
233
234 BYTE ff_italic;
235 switch ( font->GetStyle() )
236 {
237 case wxITALIC:
238 case wxSLANT:
239 ff_italic = 1;
240 break;
241
242 default:
243 wxFAIL_MSG(wxT("unknown font slant"));
244 // fall through
245
246 case wxNORMAL:
247 ff_italic = 0;
248 }
249
250 int ff_weight;
251 switch ( font->GetWeight() )
252 {
253 default:
254 wxFAIL_MSG(_T("unknown font weight"));
255 // fall through
256
257 case wxNORMAL:
258 ff_weight = FW_NORMAL;
259 break;
260
261 case wxLIGHT:
262 ff_weight = FW_LIGHT;
263 break;
264
265 case wxBOLD:
266 ff_weight = FW_BOLD;
267 break;
268 }
269
270 #if 0
271 HDC dc = ::GetDC(NULL);
272 int ppInch = ::GetDeviceCaps(dc, LOGPIXELSY);
273 ::ReleaseDC(NULL, dc);
274 #else
275 // New behaviour: apparently ppInch varies according to Large/Small Fonts
276 // setting in Windows. This messes up fonts. So, set ppInch to a constant
277 // 96 dpi.
278 static const int ppInch = 96;
279 #endif // 0/1
280
281 #if wxFONT_SIZE_COMPATIBILITY
282 // Incorrect, but compatible with old wxWindows behaviour
283 int nHeight = (font->GetPointSize()*ppInch/72);
284 #else
285 // Correct for Windows compatibility
286 int nHeight = - (font->GetPointSize()*ppInch/72);
287 #endif
288
289 wxString facename = font->GetFaceName();
290 if ( !!facename )
291 {
292 ff_face = facename;
293 }
294 //else: ff_face is a reasonable default facename for this font family
295
296 // deal with encoding now
297 wxNativeEncodingInfo info;
298 wxFontEncoding encoding = font->GetEncoding();
299 if ( !wxGetNativeFontEncoding(encoding, &info) )
300 {
301 if ( !wxTheFontMapper->GetAltForEncoding(encoding, &info) )
302 {
303 // unsupported encoding, replace with the default
304 info.charset = ANSI_CHARSET;
305 }
306 }
307
308 if ( !info.facename.IsEmpty() )
309 {
310 // the facename determined by the encoding overrides everything else
311 ff_face = info.facename;
312 }
313
314 // transfer all the data to LOGFONT
315 logFont->lfHeight = nHeight;
316 logFont->lfWidth = 0;
317 logFont->lfEscapement = 0;
318 logFont->lfOrientation = 0;
319 logFont->lfWeight = ff_weight;
320 logFont->lfItalic = ff_italic;
321 logFont->lfUnderline = (BYTE)font->GetUnderlined();
322 logFont->lfStrikeOut = 0;
323 logFont->lfCharSet = info.charset;
324 logFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
325 logFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
326 logFont->lfQuality = PROOF_QUALITY;
327 logFont->lfPitchAndFamily = DEFAULT_PITCH | ff_family;
328 wxStrncpy(logFont->lfFaceName, ff_face, WXSIZEOF(logFont->lfFaceName));
329 }
330
331 wxFont wxCreateFontFromLogFont(const LOGFONT *logFont)
332 {
333 // extract family from pitch-and-family
334 int lfFamily = logFont->lfPitchAndFamily;
335 if ( lfFamily & FIXED_PITCH )
336 lfFamily -= FIXED_PITCH;
337 if ( lfFamily & VARIABLE_PITCH )
338 lfFamily -= VARIABLE_PITCH;
339
340 int fontFamily;
341 switch ( lfFamily )
342 {
343 case FF_ROMAN:
344 fontFamily = wxROMAN;
345 break;
346
347 case FF_SWISS:
348 fontFamily = wxSWISS;
349 break;
350
351 case FF_SCRIPT:
352 fontFamily = wxSCRIPT;
353 break;
354
355 case FF_MODERN:
356 fontFamily = wxMODERN;
357 break;
358
359 case FF_DECORATIVE:
360 fontFamily = wxDECORATIVE;
361 break;
362
363 default:
364 fontFamily = wxSWISS;
365 }
366
367 // weight and style
368 int fontWeight = wxNORMAL;
369 switch ( logFont->lfWeight )
370 {
371 case FW_LIGHT:
372 fontWeight = wxLIGHT;
373 break;
374
375 default:
376 case FW_NORMAL:
377 fontWeight = wxNORMAL;
378 break;
379
380 case FW_BOLD:
381 fontWeight = wxBOLD;
382 break;
383 }
384
385 int fontStyle = logFont->lfItalic ? wxITALIC : wxNORMAL;
386
387 bool fontUnderline = logFont->lfUnderline != 0;
388
389 wxString fontFace = logFont->lfFaceName;
390
391 // font size
392 HDC dc = ::GetDC(NULL);
393
394 // remember that 1pt = 1/72inch
395 int height = abs(logFont->lfHeight);
396 int fontPoints = (72*height)/GetDeviceCaps(dc, LOGPIXELSY);
397
398 ::ReleaseDC(NULL, dc);
399
400 wxFontEncoding fontEncoding;
401 switch ( logFont->lfCharSet )
402 {
403 default:
404 wxFAIL_MSG(wxT("unsupported charset"));
405 // fall through
406
407 case ANSI_CHARSET:
408 fontEncoding = wxFONTENCODING_CP1252;
409 break;
410
411 #ifdef __WIN32__
412 case EASTEUROPE_CHARSET:
413 fontEncoding = wxFONTENCODING_CP1250;
414 break;
415
416 case BALTIC_CHARSET:
417 fontEncoding = wxFONTENCODING_CP1257;
418 break;
419
420 case RUSSIAN_CHARSET:
421 fontEncoding = wxFONTENCODING_CP1251;
422 break;
423
424 case ARABIC_CHARSET:
425 fontEncoding = wxFONTENCODING_CP1256;
426 break;
427
428 case GREEK_CHARSET:
429 fontEncoding = wxFONTENCODING_CP1253;
430 break;
431
432 case HEBREW_CHARSET:
433 fontEncoding = wxFONTENCODING_CP1255;
434 break;
435
436 case TURKISH_CHARSET:
437 fontEncoding = wxFONTENCODING_CP1254;
438 break;
439
440 case THAI_CHARSET:
441 fontEncoding = wxFONTENCODING_CP437;
442 break;
443 #endif
444
445 case OEM_CHARSET:
446 fontEncoding = wxFONTENCODING_CP437;
447 break;
448 }
449
450 return wxFont(fontPoints, fontFamily, fontStyle,
451 fontWeight, fontUnderline, fontFace,
452 fontEncoding);
453 }
454 #endif // 0
455