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