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