]> git.saurik.com Git - wxWidgets.git/blame - src/msw/fontutil.cpp
another segfault fix
[wxWidgets.git] / src / msw / fontutil.cpp
CommitLineData
11c7d5b6
VZ
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
e757496e
MB
44// for MSVC5 and old w32api
45#ifndef HANGUL_CHARSET
46# define HANGUL_CHARSET 129
47#endif
48
11c7d5b6
VZ
49// ============================================================================
50// implementation
51// ============================================================================
52
53// ----------------------------------------------------------------------------
54// wxNativeEncodingInfo
55// ----------------------------------------------------------------------------
56
57// convert to/from the string representation: format is
1e1d0be1 58// encodingid;facename[;charset]
11c7d5b6
VZ
59
60bool wxNativeEncodingInfo::FromString(const wxString& s)
61{
62 wxStringTokenizer tokenizer(s, _T(";"));
63
1e1d0be1
VS
64 wxString encid = tokenizer.GetNextToken();
65 long enc;
66 if ( !encid.ToLong(&enc) )
67 return FALSE;
68 encoding = (wxFontEncoding)enc;
69
11c7d5b6 70 facename = tokenizer.GetNextToken();
11c7d5b6
VZ
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
91wxString wxNativeEncodingInfo::ToString() const
92{
1e1d0be1 93 wxString s;
f6bcfd97 94
1e1d0be1 95 s << (long)encoding << _T(';') << facename;
11c7d5b6
VZ
96 if ( charset != ANSI_CHARSET )
97 {
1e1d0be1 98 s << _T(';') << charset;
11c7d5b6
VZ
99 }
100
101 return s;
102}
103
104// ----------------------------------------------------------------------------
105// helper functions
106// ----------------------------------------------------------------------------
107
108bool 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
04ef50df 129#if !defined(__WIN16__) && !defined(__WXMICROWIN__)
bc4e6fcd
VZ
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
11c7d5b6
VZ
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;
f3314fbc
JS
176
177 case wxFONTENCODING_CP874:
178 info->charset = THAI_CHARSET;
179 break;
bc4e6fcd
VZ
180
181
11c7d5b6
VZ
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
6b0eebc5 193 info->encoding = encoding;
f6bcfd97 194
11c7d5b6
VZ
195 return TRUE;
196}
197
198bool 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;
0e89bb17 205 wxStrncpy(lf.lfFaceName, info.facename, sizeof(lf.lfFaceName));
11c7d5b6
VZ
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
f6bcfd97
BP
219// ----------------------------------------------------------------------------
220// wxFontEncoding <-> CHARSET_XXX
221// ----------------------------------------------------------------------------
222
223wxFontEncoding 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
04ef50df 240#if defined(__WIN32__) && !defined(__WXMICROWIN__)
f6bcfd97
BP
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;
bc4e6fcd
VZ
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
f6bcfd97
BP
289#endif // Win32
290
291 case OEM_CHARSET:
292 fontEncoding = wxFONTENCODING_CP437;
293 break;
294 }
295
296 return fontEncoding;
297}
298
11c7d5b6
VZ
299// ----------------------------------------------------------------------------
300// wxFont <-> LOGFONT conversion
301// ----------------------------------------------------------------------------
302
303void 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
55bd3f34
VZ
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
11c7d5b6
VZ
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;
55bd3f34 390#endif // 1/0
11c7d5b6 391
55bd3f34 392 int pointSize = font->GetPointSize();
11c7d5b6
VZ
393#if wxFONT_SIZE_COMPATIBILITY
394 // Incorrect, but compatible with old wxWindows behaviour
55bd3f34 395 int nHeight = (pointSize*ppInch)/72;
11c7d5b6
VZ
396#else
397 // Correct for Windows compatibility
55bd3f34 398 int nHeight = -(int)((pointSize*((double)ppInch)/72.0) + 0.5);
11c7d5b6
VZ
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 {
1e6feb95 413#if wxUSE_FONTMAP
11c7d5b6 414 if ( !wxTheFontMapper->GetAltForEncoding(encoding, &info) )
1e6feb95 415#endif // wxUSE_FONTMAP
11c7d5b6
VZ
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
445wxFont wxCreateFontFromLogFont(const LOGFONT *logFont)
446{
09fcd889 447 wxNativeFontInfo info;
11c7d5b6 448
09fcd889 449 info.lf = *logFont;
11c7d5b6 450
09fcd889 451 return wxFont(info);
11c7d5b6
VZ
452}
453