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