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