]> git.saurik.com Git - wxWidgets.git/blame - src/common/fontcmn.cpp
Applied #15375 to stop event-sending in generic wxSpinCtrl ctor (eco)
[wxWidgets.git] / src / common / fontcmn.cpp
CommitLineData
8f7fa6f8 1/////////////////////////////////////////////////////////////////////////////
da80ae71 2// Name: src/common/fontcmn.cpp
0c5d3e1c
VZ
3// Purpose: implementation of wxFontBase methods
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 20.09.99
77ffb593 7// Copyright: (c) wxWidgets team
65571936 8// Licence: wxWindows licence
0c5d3e1c
VZ
9/////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
19// For compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
da80ae71 23 #pragma hdrstop
0c5d3e1c
VZ
24#endif
25
da80ae71
WS
26#include "wx/font.h"
27
0c5d3e1c 28#ifndef WX_PRECOMP
452aa069 29 #include "wx/dc.h"
9342fdbe 30 #include "wx/intl.h"
f76c3ff6 31 #include "wx/math.h"
9342fdbe 32 #include "wx/dcscreen.h"
8d3ba63b 33 #include "wx/log.h"
dd05139a 34 #include "wx/gdicmn.h"
0c5d3e1c
VZ
35#endif // WX_PRECOMP
36
82ef81ed 37#if defined(__WXMSW__)
7bd236e6
WS
38 #include "wx/msw/private.h" // includes windows.h for LOGFONT
39 #include "wx/msw/winundef.h"
1c193821
JS
40#endif
41
76e23cdb 42#include "wx/fontutil.h" // for wxNativeFontInfo
ab5fe833 43#include "wx/fontmap.h"
85ab460e 44#include "wx/fontenum.h"
76e23cdb 45
30764ab5
VZ
46#include "wx/tokenzr.h"
47
4b6a582b
VZ
48// debugger helper: this function can be called from a debugger to show what
49// the date really is
50extern const char *wxDumpFont(const wxFont *font)
51{
52 static char buf[256];
53
54 const wxFontWeight weight = font->GetWeight();
55
56 wxString s;
57 s.Printf(wxS("%s-%s-%s-%d-%d"),
58 font->GetFaceName(),
59 weight == wxFONTWEIGHT_NORMAL
9a83f860 60 ? wxT("normal")
4b6a582b 61 : weight == wxFONTWEIGHT_BOLD
9a83f860
VZ
62 ? wxT("bold")
63 : wxT("light"),
4b6a582b 64 font->GetStyle() == wxFONTSTYLE_NORMAL
9a83f860
VZ
65 ? wxT("regular")
66 : wxT("italic"),
4b6a582b
VZ
67 font->GetPointSize(),
68 font->GetEncoding());
69
61f24aea 70 wxStrlcpy(buf, s.mb_str(), WXSIZEOF(buf));
4b6a582b
VZ
71 return buf;
72}
73
28953245
SC
74// ----------------------------------------------------------------------------
75// XTI
76// ----------------------------------------------------------------------------
77
78wxBEGIN_ENUM( wxFontFamily )
e765d7ee
SC
79wxENUM_MEMBER( wxFONTFAMILY_DEFAULT )
80wxENUM_MEMBER( wxFONTFAMILY_DECORATIVE )
81wxENUM_MEMBER( wxFONTFAMILY_ROMAN )
82wxENUM_MEMBER( wxFONTFAMILY_SCRIPT )
83wxENUM_MEMBER( wxFONTFAMILY_SWISS )
84wxENUM_MEMBER( wxFONTFAMILY_MODERN )
85wxENUM_MEMBER( wxFONTFAMILY_TELETYPE )
28953245
SC
86wxEND_ENUM( wxFontFamily )
87
88wxBEGIN_ENUM( wxFontStyle )
e765d7ee
SC
89wxENUM_MEMBER( wxFONTSTYLE_NORMAL )
90wxENUM_MEMBER( wxFONTSTYLE_ITALIC )
91wxENUM_MEMBER( wxFONTSTYLE_SLANT )
28953245
SC
92wxEND_ENUM( wxFontStyle )
93
94wxBEGIN_ENUM( wxFontWeight )
e765d7ee
SC
95wxENUM_MEMBER( wxFONTWEIGHT_NORMAL )
96wxENUM_MEMBER( wxFONTWEIGHT_LIGHT )
97wxENUM_MEMBER( wxFONTWEIGHT_BOLD )
28953245
SC
98wxEND_ENUM( wxFontWeight )
99
100wxIMPLEMENT_DYNAMIC_CLASS_WITH_COPY_XTI(wxFont, wxGDIObject, "wx/font.h")
101
e765d7ee
SC
102//WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxFont>)
103
28953245
SC
104wxBEGIN_PROPERTIES_TABLE(wxFont)
105wxPROPERTY( Size,int, SetPointSize, GetPointSize, 12, 0 /*flags*/, \
106 wxT("Helpstring"), wxT("group"))
e765d7ee 107wxPROPERTY( Family, wxFontFamily , SetFamily, GetFamily, (wxFontFamily)wxDEFAULT, \
28953245 108 0 /*flags*/, wxT("Helpstring"), wxT("group")) // wxFontFamily
e765d7ee 109wxPROPERTY( Style, wxFontStyle, SetStyle, GetStyle, (wxFontStyle)wxNORMAL, 0 /*flags*/, \
28953245 110 wxT("Helpstring"), wxT("group")) // wxFontStyle
e765d7ee 111wxPROPERTY( Weight, wxFontWeight, SetWeight, GetWeight, (wxFontWeight)wxNORMAL, 0 /*flags*/, \
28953245
SC
112 wxT("Helpstring"), wxT("group")) // wxFontWeight
113wxPROPERTY( Underlined, bool, SetUnderlined, GetUnderlined, false, 0 /*flags*/, \
114 wxT("Helpstring"), wxT("group"))
c7a49742
VZ
115wxPROPERTY( Strikethrough, bool, SetStrikethrough, GetStrikethrough, false, 0, \
116 wxT("Helpstring"), wxT("group"))
28953245
SC
117wxPROPERTY( Face, wxString, SetFaceName, GetFaceName, wxEMPTY_PARAMETER_VALUE, \
118 0 /*flags*/, wxT("Helpstring"), wxT("group"))
119wxPROPERTY( Encoding, wxFontEncoding, SetEncoding, GetEncoding, \
120 wxFONTENCODING_DEFAULT, 0 /*flags*/, wxT("Helpstring"), wxT("group"))
121wxEND_PROPERTIES_TABLE()
122
e765d7ee 123wxCONSTRUCTOR_6( wxFont, int, Size, wxFontFamily, Family, wxFontStyle, Style, wxFontWeight, Weight, \
28953245
SC
124 bool, Underlined, wxString, Face )
125
126wxEMPTY_HANDLERS_TABLE(wxFont)
127
0c5d3e1c
VZ
128// ============================================================================
129// implementation
130// ============================================================================
131
132// ----------------------------------------------------------------------------
133// wxFontBase
134// ----------------------------------------------------------------------------
135
136wxFontEncoding wxFontBase::ms_encodingDefault = wxFONTENCODING_SYSTEM;
137
cafbf6fb
VZ
138/* static */
139void wxFontBase::SetDefaultEncoding(wxFontEncoding encoding)
140{
141 // GetDefaultEncoding() should return something != wxFONTENCODING_DEFAULT
142 // and, besides, using this value here doesn't make any sense
143 wxCHECK_RET( encoding != wxFONTENCODING_DEFAULT,
9a83f860 144 wxT("can't set default encoding to wxFONTENCODING_DEFAULT") );
cafbf6fb
VZ
145
146 ms_encodingDefault = encoding;
147}
148
799ea011
GD
149wxFontBase::~wxFontBase()
150{
151 // this destructor is required for Darwin
152}
153
7beba2fc 154/* static */
0c5d3e1c 155wxFont *wxFontBase::New(int size,
0c14b6c3
FM
156 wxFontFamily family,
157 wxFontStyle style,
158 wxFontWeight weight,
0c5d3e1c
VZ
159 bool underlined,
160 const wxString& face,
161 wxFontEncoding encoding)
162{
163 return new wxFont(size, family, style, weight, underlined, face, encoding);
164}
165
b5791cc7
FM
166/* static */
167wxFont *wxFontBase::New(const wxSize& pixelSize,
168 wxFontFamily family,
169 wxFontStyle style,
170 wxFontWeight weight,
171 bool underlined,
172 const wxString& face,
173 wxFontEncoding encoding)
544229d1 174{
b5791cc7
FM
175 return new wxFont(pixelSize, family, style, weight, underlined,
176 face, encoding);
544229d1
VZ
177}
178
179/* static */
180wxFont *wxFontBase::New(int pointSize,
181 wxFontFamily family,
182 int flags,
183 const wxString& face,
184 wxFontEncoding encoding)
185{
0634700a
VZ
186 return New(pointSize, family,
187 GetStyleFromFlags(flags),
188 GetWeightFromFlags(flags),
189 GetUnderlinedFromFlags(flags),
190 face, encoding);
544229d1
VZ
191}
192
193/* static */
194wxFont *wxFontBase::New(const wxSize& pixelSize,
0c14b6c3 195 wxFontFamily family,
b5791cc7 196 int flags,
544229d1
VZ
197 const wxString& face,
198 wxFontEncoding encoding)
199{
0634700a
VZ
200 return New(pixelSize, family,
201 GetStyleFromFlags(flags),
202 GetWeightFromFlags(flags),
203 GetUnderlinedFromFlags(flags),
204 face, encoding);
544229d1
VZ
205}
206
207/* static */
b5791cc7 208wxFont *wxFontBase::New(const wxNativeFontInfo& info)
544229d1 209{
b5791cc7
FM
210 return new wxFont(info);
211}
212
213/* static */
214wxFont *wxFontBase::New(const wxString& strNativeFontDesc)
215{
216 wxNativeFontInfo fontInfo;
217 if ( !fontInfo.FromString(strNativeFontDesc) )
218 return new wxFont(*wxNORMAL_FONT);
219
220 return New(fontInfo);
221}
222
223bool wxFontBase::IsFixedWidth() const
224{
225 return GetFamily() == wxFONTFAMILY_TELETYPE;
544229d1
VZ
226}
227
228wxSize wxFontBase::GetPixelSize() const
229{
230 wxScreenDC dc;
231 dc.SetFont(*(wxFont *)this);
232 return wxSize(dc.GetCharWidth(), dc.GetCharHeight());
233}
234
235bool wxFontBase::IsUsingSizeInPixels() const
236{
237 return false;
238}
239
240void wxFontBase::SetPixelSize( const wxSize& pixelSize )
241{
b5791cc7
FM
242 wxCHECK_RET( pixelSize.GetWidth() >= 0 && pixelSize.GetHeight() > 0,
243 "Negative values for the pixel size or zero pixel height are not allowed" );
244
544229d1 245 wxScreenDC dc;
01cb1c26 246
b5791cc7
FM
247 // NOTE: this algorithm for adjusting the font size is used by all
248 // implementations of wxFont except under wxMSW and wxGTK where
249 // native support to font creation using pixel-size is provided.
03647350 250
b5791cc7
FM
251 int largestGood = 0;
252 int smallestBad = 0;
30764ab5 253
b5791cc7
FM
254 bool initialGoodFound = false;
255 bool initialBadFound = false;
7826e2dd 256
b5791cc7
FM
257 // NB: this assignment was separated from the variable definition
258 // in order to fix a gcc v3.3.3 compiler crash
259 int currentSize = GetPointSize();
260 while (currentSize > 0)
261 {
262 dc.SetFont(*static_cast<wxFont*>(this));
7826e2dd 263
b5791cc7
FM
264 // if currentSize (in points) results in a font that is smaller
265 // than required by pixelSize it is considered a good size
266 // NOTE: the pixel size width may be zero
267 if (dc.GetCharHeight() <= pixelSize.GetHeight() &&
268 (pixelSize.GetWidth() == 0 ||
269 dc.GetCharWidth() <= pixelSize.GetWidth()))
270 {
271 largestGood = currentSize;
272 initialGoodFound = true;
273 }
274 else
275 {
276 smallestBad = currentSize;
277 initialBadFound = true;
278 }
279 if (!initialGoodFound)
280 {
281 currentSize /= 2;
282 }
283 else if (!initialBadFound)
284 {
285 currentSize *= 2;
286 }
287 else
288 {
289 int distance = smallestBad - largestGood;
290 if (distance == 1)
291 break;
292
293 currentSize = largestGood + distance / 2;
294 }
295
296 SetPointSize(currentSize);
297 }
298
299 if (currentSize != largestGood)
300 SetPointSize(largestGood);
53f6aab7
VZ
301}
302
9045ad9d 303void wxFontBase::DoSetNativeFontInfo(const wxNativeFontInfo& info)
30764ab5 304{
ab5fe833 305#ifdef wxNO_NATIVE_FONTINFO
30764ab5
VZ
306 SetPointSize(info.pointSize);
307 SetFamily(info.family);
308 SetStyle(info.style);
309 SetWeight(info.weight);
310 SetUnderlined(info.underlined);
c7a49742 311 SetStrikethrough(info.strikethrough);
30764ab5
VZ
312 SetFaceName(info.faceName);
313 SetEncoding(info.encoding);
33ac7e6f 314#else
1e6feb95 315 (void)info;
30764ab5
VZ
316#endif
317}
318
7826e2dd
VZ
319wxString wxFontBase::GetNativeFontInfoDesc() const
320{
64932e41
VZ
321 wxCHECK_MSG( IsOk(), wxEmptyString, wxT("invalid font") );
322
7826e2dd 323 wxString fontDesc;
3bf5a59b 324 const wxNativeFontInfo *fontInfo = GetNativeFontInfo();
7826e2dd
VZ
325 if ( fontInfo )
326 {
327 fontDesc = fontInfo->ToString();
dd05139a 328 wxASSERT_MSG(!fontDesc.empty(), wxT("This should be a non-empty string!"));
85ab460e
VZ
329 }
330 else
331 {
7bd236e6 332 wxFAIL_MSG(wxT("Derived class should have created the wxNativeFontInfo!"));
7826e2dd
VZ
333 }
334
335 return fontDesc;
336}
337
ab5fe833
VZ
338wxString wxFontBase::GetNativeFontInfoUserDesc() const
339{
64932e41
VZ
340 wxCHECK_MSG( IsOk(), wxEmptyString, wxT("invalid font") );
341
ab5fe833 342 wxString fontDesc;
3bf5a59b 343 const wxNativeFontInfo *fontInfo = GetNativeFontInfo();
ab5fe833
VZ
344 if ( fontInfo )
345 {
346 fontDesc = fontInfo->ToUserString();
dd05139a 347 wxASSERT_MSG(!fontDesc.empty(), wxT("This should be a non-empty string!"));
85ab460e
VZ
348 }
349 else
350 {
7456f382 351 wxFAIL_MSG(wxT("Derived class should have created the wxNativeFontInfo!"));
ab5fe833
VZ
352 }
353
354 return fontDesc;
355}
356
85ab460e 357bool wxFontBase::SetNativeFontInfo(const wxString& info)
31d1b66e
VZ
358{
359 wxNativeFontInfo fontInfo;
360 if ( !info.empty() && fontInfo.FromString(info) )
361 {
362 SetNativeFontInfo(fontInfo);
85ab460e 363 return true;
31d1b66e 364 }
85ab460e 365
85ab460e 366 return false;
31d1b66e
VZ
367}
368
85ab460e 369bool wxFontBase::SetNativeFontInfoUserDesc(const wxString& info)
ab5fe833
VZ
370{
371 wxNativeFontInfo fontInfo;
372 if ( !info.empty() && fontInfo.FromUserString(info) )
373 {
374 SetNativeFontInfo(fontInfo);
85ab460e 375 return true;
ab5fe833 376 }
85ab460e 377
85ab460e 378 return false;
ab5fe833
VZ
379}
380
0c5d3e1c
VZ
381bool wxFontBase::operator==(const wxFont& font) const
382{
8bf30fe9
VZ
383 // either it is the same font, i.e. they share the same common data or they
384 // have different ref datas but still describe the same font
a38cd629 385 return IsSameAs(font) ||
8bf30fe9 386 (
70f70818 387 IsOk() == font.IsOk() &&
8bf30fe9 388 GetPointSize() == font.GetPointSize() &&
82d0e7fe
VZ
389 // in wxGTK1 GetPixelSize() calls GetInternalFont() which uses
390 // operator==() resulting in infinite recursion so we can't use it
391 // in that port
392#if !defined(__WXGTK__) || defined(__WXGTK20__)
cc3de8a3 393 GetPixelSize() == font.GetPixelSize() &&
82d0e7fe 394#endif
8bf30fe9
VZ
395 GetFamily() == font.GetFamily() &&
396 GetStyle() == font.GetStyle() &&
e6adf058 397 GetWeight() == font.GetWeight() &&
8bf30fe9 398 GetUnderlined() == font.GetUnderlined() &&
c7a49742 399 GetStrikethrough() == font.GetStrikethrough() &&
85ab460e 400 GetFaceName().IsSameAs(font.GetFaceName(), false) &&
8bf30fe9
VZ
401 GetEncoding() == font.GetEncoding()
402 );
0c5d3e1c
VZ
403}
404
59b7da02
VZ
405wxFontFamily wxFontBase::GetFamily() const
406{
407 wxCHECK_MSG( IsOk(), wxFONTFAMILY_UNKNOWN, wxS("invalid font") );
408
409 // Don't return wxFONTFAMILY_UNKNOWN from here because it prevents the code
410 // like wxFont(size, wxNORMAL_FONT->GetFamily(), ...) from working (see
411 // #12330). This is really just a hack but it allows to keep compatibility
412 // and doesn't really have any bad drawbacks so do this until someone comes
413 // up with a better idea.
414 const wxFontFamily family = DoGetFamily();
415
416 return family == wxFONTFAMILY_UNKNOWN ? wxFONTFAMILY_DEFAULT : family;
417}
418
0c5d3e1c
VZ
419wxString wxFontBase::GetFamilyString() const
420{
70f70818 421 wxCHECK_MSG( IsOk(), "wxFONTFAMILY_DEFAULT", "invalid font" );
0c5d3e1c
VZ
422
423 switch ( GetFamily() )
424 {
70f70818
FM
425 case wxFONTFAMILY_DECORATIVE: return "wxFONTFAMILY_DECORATIVE";
426 case wxFONTFAMILY_ROMAN: return "wxFONTFAMILY_ROMAN";
427 case wxFONTFAMILY_SCRIPT: return "wxFONTFAMILY_SCRIPT";
428 case wxFONTFAMILY_SWISS: return "wxFONTFAMILY_SWISS";
429 case wxFONTFAMILY_MODERN: return "wxFONTFAMILY_MODERN";
430 case wxFONTFAMILY_TELETYPE: return "wxFONTFAMILY_TELETYPE";
f2c1b903 431 case wxFONTFAMILY_UNKNOWN: return "wxFONTFAMILY_UNKNOWN";
70f70818 432 default: return "wxFONTFAMILY_DEFAULT";
0c5d3e1c
VZ
433 }
434}
435
436wxString wxFontBase::GetStyleString() const
437{
70f70818 438 wxCHECK_MSG( IsOk(), "wxFONTSTYLE_DEFAULT", "invalid font" );
0c5d3e1c
VZ
439
440 switch ( GetStyle() )
441 {
70f70818
FM
442 case wxFONTSTYLE_NORMAL: return "wxFONTSTYLE_NORMAL";
443 case wxFONTSTYLE_SLANT: return "wxFONTSTYLE_SLANT";
444 case wxFONTSTYLE_ITALIC: return "wxFONTSTYLE_ITALIC";
445 default: return "wxFONTSTYLE_DEFAULT";
0c5d3e1c
VZ
446 }
447}
448
449wxString wxFontBase::GetWeightString() const
450{
70f70818 451 wxCHECK_MSG( IsOk(), "wxFONTWEIGHT_DEFAULT", "invalid font" );
0c5d3e1c
VZ
452
453 switch ( GetWeight() )
454 {
70f70818
FM
455 case wxFONTWEIGHT_NORMAL: return "wxFONTWEIGHT_NORMAL";
456 case wxFONTWEIGHT_BOLD: return "wxFONTWEIGHT_BOLD";
457 case wxFONTWEIGHT_LIGHT: return "wxFONTWEIGHT_LIGHT";
458 default: return "wxFONTWEIGHT_DEFAULT";
0c5d3e1c
VZ
459 }
460}
461
ff427585 462bool wxFontBase::SetFaceName(const wxString& facename)
85ab460e 463{
ff427585 464#if wxUSE_FONTENUM
85ab460e
VZ
465 if (!wxFontEnumerator::IsValidFacename(facename))
466 {
70f70818 467 UnRef(); // make IsOk() return false
85ab460e
VZ
468 return false;
469 }
ff427585
VZ
470#else // !wxUSE_FONTENUM
471 wxUnusedVar(facename);
472#endif // wxUSE_FONTENUM/!wxUSE_FONTENUM
85ab460e
VZ
473
474 return true;
475}
476
19da7aaa
VZ
477void wxFontBase::SetSymbolicSize(wxFontSymbolicSize size)
478{
479 SetSymbolicSizeRelativeTo(size, wxNORMAL_FONT->GetPointSize());
480}
481
482/* static */
483int wxFontBase::AdjustToSymbolicSize(wxFontSymbolicSize size, int base)
484{
485 // Using a fixed factor (1.2, from CSS2) is a bad idea as explained at
486 // http://www.w3.org/TR/CSS21/fonts.html#font-size-props so use the values
487 // from http://style.cleverchimp.com/font_size_intervals/altintervals.html
488 // instead.
489 static const float factors[] = { 0.60f, 0.75f, 0.89f, 1.f, 1.2f, 1.5f, 2.f };
490
491 wxCOMPILE_TIME_ASSERT
492 (
493 WXSIZEOF(factors) == wxFONTSIZE_XX_LARGE - wxFONTSIZE_XX_SMALL + 1,
494 WrongFontSizeFactorsSize
495 );
496
f76c3ff6 497 return wxRound(factors[size - wxFONTSIZE_XX_SMALL]*base);
19da7aaa
VZ
498}
499
6e7d2550
VZ
500wxFont& wxFont::MakeBold()
501{
502 SetWeight(wxFONTWEIGHT_BOLD);
503 return *this;
504}
505
506wxFont wxFont::Bold() const
f76c0758
VZ
507{
508 wxFont font(*this);
6e7d2550 509 font.MakeBold();
f76c0758
VZ
510 return font;
511}
512
6e7d2550
VZ
513wxFont& wxFont::MakeItalic()
514{
515 SetStyle(wxFONTSTYLE_ITALIC);
516 return *this;
517}
518
519wxFont wxFont::Italic() const
f76c0758
VZ
520{
521 wxFont font(*this);
801423ee
VZ
522 font.MakeItalic();
523 return font;
524}
525
526wxFont& wxFont::MakeUnderlined()
527{
528 SetUnderlined(true);
529 return *this;
530}
531
532wxFont wxFont::Underlined() const
533{
534 wxFont font(*this);
535 font.MakeUnderlined();
f76c0758
VZ
536 return font;
537}
538
c7a49742
VZ
539wxFont wxFont::Strikethrough() const
540{
541 wxFont font(*this);
542 font.MakeStrikethrough();
543 return font;
544}
545
546wxFont& wxFont::MakeStrikethrough()
547{
548 SetStrikethrough(true);
549 return *this;
550}
551
6e7d2550
VZ
552wxFont& wxFont::Scale(float x)
553{
554 SetPointSize(int(x*GetPointSize() + 0.5));
555 return *this;
556}
557
558wxFont wxFont::Scaled(float x) const
f76c0758
VZ
559{
560 wxFont font(*this);
6e7d2550 561 font.Scale(x);
f76c0758
VZ
562 return font;
563}
85ab460e 564
30764ab5
VZ
565// ----------------------------------------------------------------------------
566// wxNativeFontInfo
567// ----------------------------------------------------------------------------
568
85ab460e 569// Up to now, there are no native implementations of this function:
ff427585 570void wxNativeFontInfo::SetFaceName(const wxArrayString& facenames)
85ab460e 571{
ff427585 572#if wxUSE_FONTENUM
85ab460e
VZ
573 for (size_t i=0; i < facenames.GetCount(); i++)
574 {
575 if (wxFontEnumerator::IsValidFacename(facenames[i]))
576 {
577 SetFaceName(facenames[i]);
578 return;
579 }
580 }
581
582 // set the first valid facename we can find on this system
583 wxString validfacename = wxFontEnumerator::GetFacenames().Item(0);
584 wxLogTrace(wxT("font"), wxT("Falling back to '%s'"), validfacename.c_str());
585 SetFaceName(validfacename);
ff427585
VZ
586#else // !wxUSE_FONTENUM
587 SetFaceName(facenames[0]);
588#endif // wxUSE_FONTENUM/!wxUSE_FONTENUM
85ab460e
VZ
589}
590
591
ab5fe833
VZ
592#ifdef wxNO_NATIVE_FONTINFO
593
30764ab5
VZ
594// These are the generic forms of FromString()/ToString.
595//
c7a49742
VZ
596// convert to/from the string representation: the general format is
597// "version;the rest..." with currently defined versions being:
598//
599// 0;pointsize;family;style;weight;underlined;facename;encoding
600// 1;pointsize;family;style;weight;underlined;strikethrough;facename;encoding
30764ab5
VZ
601
602bool wxNativeFontInfo::FromString(const wxString& s)
603{
604 long l;
077c263a 605 unsigned long version;
30764ab5 606
9a83f860 607 wxStringTokenizer tokenizer(s, wxT(";"));
30764ab5
VZ
608
609 wxString token = tokenizer.GetNextToken();
077c263a 610 if ( !token.ToULong(&version) || version > 1 )
c7a49742 611 return false;
33ac7e6f 612
09fcd889 613 token = tokenizer.GetNextToken();
30764ab5 614 if ( !token.ToLong(&l) )
a62848fd 615 return false;
30764ab5
VZ
616 pointSize = (int)l;
617
618 token = tokenizer.GetNextToken();
619 if ( !token.ToLong(&l) )
a62848fd 620 return false;
f7b301fa 621 family = (wxFontFamily)l;
30764ab5
VZ
622
623 token = tokenizer.GetNextToken();
624 if ( !token.ToLong(&l) )
a62848fd 625 return false;
ab5fe833 626 style = (wxFontStyle)l;
30764ab5
VZ
627
628 token = tokenizer.GetNextToken();
629 if ( !token.ToLong(&l) )
a62848fd 630 return false;
ab5fe833 631 weight = (wxFontWeight)l;
30764ab5
VZ
632
633 token = tokenizer.GetNextToken();
634 if ( !token.ToLong(&l) )
a62848fd 635 return false;
189e08b4 636 underlined = l != 0;
30764ab5 637
c7a49742
VZ
638 if ( version == 1 )
639 {
640 token = tokenizer.GetNextToken();
641 if ( !token.ToLong(&l) )
642 return false;
643 strikethrough = l != 0;
644 }
645
30764ab5 646 faceName = tokenizer.GetNextToken();
0a9f0ef7
JS
647
648#ifndef __WXMAC__
30764ab5 649 if( !faceName )
a62848fd 650 return false;
0a9f0ef7 651#endif
30764ab5
VZ
652
653 token = tokenizer.GetNextToken();
654 if ( !token.ToLong(&l) )
a62848fd 655 return false;
30764ab5
VZ
656 encoding = (wxFontEncoding)l;
657
a62848fd 658 return true;
30764ab5
VZ
659}
660
661wxString wxNativeFontInfo::ToString() const
662{
663 wxString s;
664
c7a49742
VZ
665 s.Printf(wxT("%d;%d;%d;%d;%d;%d;%d;%s;%d"),
666 1, // version
30764ab5
VZ
667 pointSize,
668 family,
ab5fe833
VZ
669 (int)style,
670 (int)weight,
30764ab5 671 underlined,
c7a49742 672 strikethrough,
30764ab5
VZ
673 faceName.GetData(),
674 (int)encoding);
675
676 return s;
677}
678
ab5fe833
VZ
679void wxNativeFontInfo::Init()
680{
3bf5a59b 681 pointSize = 0;
ab5fe833
VZ
682 family = wxFONTFAMILY_DEFAULT;
683 style = wxFONTSTYLE_NORMAL;
684 weight = wxFONTWEIGHT_NORMAL;
a62848fd 685 underlined = false;
c7a49742 686 strikethrough = false;
ab5fe833
VZ
687 faceName.clear();
688 encoding = wxFONTENCODING_DEFAULT;
689}
690
691int wxNativeFontInfo::GetPointSize() const
692{
693 return pointSize;
694}
695
696wxFontStyle wxNativeFontInfo::GetStyle() const
697{
698 return style;
699}
700
701wxFontWeight wxNativeFontInfo::GetWeight() const
702{
703 return weight;
704}
705
706bool wxNativeFontInfo::GetUnderlined() const
707{
708 return underlined;
709}
710
c7a49742
VZ
711bool wxNativeFontInfo::GetStrikethrough() const
712{
713 return strikethrough;
714}
715
ab5fe833
VZ
716wxString wxNativeFontInfo::GetFaceName() const
717{
718 return faceName;
719}
720
7936354d
VZ
721wxFontFamily wxNativeFontInfo::GetFamily() const
722{
723 return family;
724}
725
ab5fe833
VZ
726wxFontEncoding wxNativeFontInfo::GetEncoding() const
727{
728 return encoding;
729}
730
731void wxNativeFontInfo::SetPointSize(int pointsize)
732{
733 pointSize = pointsize;
734}
735
736void wxNativeFontInfo::SetStyle(wxFontStyle style_)
737{
738 style = style_;
739}
740
741void wxNativeFontInfo::SetWeight(wxFontWeight weight_)
742{
743 weight = weight_;
744}
745
746void wxNativeFontInfo::SetUnderlined(bool underlined_)
747{
748 underlined = underlined_;
749}
750
c7a49742
VZ
751void wxNativeFontInfo::SetStrikethrough(bool strikethrough_)
752{
753 strikethrough = strikethrough_;
754}
755
85ab460e 756bool wxNativeFontInfo::SetFaceName(const wxString& facename_)
ab5fe833 757{
f7b301fa 758 faceName = facename_;
85ab460e 759 return true;
ab5fe833
VZ
760}
761
3f1d1373 762void wxNativeFontInfo::SetFamily(wxFontFamily family_)
7936354d
VZ
763{
764 family = family_;
765}
766
ab5fe833
VZ
767void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding_)
768{
769 encoding = encoding_;
770}
771
7826e2dd 772#endif // generic wxNativeFontInfo implementation
30764ab5 773
ab5fe833
VZ
774// conversion to/from user-readable string: this is used in the generic
775// versions and under MSW as well because there is no standard font description
776// format there anyhow (but there is a well-defined standard for X11 fonts used
777// by wxGTK and wxMotif)
778
f1c40652 779#if defined(wxNO_NATIVE_FONTINFO) || defined(__WXMSW__) || defined (__WXPM__) || defined(__WXOSX__)
ab5fe833
VZ
780
781wxString wxNativeFontInfo::ToUserString() const
782{
783 wxString desc;
784
785 // first put the adjectives, if any - this is English-centric, of course,
786 // but what else can we do?
787 if ( GetUnderlined() )
788 {
85ab460e 789 desc << _("underlined");
ab5fe833
VZ
790 }
791
c7a49742
VZ
792 if ( GetStrikethrough() )
793 {
794 desc << _("strikethrough");
795 }
796
ab5fe833
VZ
797 switch ( GetWeight() )
798 {
799 default:
9a83f860 800 wxFAIL_MSG( wxT("unknown font weight") );
ab5fe833
VZ
801 // fall through
802
803 case wxFONTWEIGHT_NORMAL:
804 break;
805
806 case wxFONTWEIGHT_LIGHT:
85ab460e 807 desc << _(" light");
ab5fe833
VZ
808 break;
809
810 case wxFONTWEIGHT_BOLD:
85ab460e 811 desc << _(" bold");
ab5fe833
VZ
812 break;
813 }
814
815 switch ( GetStyle() )
816 {
817 default:
9a83f860 818 wxFAIL_MSG( wxT("unknown font style") );
ab5fe833
VZ
819 // fall through
820
821 case wxFONTSTYLE_NORMAL:
822 break;
823
824 // we don't distinguish between the two for now anyhow...
825 case wxFONTSTYLE_ITALIC:
826 case wxFONTSTYLE_SLANT:
85ab460e 827 desc << _(" italic");
ab5fe833
VZ
828 break;
829 }
830
a9249b2e
VZ
831 wxString face = GetFaceName();
832 if ( !face.empty() )
ab5fe833 833 {
c1ab2be0
FM
834 if (face.Contains(' ') || face.Contains(';') || face.Contains(','))
835 {
836 face.Replace("'", "");
837 // eventually remove quote characters: most systems do not
838 // allow them in a facename anyway so this usually does nothing
839
840 // make it possible for FromUserString() function to understand
841 // that the different words which compose this facename are
842 // not different adjectives or other data but rather all parts
843 // of the facename
08267a6e 844 desc << wxT(" '") << face << wxT("'");
c1ab2be0
FM
845 }
846 else
9a83f860 847 desc << wxT(' ') << face;
ab5fe833 848 }
1a2ca1d6
VZ
849 else // no face name specified
850 {
851 // use the family
852 wxString familyStr;
853 switch ( GetFamily() )
854 {
855 case wxFONTFAMILY_DECORATIVE:
856 familyStr = "decorative";
857 break;
858
859 case wxFONTFAMILY_ROMAN:
860 familyStr = "roman";
861 break;
862
863 case wxFONTFAMILY_SCRIPT:
864 familyStr = "script";
865 break;
866
867 case wxFONTFAMILY_SWISS:
868 familyStr = "swiss";
869 break;
870
871 case wxFONTFAMILY_MODERN:
872 familyStr = "modern";
873 break;
874
875 case wxFONTFAMILY_TELETYPE:
876 familyStr = "teletype";
877 break;
878
879 case wxFONTFAMILY_DEFAULT:
880 case wxFONTFAMILY_UNKNOWN:
881 break;
882
883 default:
884 wxFAIL_MSG( "unknown font family" );
885 }
886
887 if ( !familyStr.empty() )
888 desc << " '" << familyStr << " family'";
889 }
ab5fe833 890
a9249b2e
VZ
891 int size = GetPointSize();
892 if ( size != wxNORMAL_FONT->GetPointSize() )
ab5fe833 893 {
9a83f860 894 desc << wxT(' ') << size;
ab5fe833 895 }
a9249b2e 896
e7e52b6d 897#if wxUSE_FONTMAP
a9249b2e
VZ
898 wxFontEncoding enc = GetEncoding();
899 if ( enc != wxFONTENCODING_DEFAULT && enc != wxFONTENCODING_SYSTEM )
900 {
9a83f860 901 desc << wxT(' ') << wxFontMapper::GetEncodingName(enc);
a9249b2e 902 }
e7e52b6d 903#endif // wxUSE_FONTMAP
a9249b2e 904
85ab460e 905 return desc.Strip(wxString::both).MakeLower();
ab5fe833
VZ
906}
907
908bool wxNativeFontInfo::FromUserString(const wxString& s)
909{
910 // reset to the default state
911 Init();
912
c1ab2be0
FM
913 // ToUserString() will quote the facename if it contains spaces, commas
914 // or semicolons: we must be able to understand that quoted text is
915 // a single token:
916 wxString toparse(s);
c1ab2be0 917
ab5fe833 918 // parse a more or less free form string
9a83f860 919 wxStringTokenizer tokenizer(toparse, wxT(";, "), wxTOKEN_STRTOK);
ab5fe833
VZ
920
921 wxString face;
922 unsigned long size;
77f15ffe
VS
923 bool weightfound = false, pointsizefound = false;
924#if wxUSE_FONTMAP
925 bool encodingfound = false;
926#endif
c1ab2be0 927 bool insideQuotes = false;
ab5fe833
VZ
928
929 while ( tokenizer.HasMoreTokens() )
930 {
931 wxString token = tokenizer.GetNextToken();
932
933 // normalize it
a62848fd 934 token.Trim(true).Trim(false).MakeLower();
c1ab2be0
FM
935 if (insideQuotes)
936 {
03647350 937 if (token.StartsWith("'") ||
c1ab2be0
FM
938 token.EndsWith("'"))
939 {
940 insideQuotes = false;
941
942 // add this last token to the facename:
943 face += " " + token;
944
945 // normalize facename:
946 face = face.Trim(true).Trim(false);
947 face.Replace("'", "");
948
949 continue;
950 }
951 }
952 else
953 {
954 if (token.StartsWith("'"))
955 insideQuotes = true;
956 }
ab5fe833
VZ
957
958 // look for the known tokens
c1ab2be0
FM
959 if ( insideQuotes )
960 {
961 // only the facename may be quoted:
962 face += " " + token;
963 continue;
964 }
9a83f860 965 if ( token == wxT("underlined") || token == _("underlined") )
ab5fe833 966 {
a62848fd 967 SetUnderlined(true);
ab5fe833 968 }
c7a49742
VZ
969 else if ( token == wxT("strikethrough") || token == _("strikethrough") )
970 {
971 SetStrikethrough(true);
972 }
9a83f860 973 else if ( token == wxT("light") || token == _("light") )
ab5fe833
VZ
974 {
975 SetWeight(wxFONTWEIGHT_LIGHT);
85ab460e 976 weightfound = true;
ab5fe833 977 }
9a83f860 978 else if ( token == wxT("bold") || token == _("bold") )
ab5fe833
VZ
979 {
980 SetWeight(wxFONTWEIGHT_BOLD);
85ab460e 981 weightfound = true;
ab5fe833 982 }
9a83f860 983 else if ( token == wxT("italic") || token == _("italic") )
ab5fe833
VZ
984 {
985 SetStyle(wxFONTSTYLE_ITALIC);
986 }
987 else if ( token.ToULong(&size) )
988 {
a9249b2e 989 SetPointSize(size);
85ab460e 990 pointsizefound = true;
ab5fe833 991 }
85ab460e
VZ
992 else
993 {
e7e52b6d 994#if wxUSE_FONTMAP
85ab460e
VZ
995 // try to interpret this as an encoding
996 wxFontEncoding encoding = wxFontMapper::Get()->CharsetToEncoding(token, false);
997 if ( encoding != wxFONTENCODING_DEFAULT &&
998 encoding != wxFONTENCODING_SYSTEM ) // returned when the recognition failed
ab5fe833
VZ
999 {
1000 SetEncoding(encoding);
85ab460e 1001 encodingfound = true;
ab5fe833 1002 }
85ab460e 1003 else
ab5fe833 1004 {
85ab460e
VZ
1005#endif // wxUSE_FONTMAP
1006
1007 // assume it is the face name
ab5fe833
VZ
1008 if ( !face.empty() )
1009 {
9a83f860 1010 face += wxT(' ');
ab5fe833
VZ
1011 }
1012
1013 face += token;
1014
1015 // skip the code which resets face below
1016 continue;
85ab460e
VZ
1017
1018#if wxUSE_FONTMAP
1019 }
1020#endif // wxUSE_FONTMAP
ab5fe833
VZ
1021 }
1022
1023 // if we had had the facename, we shouldn't continue appending tokens
1024 // to it (i.e. "foo bold bar" shouldn't result in the facename "foo
1025 // bar")
1026 if ( !face.empty() )
1027 {
1a2ca1d6
VZ
1028 wxString familyStr;
1029 if ( face.EndsWith(" family", &familyStr) )
1030 {
1031 // it's not a facename but rather a font family
1032 wxFontFamily family;
1033 if ( familyStr == "decorative" )
1034 family = wxFONTFAMILY_DECORATIVE;
1035 else if ( familyStr == "roman" )
1036 family = wxFONTFAMILY_ROMAN;
1037 else if ( familyStr == "script" )
1038 family = wxFONTFAMILY_SCRIPT;
1039 else if ( familyStr == "swiss" )
1040 family = wxFONTFAMILY_SWISS;
1041 else if ( familyStr == "modern" )
1042 family = wxFONTFAMILY_MODERN;
1043 else if ( familyStr == "teletype" )
1044 family = wxFONTFAMILY_TELETYPE;
1045 else
1046 return false;
03647350 1047
1a2ca1d6
VZ
1048 SetFamily(family);
1049 }
85ab460e 1050 // NB: the check on the facename is implemented in wxFontBase::SetFaceName
4c51a665 1051 // and not in wxNativeFontInfo::SetFaceName thus we need to explicitly
85ab460e 1052 // call here wxFontEnumerator::IsValidFacename
1a2ca1d6 1053 else if (
ff427585
VZ
1054#if wxUSE_FONTENUM
1055 !wxFontEnumerator::IsValidFacename(face) ||
1056#endif // wxUSE_FONTENUM
1057 !SetFaceName(face) )
1058 {
85ab460e 1059 SetFaceName(wxNORMAL_FONT->GetFaceName());
ff427585
VZ
1060 }
1061
ab5fe833
VZ
1062 face.clear();
1063 }
1064 }
1065
1066 // we might not have flushed it inside the loop
1067 if ( !face.empty() )
1068 {
85ab460e 1069 // NB: the check on the facename is implemented in wxFontBase::SetFaceName
4c51a665 1070 // and not in wxNativeFontInfo::SetFaceName thus we need to explicitly
85ab460e 1071 // call here wxFontEnumerator::IsValidFacename
ff427585
VZ
1072 if (
1073#if wxUSE_FONTENUM
1074 !wxFontEnumerator::IsValidFacename(face) ||
1075#endif // wxUSE_FONTENUM
1076 !SetFaceName(face) )
1077 {
1078 SetFaceName(wxNORMAL_FONT->GetFaceName());
1079 }
ab5fe833
VZ
1080 }
1081
85ab460e
VZ
1082 // set point size to default value if size was not given
1083 if ( !pointsizefound )
1084 SetPointSize(wxNORMAL_FONT->GetPointSize());
1085
1086 // set font weight to default value if weight was not given
1087 if ( !weightfound )
1088 SetWeight(wxFONTWEIGHT_NORMAL);
1089
1090#if wxUSE_FONTMAP
1091 // set font encoding to default value if encoding was not given
1092 if ( !encodingfound )
1093 SetEncoding(wxFONTENCODING_SYSTEM);
1094#endif // wxUSE_FONTMAP
1095
a62848fd 1096 return true;
ab5fe833
VZ
1097}
1098
0eb529d9 1099#endif // generic or wxMSW or wxOS2
fc9361e3
VZ
1100
1101
1102// wxFont <-> wxString utilities, used by wxConfig
1103wxString wxToString(const wxFontBase& font)
1104{
1105 return font.IsOk() ? font.GetNativeFontInfoDesc()
1106 : wxString();
1107}
1108
1109bool wxFromString(const wxString& str, wxFontBase *font)
1110{
9a83f860 1111 wxCHECK_MSG( font, false, wxT("NULL output parameter") );
fc9361e3
VZ
1112
1113 if ( str.empty() )
1114 {
1115 *font = wxNullFont;
1116 return true;
1117 }
1118
1119 return font->SetNativeFontInfo(str);
1120}
1121
1122