]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/fontcmn.cpp
fixing overrelease and out-of-bounds write, fixes #13725
[wxWidgets.git] / src / common / fontcmn.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/common/fontcmn.cpp
3// Purpose: implementation of wxFontBase methods
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 20.09.99
7// RCS-ID: $Id$
8// Copyright: (c) wxWidgets team
9// Licence: wxWindows licence
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__
24 #pragma hdrstop
25#endif
26
27#include "wx/font.h"
28
29#ifndef WX_PRECOMP
30 #include "wx/dc.h"
31 #include "wx/intl.h"
32 #include "wx/math.h"
33 #include "wx/dcscreen.h"
34 #include "wx/log.h"
35 #include "wx/gdicmn.h"
36#endif // WX_PRECOMP
37
38#if defined(__WXMSW__)
39 #include "wx/msw/private.h" // includes windows.h for LOGFONT
40 #include "wx/msw/winundef.h"
41#endif
42
43#include "wx/fontutil.h" // for wxNativeFontInfo
44#include "wx/fontmap.h"
45#include "wx/fontenum.h"
46
47#include "wx/tokenzr.h"
48
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
61 ? wxT("normal")
62 : weight == wxFONTWEIGHT_BOLD
63 ? wxT("bold")
64 : wxT("light"),
65 font->GetStyle() == wxFONTSTYLE_NORMAL
66 ? wxT("regular")
67 : wxT("italic"),
68 font->GetPointSize(),
69 font->GetEncoding());
70
71 wxStrlcpy(buf, s.mb_str(), WXSIZEOF(buf));
72 return buf;
73}
74
75// ----------------------------------------------------------------------------
76// XTI
77// ----------------------------------------------------------------------------
78
79wxBEGIN_ENUM( wxFontFamily )
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 )
87wxEND_ENUM( wxFontFamily )
88
89wxBEGIN_ENUM( wxFontStyle )
90wxENUM_MEMBER( wxFONTSTYLE_NORMAL )
91wxENUM_MEMBER( wxFONTSTYLE_ITALIC )
92wxENUM_MEMBER( wxFONTSTYLE_SLANT )
93wxEND_ENUM( wxFontStyle )
94
95wxBEGIN_ENUM( wxFontWeight )
96wxENUM_MEMBER( wxFONTWEIGHT_NORMAL )
97wxENUM_MEMBER( wxFONTWEIGHT_LIGHT )
98wxENUM_MEMBER( wxFONTWEIGHT_BOLD )
99wxEND_ENUM( wxFontWeight )
100
101wxIMPLEMENT_DYNAMIC_CLASS_WITH_COPY_XTI(wxFont, wxGDIObject, "wx/font.h")
102
103//WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxFont>)
104
105wxBEGIN_PROPERTIES_TABLE(wxFont)
106wxPROPERTY( Size,int, SetPointSize, GetPointSize, 12, 0 /*flags*/, \
107 wxT("Helpstring"), wxT("group"))
108wxPROPERTY( Family, wxFontFamily , SetFamily, GetFamily, (wxFontFamily)wxDEFAULT, \
109 0 /*flags*/, wxT("Helpstring"), wxT("group")) // wxFontFamily
110wxPROPERTY( Style, wxFontStyle, SetStyle, GetStyle, (wxFontStyle)wxNORMAL, 0 /*flags*/, \
111 wxT("Helpstring"), wxT("group")) // wxFontStyle
112wxPROPERTY( Weight, wxFontWeight, SetWeight, GetWeight, (wxFontWeight)wxNORMAL, 0 /*flags*/, \
113 wxT("Helpstring"), wxT("group")) // wxFontWeight
114wxPROPERTY( Underlined, bool, SetUnderlined, GetUnderlined, false, 0 /*flags*/, \
115 wxT("Helpstring"), wxT("group"))
116wxPROPERTY( Strikethrough, bool, SetStrikethrough, GetStrikethrough, false, 0, \
117 wxT("Helpstring"), wxT("group"))
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
124wxCONSTRUCTOR_6( wxFont, int, Size, wxFontFamily, Family, wxFontStyle, Style, wxFontWeight, Weight, \
125 bool, Underlined, wxString, Face )
126
127wxEMPTY_HANDLERS_TABLE(wxFont)
128
129// ============================================================================
130// implementation
131// ============================================================================
132
133// ----------------------------------------------------------------------------
134// wxFontBase
135// ----------------------------------------------------------------------------
136
137wxFontEncoding wxFontBase::ms_encodingDefault = wxFONTENCODING_SYSTEM;
138
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,
145 wxT("can't set default encoding to wxFONTENCODING_DEFAULT") );
146
147 ms_encodingDefault = encoding;
148}
149
150wxFontBase::~wxFontBase()
151{
152 // this destructor is required for Darwin
153}
154
155/* static */
156wxFont *wxFontBase::New(int size,
157 wxFontFamily family,
158 wxFontStyle style,
159 wxFontWeight weight,
160 bool underlined,
161 const wxString& face,
162 wxFontEncoding encoding)
163{
164 return new wxFont(size, family, style, weight, underlined, face, encoding);
165}
166
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)
175{
176 return new wxFont(pixelSize, family, style, weight, underlined,
177 face, encoding);
178}
179
180/* static */
181wxFont *wxFontBase::New(int pointSize,
182 wxFontFamily family,
183 int flags,
184 const wxString& face,
185 wxFontEncoding encoding)
186{
187 return New(pointSize, family,
188 GetStyleFromFlags(flags),
189 GetWeightFromFlags(flags),
190 GetUnderlinedFromFlags(flags),
191 face, encoding);
192}
193
194/* static */
195wxFont *wxFontBase::New(const wxSize& pixelSize,
196 wxFontFamily family,
197 int flags,
198 const wxString& face,
199 wxFontEncoding encoding)
200{
201 return New(pixelSize, family,
202 GetStyleFromFlags(flags),
203 GetWeightFromFlags(flags),
204 GetUnderlinedFromFlags(flags),
205 face, encoding);
206}
207
208/* static */
209wxFont *wxFontBase::New(const wxNativeFontInfo& info)
210{
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;
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{
243 wxCHECK_RET( pixelSize.GetWidth() >= 0 && pixelSize.GetHeight() > 0,
244 "Negative values for the pixel size or zero pixel height are not allowed" );
245
246 wxScreenDC dc;
247
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.
251
252 int largestGood = 0;
253 int smallestBad = 0;
254
255 bool initialGoodFound = false;
256 bool initialBadFound = false;
257
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));
264
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);
302}
303
304void wxFontBase::DoSetNativeFontInfo(const wxNativeFontInfo& info)
305{
306#ifdef wxNO_NATIVE_FONTINFO
307 SetPointSize(info.pointSize);
308 SetFamily(info.family);
309 SetStyle(info.style);
310 SetWeight(info.weight);
311 SetUnderlined(info.underlined);
312 SetStrikethrough(info.strikethrough);
313 SetFaceName(info.faceName);
314 SetEncoding(info.encoding);
315#else
316 (void)info;
317#endif
318}
319
320wxString wxFontBase::GetNativeFontInfoDesc() const
321{
322 wxCHECK_MSG( IsOk(), wxEmptyString, wxT("invalid font") );
323
324 wxString fontDesc;
325 const wxNativeFontInfo *fontInfo = GetNativeFontInfo();
326 if ( fontInfo )
327 {
328 fontDesc = fontInfo->ToString();
329 wxASSERT_MSG(!fontDesc.empty(), wxT("This should be a non-empty string!"));
330 }
331 else
332 {
333 wxFAIL_MSG(wxT("Derived class should have created the wxNativeFontInfo!"));
334 }
335
336 return fontDesc;
337}
338
339wxString wxFontBase::GetNativeFontInfoUserDesc() const
340{
341 wxCHECK_MSG( IsOk(), wxEmptyString, wxT("invalid font") );
342
343 wxString fontDesc;
344 const wxNativeFontInfo *fontInfo = GetNativeFontInfo();
345 if ( fontInfo )
346 {
347 fontDesc = fontInfo->ToUserString();
348 wxASSERT_MSG(!fontDesc.empty(), wxT("This should be a non-empty string!"));
349 }
350 else
351 {
352 wxFAIL_MSG(wxT("Derived class should have created the wxNativeFontInfo!"));
353 }
354
355 return fontDesc;
356}
357
358bool wxFontBase::SetNativeFontInfo(const wxString& info)
359{
360 wxNativeFontInfo fontInfo;
361 if ( !info.empty() && fontInfo.FromString(info) )
362 {
363 SetNativeFontInfo(fontInfo);
364 return true;
365 }
366
367 return false;
368}
369
370bool wxFontBase::SetNativeFontInfoUserDesc(const wxString& info)
371{
372 wxNativeFontInfo fontInfo;
373 if ( !info.empty() && fontInfo.FromUserString(info) )
374 {
375 SetNativeFontInfo(fontInfo);
376 return true;
377 }
378
379 return false;
380}
381
382bool wxFontBase::operator==(const wxFont& font) const
383{
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
386 return IsSameAs(font) ||
387 (
388 IsOk() == font.IsOk() &&
389 GetPointSize() == font.GetPointSize() &&
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__)
394 GetPixelSize() == font.GetPixelSize() &&
395#endif
396 GetFamily() == font.GetFamily() &&
397 GetStyle() == font.GetStyle() &&
398 GetWeight() == font.GetWeight() &&
399 GetUnderlined() == font.GetUnderlined() &&
400 GetStrikethrough() == font.GetStrikethrough() &&
401 GetFaceName().IsSameAs(font.GetFaceName(), false) &&
402 GetEncoding() == font.GetEncoding()
403 );
404}
405
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
420wxString wxFontBase::GetFamilyString() const
421{
422 wxCHECK_MSG( IsOk(), "wxFONTFAMILY_DEFAULT", "invalid font" );
423
424 switch ( GetFamily() )
425 {
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";
432 case wxFONTFAMILY_UNKNOWN: return "wxFONTFAMILY_UNKNOWN";
433 default: return "wxFONTFAMILY_DEFAULT";
434 }
435}
436
437wxString wxFontBase::GetStyleString() const
438{
439 wxCHECK_MSG( IsOk(), "wxFONTSTYLE_DEFAULT", "invalid font" );
440
441 switch ( GetStyle() )
442 {
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";
447 }
448}
449
450wxString wxFontBase::GetWeightString() const
451{
452 wxCHECK_MSG( IsOk(), "wxFONTWEIGHT_DEFAULT", "invalid font" );
453
454 switch ( GetWeight() )
455 {
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";
460 }
461}
462
463bool wxFontBase::SetFaceName(const wxString& facename)
464{
465#if wxUSE_FONTENUM
466 if (!wxFontEnumerator::IsValidFacename(facename))
467 {
468 UnRef(); // make IsOk() return false
469 return false;
470 }
471#else // !wxUSE_FONTENUM
472 wxUnusedVar(facename);
473#endif // wxUSE_FONTENUM/!wxUSE_FONTENUM
474
475 return true;
476}
477
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
498 return wxRound(factors[size - wxFONTSIZE_XX_SMALL]*base);
499}
500
501wxFont& wxFont::MakeBold()
502{
503 SetWeight(wxFONTWEIGHT_BOLD);
504 return *this;
505}
506
507wxFont wxFont::Bold() const
508{
509 wxFont font(*this);
510 font.MakeBold();
511 return font;
512}
513
514wxFont& wxFont::MakeItalic()
515{
516 SetStyle(wxFONTSTYLE_ITALIC);
517 return *this;
518}
519
520wxFont wxFont::Italic() const
521{
522 wxFont font(*this);
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();
537 return font;
538}
539
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
553wxFont& wxFont::Scale(float x)
554{
555 SetPointSize(int(x*GetPointSize() + 0.5));
556 return *this;
557}
558
559wxFont wxFont::Scaled(float x) const
560{
561 wxFont font(*this);
562 font.Scale(x);
563 return font;
564}
565
566// ----------------------------------------------------------------------------
567// wxNativeFontInfo
568// ----------------------------------------------------------------------------
569
570// Up to now, there are no native implementations of this function:
571void wxNativeFontInfo::SetFaceName(const wxArrayString& facenames)
572{
573#if wxUSE_FONTENUM
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);
587#else // !wxUSE_FONTENUM
588 SetFaceName(facenames[0]);
589#endif // wxUSE_FONTENUM/!wxUSE_FONTENUM
590}
591
592
593#ifdef wxNO_NATIVE_FONTINFO
594
595// These are the generic forms of FromString()/ToString.
596//
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
602
603bool wxNativeFontInfo::FromString(const wxString& s)
604{
605 long l;
606 unsigned long version;
607
608 wxStringTokenizer tokenizer(s, wxT(";"));
609
610 wxString token = tokenizer.GetNextToken();
611 if ( !token.ToULong(&version) || version > 1 )
612 return false;
613
614 token = tokenizer.GetNextToken();
615 if ( !token.ToLong(&l) )
616 return false;
617 pointSize = (int)l;
618
619 token = tokenizer.GetNextToken();
620 if ( !token.ToLong(&l) )
621 return false;
622 family = (wxFontFamily)l;
623
624 token = tokenizer.GetNextToken();
625 if ( !token.ToLong(&l) )
626 return false;
627 style = (wxFontStyle)l;
628
629 token = tokenizer.GetNextToken();
630 if ( !token.ToLong(&l) )
631 return false;
632 weight = (wxFontWeight)l;
633
634 token = tokenizer.GetNextToken();
635 if ( !token.ToLong(&l) )
636 return false;
637 underlined = l != 0;
638
639 if ( version == 1 )
640 {
641 token = tokenizer.GetNextToken();
642 if ( !token.ToLong(&l) )
643 return false;
644 strikethrough = l != 0;
645 }
646
647 faceName = tokenizer.GetNextToken();
648
649#ifndef __WXMAC__
650 if( !faceName )
651 return false;
652#endif
653
654 token = tokenizer.GetNextToken();
655 if ( !token.ToLong(&l) )
656 return false;
657 encoding = (wxFontEncoding)l;
658
659 return true;
660}
661
662wxString wxNativeFontInfo::ToString() const
663{
664 wxString s;
665
666 s.Printf(wxT("%d;%d;%d;%d;%d;%d;%d;%s;%d"),
667 1, // version
668 pointSize,
669 family,
670 (int)style,
671 (int)weight,
672 underlined,
673 strikethrough,
674 faceName.GetData(),
675 (int)encoding);
676
677 return s;
678}
679
680void wxNativeFontInfo::Init()
681{
682 pointSize = 0;
683 family = wxFONTFAMILY_DEFAULT;
684 style = wxFONTSTYLE_NORMAL;
685 weight = wxFONTWEIGHT_NORMAL;
686 underlined = false;
687 strikethrough = false;
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
712bool wxNativeFontInfo::GetStrikethrough() const
713{
714 return strikethrough;
715}
716
717wxString wxNativeFontInfo::GetFaceName() const
718{
719 return faceName;
720}
721
722wxFontFamily wxNativeFontInfo::GetFamily() const
723{
724 return family;
725}
726
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
752void wxNativeFontInfo::SetStrikethrough(bool strikethrough_)
753{
754 strikethrough = strikethrough_;
755}
756
757bool wxNativeFontInfo::SetFaceName(const wxString& facename_)
758{
759 faceName = facename_;
760 return true;
761}
762
763void wxNativeFontInfo::SetFamily(wxFontFamily family_)
764{
765 family = family_;
766}
767
768void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding_)
769{
770 encoding = encoding_;
771}
772
773#endif // generic wxNativeFontInfo implementation
774
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
780#if defined(wxNO_NATIVE_FONTINFO) || defined(__WXMSW__) || defined (__WXPM__) || defined(__WXOSX__)
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 {
790 desc << _("underlined");
791 }
792
793 if ( GetStrikethrough() )
794 {
795 desc << _("strikethrough");
796 }
797
798 switch ( GetWeight() )
799 {
800 default:
801 wxFAIL_MSG( wxT("unknown font weight") );
802 // fall through
803
804 case wxFONTWEIGHT_NORMAL:
805 break;
806
807 case wxFONTWEIGHT_LIGHT:
808 desc << _(" light");
809 break;
810
811 case wxFONTWEIGHT_BOLD:
812 desc << _(" bold");
813 break;
814 }
815
816 switch ( GetStyle() )
817 {
818 default:
819 wxFAIL_MSG( wxT("unknown font style") );
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:
828 desc << _(" italic");
829 break;
830 }
831
832 wxString face = GetFaceName();
833 if ( !face.empty() )
834 {
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
845 desc << wxT(" '") << face << _("'");
846 }
847 else
848 desc << wxT(' ') << face;
849 }
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 }
891
892 int size = GetPointSize();
893 if ( size != wxNORMAL_FONT->GetPointSize() )
894 {
895 desc << wxT(' ') << size;
896 }
897
898#if wxUSE_FONTMAP
899 wxFontEncoding enc = GetEncoding();
900 if ( enc != wxFONTENCODING_DEFAULT && enc != wxFONTENCODING_SYSTEM )
901 {
902 desc << wxT(' ') << wxFontMapper::GetEncodingName(enc);
903 }
904#endif // wxUSE_FONTMAP
905
906 return desc.Strip(wxString::both).MakeLower();
907}
908
909bool wxNativeFontInfo::FromUserString(const wxString& s)
910{
911 // reset to the default state
912 Init();
913
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);
918
919 // parse a more or less free form string
920 wxStringTokenizer tokenizer(toparse, wxT(";, "), wxTOKEN_STRTOK);
921
922 wxString face;
923 unsigned long size;
924 bool weightfound = false, pointsizefound = false;
925#if wxUSE_FONTMAP
926 bool encodingfound = false;
927#endif
928 bool insideQuotes = false;
929
930 while ( tokenizer.HasMoreTokens() )
931 {
932 wxString token = tokenizer.GetNextToken();
933
934 // normalize it
935 token.Trim(true).Trim(false).MakeLower();
936 if (insideQuotes)
937 {
938 if (token.StartsWith("'") ||
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 }
958
959 // look for the known tokens
960 if ( insideQuotes )
961 {
962 // only the facename may be quoted:
963 face += " " + token;
964 continue;
965 }
966 if ( token == wxT("underlined") || token == _("underlined") )
967 {
968 SetUnderlined(true);
969 }
970 else if ( token == wxT("strikethrough") || token == _("strikethrough") )
971 {
972 SetStrikethrough(true);
973 }
974 else if ( token == wxT("light") || token == _("light") )
975 {
976 SetWeight(wxFONTWEIGHT_LIGHT);
977 weightfound = true;
978 }
979 else if ( token == wxT("bold") || token == _("bold") )
980 {
981 SetWeight(wxFONTWEIGHT_BOLD);
982 weightfound = true;
983 }
984 else if ( token == wxT("italic") || token == _("italic") )
985 {
986 SetStyle(wxFONTSTYLE_ITALIC);
987 }
988 else if ( token.ToULong(&size) )
989 {
990 SetPointSize(size);
991 pointsizefound = true;
992 }
993 else
994 {
995#if wxUSE_FONTMAP
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
1000 {
1001 SetEncoding(encoding);
1002 encodingfound = true;
1003 }
1004 else
1005 {
1006#endif // wxUSE_FONTMAP
1007
1008 // assume it is the face name
1009 if ( !face.empty() )
1010 {
1011 face += wxT(' ');
1012 }
1013
1014 face += token;
1015
1016 // skip the code which resets face below
1017 continue;
1018
1019#if wxUSE_FONTMAP
1020 }
1021#endif // wxUSE_FONTMAP
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 {
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;
1048
1049 SetFamily(family);
1050 }
1051 // NB: the check on the facename is implemented in wxFontBase::SetFaceName
1052 // and not in wxNativeFontInfo::SetFaceName thus we need to explicitly
1053 // call here wxFontEnumerator::IsValidFacename
1054 else if (
1055#if wxUSE_FONTENUM
1056 !wxFontEnumerator::IsValidFacename(face) ||
1057#endif // wxUSE_FONTENUM
1058 !SetFaceName(face) )
1059 {
1060 SetFaceName(wxNORMAL_FONT->GetFaceName());
1061 }
1062
1063 face.clear();
1064 }
1065 }
1066
1067 // we might not have flushed it inside the loop
1068 if ( !face.empty() )
1069 {
1070 // NB: the check on the facename is implemented in wxFontBase::SetFaceName
1071 // and not in wxNativeFontInfo::SetFaceName thus we need to explicitly
1072 // call here wxFontEnumerator::IsValidFacename
1073 if (
1074#if wxUSE_FONTENUM
1075 !wxFontEnumerator::IsValidFacename(face) ||
1076#endif // wxUSE_FONTENUM
1077 !SetFaceName(face) )
1078 {
1079 SetFaceName(wxNORMAL_FONT->GetFaceName());
1080 }
1081 }
1082
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
1097 return true;
1098}
1099
1100#endif // generic or wxMSW or wxOS2
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{
1112 wxCHECK_MSG( font, false, wxT("NULL output parameter") );
1113
1114 if ( str.empty() )
1115 {
1116 *font = wxNullFont;
1117 return true;
1118 }
1119
1120 return font->SetNativeFontInfo(str);
1121}
1122
1123