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