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