wxNativeEncoding::To/FromString now stores wxFontEncoding info as well (don't worry...
[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__)
127 case wxFONTENCODING_CP1250:
128 info->charset = EASTEUROPE_CHARSET;
129 break;
130
131 case wxFONTENCODING_CP1251:
132 info->charset = RUSSIAN_CHARSET;
133 break;
134
135 case wxFONTENCODING_CP1253:
136 info->charset = GREEK_CHARSET;
137 break;
138
139 case wxFONTENCODING_CP1254:
140 info->charset = TURKISH_CHARSET;
141 break;
142
143 case wxFONTENCODING_CP1255:
144 info->charset = HEBREW_CHARSET;
145 break;
146
147 case wxFONTENCODING_CP1256:
148 info->charset = ARABIC_CHARSET;
149 break;
150
151 case wxFONTENCODING_CP1257:
152 info->charset = BALTIC_CHARSET;
153 break;
154
155 case wxFONTENCODING_CP874:
156 info->charset = THAI_CHARSET;
157 break;
158 #endif // !Win16
159
160 case wxFONTENCODING_CP437:
161 info->charset = OEM_CHARSET;
162 break;
163
164 default:
165 // no way to translate this encoding into a Windows charset
166 return FALSE;
167 }
168
169 info->encoding = encoding;
170
171 return TRUE;
172 }
173
174 bool wxTestFontEncoding(const wxNativeEncodingInfo& info)
175 {
176 // try to create such font
177 LOGFONT lf;
178 wxZeroMemory(lf); // all default values
179
180 lf.lfCharSet = info.charset;
181 wxStrncpy(lf.lfFaceName, info.facename, sizeof(lf.lfFaceName));
182
183 HFONT hfont = ::CreateFontIndirect(&lf);
184 if ( !hfont )
185 {
186 // no such font
187 return FALSE;
188 }
189
190 ::DeleteObject((HGDIOBJ)hfont);
191
192 return TRUE;
193 }
194
195 // ----------------------------------------------------------------------------
196 // wxFont <-> LOGFONT conversion
197 // ----------------------------------------------------------------------------
198
199 void wxFillLogFont(LOGFONT *logFont, const wxFont *font)
200 {
201 int ff_family;
202 wxString ff_face;
203
204 switch ( font->GetFamily() )
205 {
206 case wxSCRIPT:
207 ff_family = FF_SCRIPT;
208 ff_face = _T("Script");
209 break;
210
211 case wxDECORATIVE:
212 ff_family = FF_DECORATIVE;
213 break;
214
215 case wxROMAN:
216 ff_family = FF_ROMAN;
217 ff_face = _T("Times New Roman");
218 break;
219
220 case wxTELETYPE:
221 case wxMODERN:
222 ff_family = FF_MODERN;
223 ff_face = _T("Courier New");
224 break;
225
226 case wxSWISS:
227 ff_family = FF_SWISS;
228 ff_face = _T("Arial");
229 break;
230
231 case wxDEFAULT:
232 default:
233 ff_family = FF_SWISS;
234 ff_face = _T("MS Sans Serif");
235 }
236
237 BYTE ff_italic;
238 switch ( font->GetStyle() )
239 {
240 case wxITALIC:
241 case wxSLANT:
242 ff_italic = 1;
243 break;
244
245 default:
246 wxFAIL_MSG(wxT("unknown font slant"));
247 // fall through
248
249 case wxNORMAL:
250 ff_italic = 0;
251 }
252
253 int ff_weight;
254 switch ( font->GetWeight() )
255 {
256 default:
257 wxFAIL_MSG(_T("unknown font weight"));
258 // fall through
259
260 case wxNORMAL:
261 ff_weight = FW_NORMAL;
262 break;
263
264 case wxLIGHT:
265 ff_weight = FW_LIGHT;
266 break;
267
268 case wxBOLD:
269 ff_weight = FW_BOLD;
270 break;
271 }
272
273 #if 0
274 HDC dc = ::GetDC(NULL);
275 int ppInch = ::GetDeviceCaps(dc, LOGPIXELSY);
276 ::ReleaseDC(NULL, dc);
277 #else
278 // New behaviour: apparently ppInch varies according to Large/Small Fonts
279 // setting in Windows. This messes up fonts. So, set ppInch to a constant
280 // 96 dpi.
281 static const int ppInch = 96;
282 #endif // 0/1
283
284 #if wxFONT_SIZE_COMPATIBILITY
285 // Incorrect, but compatible with old wxWindows behaviour
286 int nHeight = (font->GetPointSize()*ppInch/72);
287 #else
288 // Correct for Windows compatibility
289 int nHeight = - (font->GetPointSize()*ppInch/72);
290 #endif
291
292 wxString facename = font->GetFaceName();
293 if ( !!facename )
294 {
295 ff_face = facename;
296 }
297 //else: ff_face is a reasonable default facename for this font family
298
299 // deal with encoding now
300 wxNativeEncodingInfo info;
301 wxFontEncoding encoding = font->GetEncoding();
302 if ( !wxGetNativeFontEncoding(encoding, &info) )
303 {
304 if ( !wxTheFontMapper->GetAltForEncoding(encoding, &info) )
305 {
306 // unsupported encoding, replace with the default
307 info.charset = ANSI_CHARSET;
308 }
309 }
310
311 if ( !info.facename.IsEmpty() )
312 {
313 // the facename determined by the encoding overrides everything else
314 ff_face = info.facename;
315 }
316
317 // transfer all the data to LOGFONT
318 logFont->lfHeight = nHeight;
319 logFont->lfWidth = 0;
320 logFont->lfEscapement = 0;
321 logFont->lfOrientation = 0;
322 logFont->lfWeight = ff_weight;
323 logFont->lfItalic = ff_italic;
324 logFont->lfUnderline = (BYTE)font->GetUnderlined();
325 logFont->lfStrikeOut = 0;
326 logFont->lfCharSet = info.charset;
327 logFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
328 logFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
329 logFont->lfQuality = PROOF_QUALITY;
330 logFont->lfPitchAndFamily = DEFAULT_PITCH | ff_family;
331 wxStrncpy(logFont->lfFaceName, ff_face, WXSIZEOF(logFont->lfFaceName));
332 }
333
334 wxFont wxCreateFontFromLogFont(const LOGFONT *logFont)
335 {
336 // extract family from pitch-and-family
337 int lfFamily = logFont->lfPitchAndFamily;
338 if ( lfFamily & FIXED_PITCH )
339 lfFamily -= FIXED_PITCH;
340 if ( lfFamily & VARIABLE_PITCH )
341 lfFamily -= VARIABLE_PITCH;
342
343 int fontFamily;
344 switch ( lfFamily )
345 {
346 case FF_ROMAN:
347 fontFamily = wxROMAN;
348 break;
349
350 case FF_SWISS:
351 fontFamily = wxSWISS;
352 break;
353
354 case FF_SCRIPT:
355 fontFamily = wxSCRIPT;
356 break;
357
358 case FF_MODERN:
359 fontFamily = wxMODERN;
360 break;
361
362 case FF_DECORATIVE:
363 fontFamily = wxDECORATIVE;
364 break;
365
366 default:
367 fontFamily = wxSWISS;
368 }
369
370 // weight and style
371 int fontWeight = wxNORMAL;
372 switch ( logFont->lfWeight )
373 {
374 case FW_LIGHT:
375 fontWeight = wxLIGHT;
376 break;
377
378 default:
379 case FW_NORMAL:
380 fontWeight = wxNORMAL;
381 break;
382
383 case FW_BOLD:
384 fontWeight = wxBOLD;
385 break;
386 }
387
388 int fontStyle = logFont->lfItalic ? wxITALIC : wxNORMAL;
389
390 bool fontUnderline = logFont->lfUnderline != 0;
391
392 wxString fontFace = logFont->lfFaceName;
393
394 // font size
395 HDC dc = ::GetDC(NULL);
396
397 // remember that 1pt = 1/72inch
398 int height = abs(logFont->lfHeight);
399 int fontPoints = (72*height)/GetDeviceCaps(dc, LOGPIXELSY);
400
401 ::ReleaseDC(NULL, dc);
402
403 wxFontEncoding fontEncoding;
404 switch ( logFont->lfCharSet )
405 {
406 default:
407 wxFAIL_MSG(wxT("unsupported charset"));
408 // fall through
409
410 case ANSI_CHARSET:
411 fontEncoding = wxFONTENCODING_CP1252;
412 break;
413
414 #ifdef __WIN32__
415 case EASTEUROPE_CHARSET:
416 fontEncoding = wxFONTENCODING_CP1250;
417 break;
418
419 case BALTIC_CHARSET:
420 fontEncoding = wxFONTENCODING_CP1257;
421 break;
422
423 case RUSSIAN_CHARSET:
424 fontEncoding = wxFONTENCODING_CP1251;
425 break;
426
427 case ARABIC_CHARSET:
428 fontEncoding = wxFONTENCODING_CP1256;
429 break;
430
431 case GREEK_CHARSET:
432 fontEncoding = wxFONTENCODING_CP1253;
433 break;
434
435 case HEBREW_CHARSET:
436 fontEncoding = wxFONTENCODING_CP1255;
437 break;
438
439 case TURKISH_CHARSET:
440 fontEncoding = wxFONTENCODING_CP1254;
441 break;
442
443 case THAI_CHARSET:
444 fontEncoding = wxFONTENCODING_CP437;
445 break;
446 #endif
447
448 case OEM_CHARSET:
449 fontEncoding = wxFONTENCODING_CP437;
450 break;
451 }
452
453 return wxFont(fontPoints, fontFamily, fontStyle,
454 fontWeight, fontUnderline, fontFace,
455 fontEncoding);
456 }
457
458