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