Corrected font calculation (use screen resolution now); and check for mask in m_image.cpp
[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 // wxFont <-> LOGFONT conversion
203 // ----------------------------------------------------------------------------
204
205 void wxFillLogFont(LOGFONT *logFont, const wxFont *font)
206 {
207 int ff_family;
208 wxString ff_face;
209
210 switch ( font->GetFamily() )
211 {
212 case wxSCRIPT:
213 ff_family = FF_SCRIPT;
214 ff_face = _T("Script");
215 break;
216
217 case wxDECORATIVE:
218 ff_family = FF_DECORATIVE;
219 break;
220
221 case wxROMAN:
222 ff_family = FF_ROMAN;
223 ff_face = _T("Times New Roman");
224 break;
225
226 case wxTELETYPE:
227 case wxMODERN:
228 ff_family = FF_MODERN;
229 ff_face = _T("Courier New");
230 break;
231
232 case wxSWISS:
233 ff_family = FF_SWISS;
234 ff_face = _T("Arial");
235 break;
236
237 case wxDEFAULT:
238 default:
239 ff_family = FF_SWISS;
240 ff_face = _T("MS Sans Serif");
241 }
242
243 BYTE ff_italic;
244 switch ( font->GetStyle() )
245 {
246 case wxITALIC:
247 case wxSLANT:
248 ff_italic = 1;
249 break;
250
251 default:
252 wxFAIL_MSG(wxT("unknown font slant"));
253 // fall through
254
255 case wxNORMAL:
256 ff_italic = 0;
257 }
258
259 int ff_weight;
260 switch ( font->GetWeight() )
261 {
262 default:
263 wxFAIL_MSG(_T("unknown font weight"));
264 // fall through
265
266 case wxNORMAL:
267 ff_weight = FW_NORMAL;
268 break;
269
270 case wxLIGHT:
271 ff_weight = FW_LIGHT;
272 break;
273
274 case wxBOLD:
275 ff_weight = FW_BOLD;
276 break;
277 }
278
279 #if wxUSE_SCREEN_DPI
280 HDC dc = ::GetDC(NULL);
281 static const int ppInch = ::GetDeviceCaps(dc, LOGPIXELSY);
282 ::ReleaseDC(NULL, dc);
283 #else
284 // New behaviour: apparently ppInch varies according to Large/Small Fonts
285 // setting in Windows. This messes up fonts. So, set ppInch to a constant
286 // 96 dpi.
287 static const int ppInch = 96;
288 #endif // 0/1
289
290 #if wxFONT_SIZE_COMPATIBILITY
291 // Incorrect, but compatible with old wxWindows behaviour
292 int nHeight = (font->GetPointSize()*ppInch/72);
293 #else
294 // Correct for Windows compatibility
295 // int nHeight = - (font->GetPointSize()*ppInch/72);
296 int nHeight = - (int) ( (font->GetPointSize()*((double)ppInch)/72.0) + 0.5);
297 #endif
298
299 wxString facename = font->GetFaceName();
300 if ( !!facename )
301 {
302 ff_face = facename;
303 }
304 //else: ff_face is a reasonable default facename for this font family
305
306 // deal with encoding now
307 wxNativeEncodingInfo info;
308 wxFontEncoding encoding = font->GetEncoding();
309 if ( !wxGetNativeFontEncoding(encoding, &info) )
310 {
311 if ( !wxTheFontMapper->GetAltForEncoding(encoding, &info) )
312 {
313 // unsupported encoding, replace with the default
314 info.charset = ANSI_CHARSET;
315 }
316 }
317
318 if ( !info.facename.IsEmpty() )
319 {
320 // the facename determined by the encoding overrides everything else
321 ff_face = info.facename;
322 }
323
324 // transfer all the data to LOGFONT
325 logFont->lfHeight = nHeight;
326 logFont->lfWidth = 0;
327 logFont->lfEscapement = 0;
328 logFont->lfOrientation = 0;
329 logFont->lfWeight = ff_weight;
330 logFont->lfItalic = ff_italic;
331 logFont->lfUnderline = (BYTE)font->GetUnderlined();
332 logFont->lfStrikeOut = 0;
333 logFont->lfCharSet = info.charset;
334 logFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
335 logFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
336 logFont->lfQuality = PROOF_QUALITY;
337 logFont->lfPitchAndFamily = DEFAULT_PITCH | ff_family;
338 wxStrncpy(logFont->lfFaceName, ff_face, WXSIZEOF(logFont->lfFaceName));
339 }
340
341 wxFont wxCreateFontFromLogFont(const LOGFONT *logFont)
342 {
343 // extract family from pitch-and-family
344 int lfFamily = logFont->lfPitchAndFamily;
345 if ( lfFamily & FIXED_PITCH )
346 lfFamily -= FIXED_PITCH;
347 if ( lfFamily & VARIABLE_PITCH )
348 lfFamily -= VARIABLE_PITCH;
349
350 int fontFamily;
351 switch ( lfFamily )
352 {
353 case FF_ROMAN:
354 fontFamily = wxROMAN;
355 break;
356
357 case FF_SWISS:
358 fontFamily = wxSWISS;
359 break;
360
361 case FF_SCRIPT:
362 fontFamily = wxSCRIPT;
363 break;
364
365 case FF_MODERN:
366 fontFamily = wxMODERN;
367 break;
368
369 case FF_DECORATIVE:
370 fontFamily = wxDECORATIVE;
371 break;
372
373 default:
374 fontFamily = wxSWISS;
375 }
376
377 // weight and style
378 int fontWeight = wxNORMAL;
379 switch ( logFont->lfWeight )
380 {
381 case FW_LIGHT:
382 fontWeight = wxLIGHT;
383 break;
384
385 default:
386 case FW_NORMAL:
387 fontWeight = wxNORMAL;
388 break;
389
390 case FW_BOLD:
391 fontWeight = wxBOLD;
392 break;
393 }
394
395 int fontStyle = logFont->lfItalic ? wxITALIC : wxNORMAL;
396
397 bool fontUnderline = logFont->lfUnderline != 0;
398
399 wxString fontFace = logFont->lfFaceName;
400
401 // remember that 1pt = 1/72inch
402 int height = abs(logFont->lfHeight);
403
404 #if wxUSE_SCREEN_DPI
405 HDC dc = ::GetDC(NULL);
406 static const int ppInch = GetDeviceCaps(dc, LOGPIXELSY);
407 ::ReleaseDC(NULL, dc);
408 #else
409 static const int ppInch = 96;
410 #endif
411 int fontPoints = (int) (((72.0*((double)height))/(double) ppInch) + 0.5);
412
413 wxFontEncoding fontEncoding;
414 switch ( logFont->lfCharSet )
415 {
416 default:
417 wxFAIL_MSG(wxT("unsupported charset"));
418 // fall through
419
420 case ANSI_CHARSET:
421 fontEncoding = wxFONTENCODING_CP1252;
422 break;
423
424 #ifdef __WIN32__
425 case EASTEUROPE_CHARSET:
426 fontEncoding = wxFONTENCODING_CP1250;
427 break;
428
429 case BALTIC_CHARSET:
430 fontEncoding = wxFONTENCODING_CP1257;
431 break;
432
433 case RUSSIAN_CHARSET:
434 fontEncoding = wxFONTENCODING_CP1251;
435 break;
436
437 case ARABIC_CHARSET:
438 fontEncoding = wxFONTENCODING_CP1256;
439 break;
440
441 case GREEK_CHARSET:
442 fontEncoding = wxFONTENCODING_CP1253;
443 break;
444
445 case HEBREW_CHARSET:
446 fontEncoding = wxFONTENCODING_CP1255;
447 break;
448
449 case TURKISH_CHARSET:
450 fontEncoding = wxFONTENCODING_CP1254;
451 break;
452
453 case THAI_CHARSET:
454 fontEncoding = wxFONTENCODING_CP437;
455 break;
456 #endif
457
458 case OEM_CHARSET:
459 fontEncoding = wxFONTENCODING_CP437;
460 break;
461 }
462
463 return wxFont(fontPoints, fontFamily, fontStyle,
464 fontWeight, fontUnderline, fontFace,
465 fontEncoding);
466 }
467
468