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 // wxFont <-> LOGFONT conversion
203 // ----------------------------------------------------------------------------
205 void wxFillLogFont(LOGFONT
*logFont
, const wxFont
*font
)
210 switch ( font
->GetFamily() )
213 ff_family
= FF_SCRIPT
;
214 ff_face
= _T("Script");
218 ff_family
= FF_DECORATIVE
;
222 ff_family
= FF_ROMAN
;
223 ff_face
= _T("Times New Roman");
228 ff_family
= FF_MODERN
;
229 ff_face
= _T("Courier New");
233 ff_family
= FF_SWISS
;
234 ff_face
= _T("Arial");
239 ff_family
= FF_SWISS
;
240 ff_face
= _T("MS Sans Serif");
244 switch ( font
->GetStyle() )
252 wxFAIL_MSG(wxT("unknown font slant"));
260 switch ( font
->GetWeight() )
263 wxFAIL_MSG(_T("unknown font weight"));
267 ff_weight
= FW_NORMAL
;
271 ff_weight
= FW_LIGHT
;
280 HDC dc
= ::GetDC(NULL
);
281 static const int ppInch
= ::GetDeviceCaps(dc
, LOGPIXELSY
);
282 ::ReleaseDC(NULL
, dc
);
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
287 static const int ppInch
= 96;
290 #if wxFONT_SIZE_COMPATIBILITY
291 // Incorrect, but compatible with old wxWindows behaviour
292 int nHeight
= (font
->GetPointSize()*ppInch
/72);
294 // Correct for Windows compatibility
295 // int nHeight = - (font->GetPointSize()*ppInch/72);
296 int nHeight
= - (int) ( (font
->GetPointSize()*((double)ppInch
)/72.0) + 0.5);
299 wxString facename
= font
->GetFaceName();
304 //else: ff_face is a reasonable default facename for this font family
306 // deal with encoding now
307 wxNativeEncodingInfo info
;
308 wxFontEncoding encoding
= font
->GetEncoding();
309 if ( !wxGetNativeFontEncoding(encoding
, &info
) )
311 if ( !wxTheFontMapper
->GetAltForEncoding(encoding
, &info
) )
313 // unsupported encoding, replace with the default
314 info
.charset
= ANSI_CHARSET
;
318 if ( !info
.facename
.IsEmpty() )
320 // the facename determined by the encoding overrides everything else
321 ff_face
= info
.facename
;
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
));
341 wxFont
wxCreateFontFromLogFont(const LOGFONT
*logFont
)
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
;
354 fontFamily
= wxROMAN
;
358 fontFamily
= wxSWISS
;
362 fontFamily
= wxSCRIPT
;
366 fontFamily
= wxMODERN
;
370 fontFamily
= wxDECORATIVE
;
374 fontFamily
= wxSWISS
;
378 int fontWeight
= wxNORMAL
;
379 switch ( logFont
->lfWeight
)
382 fontWeight
= wxLIGHT
;
387 fontWeight
= wxNORMAL
;
395 int fontStyle
= logFont
->lfItalic
? wxITALIC
: wxNORMAL
;
397 bool fontUnderline
= logFont
->lfUnderline
!= 0;
399 wxString fontFace
= logFont
->lfFaceName
;
401 // remember that 1pt = 1/72inch
402 int height
= abs(logFont
->lfHeight
);
405 HDC dc
= ::GetDC(NULL
);
406 static const int ppInch
= GetDeviceCaps(dc
, LOGPIXELSY
);
407 ::ReleaseDC(NULL
, dc
);
409 static const int ppInch
= 96;
411 int fontPoints
= (int) (((72.0*((double)height
))/(double) ppInch
) + 0.5);
413 wxFontEncoding fontEncoding
;
414 switch ( logFont
->lfCharSet
)
417 wxFAIL_MSG(wxT("unsupported charset"));
421 fontEncoding
= wxFONTENCODING_CP1252
;
425 case EASTEUROPE_CHARSET
:
426 fontEncoding
= wxFONTENCODING_CP1250
;
430 fontEncoding
= wxFONTENCODING_CP1257
;
433 case RUSSIAN_CHARSET
:
434 fontEncoding
= wxFONTENCODING_CP1251
;
438 fontEncoding
= wxFONTENCODING_CP1256
;
442 fontEncoding
= wxFONTENCODING_CP1253
;
446 fontEncoding
= wxFONTENCODING_CP1255
;
449 case TURKISH_CHARSET
:
450 fontEncoding
= wxFONTENCODING_CP1254
;
454 fontEncoding
= wxFONTENCODING_CP437
;
459 fontEncoding
= wxFONTENCODING_CP437
;
463 return wxFont(fontPoints
, fontFamily
, fontStyle
,
464 fontWeight
, fontUnderline
, fontFace
,