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