1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: msw/fontutil.cpp
3 // Purpose: font-related helper functions for wxMSW
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
21 #pragma implementation "fontutil.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
32 #include "wx/string.h"
37 #include "wx/msw/private.h"
39 #include "wx/fontutil.h"
40 #include "wx/fontmap.h"
42 #include "wx/tokenzr.h"
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
50 // ============================================================================
52 // ============================================================================
54 // ----------------------------------------------------------------------------
55 // wxNativeEncodingInfo
56 // ----------------------------------------------------------------------------
58 // convert to/from the string representation: format is
59 // encodingid;facename[;charset]
61 bool wxNativeEncodingInfo::FromString(const wxString
& s
)
63 wxStringTokenizer
tokenizer(s
, _T(";"));
65 wxString encid
= tokenizer
.GetNextToken();
67 if ( !encid
.ToLong(&enc
) )
69 encoding
= (wxFontEncoding
)enc
;
71 facename
= tokenizer
.GetNextToken();
75 wxString tmp
= tokenizer
.GetNextToken();
78 // default charset (don't use DEFAULT_CHARSET though because of subtle
79 // Windows 9x/NT differences in handling it)
80 charset
= ANSI_CHARSET
;
84 if ( wxSscanf(tmp
, _T("%u"), &charset
) != 1 )
86 // should be a number!
94 wxString
wxNativeEncodingInfo::ToString() const
98 s
<< (long)encoding
<< _T(';') << facename
;
99 if ( charset
!= ANSI_CHARSET
)
101 s
<< _T(';') << charset
;
107 // ----------------------------------------------------------------------------
109 // ----------------------------------------------------------------------------
111 bool wxGetNativeFontEncoding(wxFontEncoding encoding
,
112 wxNativeEncodingInfo
*info
)
114 wxCHECK_MSG( info
, FALSE
, _T("bad pointer in wxGetNativeFontEncoding") );
116 if ( encoding
== wxFONTENCODING_DEFAULT
)
118 encoding
= wxFont::GetDefaultEncoding();
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
;
132 #if !defined(__WIN16__)
133 case wxFONTENCODING_CP1250
:
134 info
->charset
= EASTEUROPE_CHARSET
;
137 case wxFONTENCODING_CP1251
:
138 info
->charset
= RUSSIAN_CHARSET
;
141 case wxFONTENCODING_CP1253
:
142 info
->charset
= GREEK_CHARSET
;
145 case wxFONTENCODING_CP1254
:
146 info
->charset
= TURKISH_CHARSET
;
149 case wxFONTENCODING_CP1255
:
150 info
->charset
= HEBREW_CHARSET
;
153 case wxFONTENCODING_CP1256
:
154 info
->charset
= ARABIC_CHARSET
;
157 case wxFONTENCODING_CP1257
:
158 info
->charset
= BALTIC_CHARSET
;
161 case wxFONTENCODING_CP874
:
162 info
->charset
= THAI_CHARSET
;
166 case wxFONTENCODING_CP437
:
167 info
->charset
= OEM_CHARSET
;
171 // no way to translate this encoding into a Windows charset
175 info
->encoding
= encoding
;
180 bool wxTestFontEncoding(const wxNativeEncodingInfo
& info
)
182 // try to create such font
184 wxZeroMemory(lf
); // all default values
186 lf
.lfCharSet
= info
.charset
;
187 wxStrncpy(lf
.lfFaceName
, info
.facename
, sizeof(lf
.lfFaceName
));
189 HFONT hfont
= ::CreateFontIndirect(&lf
);
196 ::DeleteObject((HGDIOBJ
)hfont
);
201 // ----------------------------------------------------------------------------
202 // wxFontEncoding <-> CHARSET_XXX
203 // ----------------------------------------------------------------------------
205 wxFontEncoding
wxGetFontEncFromCharSet(int cs
)
207 wxFontEncoding fontEncoding
;
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"));
219 fontEncoding
= wxFONTENCODING_CP1252
;
223 case EASTEUROPE_CHARSET
:
224 fontEncoding
= wxFONTENCODING_CP1250
;
228 fontEncoding
= wxFONTENCODING_CP1257
;
231 case RUSSIAN_CHARSET
:
232 fontEncoding
= wxFONTENCODING_CP1251
;
236 fontEncoding
= wxFONTENCODING_CP1256
;
240 fontEncoding
= wxFONTENCODING_CP1253
;
244 fontEncoding
= wxFONTENCODING_CP1255
;
247 case TURKISH_CHARSET
:
248 fontEncoding
= wxFONTENCODING_CP1254
;
252 fontEncoding
= wxFONTENCODING_CP437
;
257 fontEncoding
= wxFONTENCODING_CP437
;
264 // ----------------------------------------------------------------------------
265 // wxFont <-> LOGFONT conversion
266 // ----------------------------------------------------------------------------
268 void wxFillLogFont(LOGFONT
*logFont
, const wxFont
*font
)
273 switch ( font
->GetFamily() )
276 ff_family
= FF_SCRIPT
;
277 ff_face
= _T("Script");
281 ff_family
= FF_DECORATIVE
;
285 ff_family
= FF_ROMAN
;
286 ff_face
= _T("Times New Roman");
291 ff_family
= FF_MODERN
;
292 ff_face
= _T("Courier New");
296 ff_family
= FF_SWISS
;
297 ff_face
= _T("Arial");
302 ff_family
= FF_SWISS
;
303 ff_face
= _T("MS Sans Serif");
307 switch ( font
->GetStyle() )
315 wxFAIL_MSG(wxT("unknown font slant"));
323 switch ( font
->GetWeight() )
326 wxFAIL_MSG(_T("unknown font weight"));
330 ff_weight
= FW_NORMAL
;
334 ff_weight
= FW_LIGHT
;
343 HDC dc
= ::GetDC(NULL
);
344 static const int ppInch
= ::GetDeviceCaps(dc
, LOGPIXELSY
);
345 ::ReleaseDC(NULL
, dc
);
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
350 static const int ppInch
= 96;
353 #if wxFONT_SIZE_COMPATIBILITY
354 // Incorrect, but compatible with old wxWindows behaviour
355 int nHeight
= (font
->GetPointSize()*ppInch
/72);
357 // Correct for Windows compatibility
358 // int nHeight = - (font->GetPointSize()*ppInch/72);
359 int nHeight
= - (int) ( (font
->GetPointSize()*((double)ppInch
)/72.0) + 0.5);
362 wxString facename
= font
->GetFaceName();
367 //else: ff_face is a reasonable default facename for this font family
369 // deal with encoding now
370 wxNativeEncodingInfo info
;
371 wxFontEncoding encoding
= font
->GetEncoding();
372 if ( !wxGetNativeFontEncoding(encoding
, &info
) )
374 if ( !wxTheFontMapper
->GetAltForEncoding(encoding
, &info
) )
376 // unsupported encoding, replace with the default
377 info
.charset
= ANSI_CHARSET
;
381 if ( !info
.facename
.IsEmpty() )
383 // the facename determined by the encoding overrides everything else
384 ff_face
= info
.facename
;
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
));
404 wxFont
wxCreateFontFromLogFont(const LOGFONT
*logFont
)
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
;
417 fontFamily
= wxROMAN
;
421 fontFamily
= wxSWISS
;
425 fontFamily
= wxSCRIPT
;
429 fontFamily
= wxMODERN
;
433 fontFamily
= wxDECORATIVE
;
437 fontFamily
= wxSWISS
;
441 int fontWeight
= wxNORMAL
;
442 switch ( logFont
->lfWeight
)
445 fontWeight
= wxLIGHT
;
450 fontWeight
= wxNORMAL
;
458 int fontStyle
= logFont
->lfItalic
? wxITALIC
: wxNORMAL
;
460 bool fontUnderline
= logFont
->lfUnderline
!= 0;
462 wxString fontFace
= logFont
->lfFaceName
;
464 // remember that 1pt = 1/72inch
465 int height
= abs(logFont
->lfHeight
);
468 HDC dc
= ::GetDC(NULL
);
469 static const int ppInch
= GetDeviceCaps(dc
, LOGPIXELSY
);
470 ::ReleaseDC(NULL
, dc
);
472 static const int ppInch
= 96;
474 int fontPoints
= (int) (((72.0*((double)height
))/(double) ppInch
) + 0.5);
476 return wxFont(fontPoints
, fontFamily
, fontStyle
,
477 fontWeight
, fontUnderline
, fontFace
,
478 wxGetFontEncFromCharSet(logFont
->lfCharSet
));