]> git.saurik.com Git - wxWidgets.git/blob - src/common/fontcmn.cpp
fixing overrelease and out-of-bounds write, fixes #13725
[wxWidgets.git] / src / common / fontcmn.cpp
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
51 extern 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
79 wxBEGIN_ENUM( wxFontFamily )
80 wxENUM_MEMBER( wxFONTFAMILY_DEFAULT )
81 wxENUM_MEMBER( wxFONTFAMILY_DECORATIVE )
82 wxENUM_MEMBER( wxFONTFAMILY_ROMAN )
83 wxENUM_MEMBER( wxFONTFAMILY_SCRIPT )
84 wxENUM_MEMBER( wxFONTFAMILY_SWISS )
85 wxENUM_MEMBER( wxFONTFAMILY_MODERN )
86 wxENUM_MEMBER( wxFONTFAMILY_TELETYPE )
87 wxEND_ENUM( wxFontFamily )
88
89 wxBEGIN_ENUM( wxFontStyle )
90 wxENUM_MEMBER( wxFONTSTYLE_NORMAL )
91 wxENUM_MEMBER( wxFONTSTYLE_ITALIC )
92 wxENUM_MEMBER( wxFONTSTYLE_SLANT )
93 wxEND_ENUM( wxFontStyle )
94
95 wxBEGIN_ENUM( wxFontWeight )
96 wxENUM_MEMBER( wxFONTWEIGHT_NORMAL )
97 wxENUM_MEMBER( wxFONTWEIGHT_LIGHT )
98 wxENUM_MEMBER( wxFONTWEIGHT_BOLD )
99 wxEND_ENUM( wxFontWeight )
100
101 wxIMPLEMENT_DYNAMIC_CLASS_WITH_COPY_XTI(wxFont, wxGDIObject, "wx/font.h")
102
103 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxFont>)
104
105 wxBEGIN_PROPERTIES_TABLE(wxFont)
106 wxPROPERTY( Size,int, SetPointSize, GetPointSize, 12, 0 /*flags*/, \
107 wxT("Helpstring"), wxT("group"))
108 wxPROPERTY( Family, wxFontFamily , SetFamily, GetFamily, (wxFontFamily)wxDEFAULT, \
109 0 /*flags*/, wxT("Helpstring"), wxT("group")) // wxFontFamily
110 wxPROPERTY( Style, wxFontStyle, SetStyle, GetStyle, (wxFontStyle)wxNORMAL, 0 /*flags*/, \
111 wxT("Helpstring"), wxT("group")) // wxFontStyle
112 wxPROPERTY( Weight, wxFontWeight, SetWeight, GetWeight, (wxFontWeight)wxNORMAL, 0 /*flags*/, \
113 wxT("Helpstring"), wxT("group")) // wxFontWeight
114 wxPROPERTY( Underlined, bool, SetUnderlined, GetUnderlined, false, 0 /*flags*/, \
115 wxT("Helpstring"), wxT("group"))
116 wxPROPERTY( Strikethrough, bool, SetStrikethrough, GetStrikethrough, false, 0, \
117 wxT("Helpstring"), wxT("group"))
118 wxPROPERTY( Face, wxString, SetFaceName, GetFaceName, wxEMPTY_PARAMETER_VALUE, \
119 0 /*flags*/, wxT("Helpstring"), wxT("group"))
120 wxPROPERTY( Encoding, wxFontEncoding, SetEncoding, GetEncoding, \
121 wxFONTENCODING_DEFAULT, 0 /*flags*/, wxT("Helpstring"), wxT("group"))
122 wxEND_PROPERTIES_TABLE()
123
124 wxCONSTRUCTOR_6( wxFont, int, Size, wxFontFamily, Family, wxFontStyle, Style, wxFontWeight, Weight, \
125 bool, Underlined, wxString, Face )
126
127 wxEMPTY_HANDLERS_TABLE(wxFont)
128
129 // ============================================================================
130 // implementation
131 // ============================================================================
132
133 // ----------------------------------------------------------------------------
134 // wxFontBase
135 // ----------------------------------------------------------------------------
136
137 wxFontEncoding wxFontBase::ms_encodingDefault = wxFONTENCODING_SYSTEM;
138
139 /* static */
140 void 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
150 wxFontBase::~wxFontBase()
151 {
152 // this destructor is required for Darwin
153 }
154
155 /* static */
156 wxFont *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 */
168 wxFont *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 */
181 wxFont *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 */
195 wxFont *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 */
209 wxFont *wxFontBase::New(const wxNativeFontInfo& info)
210 {
211 return new wxFont(info);
212 }
213
214 /* static */
215 wxFont *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
224 bool wxFontBase::IsFixedWidth() const
225 {
226 return GetFamily() == wxFONTFAMILY_TELETYPE;
227 }
228
229 wxSize wxFontBase::GetPixelSize() const
230 {
231 wxScreenDC dc;
232 dc.SetFont(*(wxFont *)this);
233 return wxSize(dc.GetCharWidth(), dc.GetCharHeight());
234 }
235
236 bool wxFontBase::IsUsingSizeInPixels() const
237 {
238 return false;
239 }
240
241 void 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
304 void 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
320 wxString 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
339 wxString 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
358 bool 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
370 bool 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
382 bool 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
406 wxFontFamily 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
420 wxString 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
437 wxString 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
450 wxString 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
463 bool 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
478 void wxFontBase::SetSymbolicSize(wxFontSymbolicSize size)
479 {
480 SetSymbolicSizeRelativeTo(size, wxNORMAL_FONT->GetPointSize());
481 }
482
483 /* static */
484 int 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
501 wxFont& wxFont::MakeBold()
502 {
503 SetWeight(wxFONTWEIGHT_BOLD);
504 return *this;
505 }
506
507 wxFont wxFont::Bold() const
508 {
509 wxFont font(*this);
510 font.MakeBold();
511 return font;
512 }
513
514 wxFont& wxFont::MakeItalic()
515 {
516 SetStyle(wxFONTSTYLE_ITALIC);
517 return *this;
518 }
519
520 wxFont wxFont::Italic() const
521 {
522 wxFont font(*this);
523 font.MakeItalic();
524 return font;
525 }
526
527 wxFont& wxFont::MakeUnderlined()
528 {
529 SetUnderlined(true);
530 return *this;
531 }
532
533 wxFont wxFont::Underlined() const
534 {
535 wxFont font(*this);
536 font.MakeUnderlined();
537 return font;
538 }
539
540 wxFont wxFont::Strikethrough() const
541 {
542 wxFont font(*this);
543 font.MakeStrikethrough();
544 return font;
545 }
546
547 wxFont& wxFont::MakeStrikethrough()
548 {
549 SetStrikethrough(true);
550 return *this;
551 }
552
553 wxFont& wxFont::Scale(float x)
554 {
555 SetPointSize(int(x*GetPointSize() + 0.5));
556 return *this;
557 }
558
559 wxFont 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:
571 void 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
603 bool 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
662 wxString 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
680 void 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
692 int wxNativeFontInfo::GetPointSize() const
693 {
694 return pointSize;
695 }
696
697 wxFontStyle wxNativeFontInfo::GetStyle() const
698 {
699 return style;
700 }
701
702 wxFontWeight wxNativeFontInfo::GetWeight() const
703 {
704 return weight;
705 }
706
707 bool wxNativeFontInfo::GetUnderlined() const
708 {
709 return underlined;
710 }
711
712 bool wxNativeFontInfo::GetStrikethrough() const
713 {
714 return strikethrough;
715 }
716
717 wxString wxNativeFontInfo::GetFaceName() const
718 {
719 return faceName;
720 }
721
722 wxFontFamily wxNativeFontInfo::GetFamily() const
723 {
724 return family;
725 }
726
727 wxFontEncoding wxNativeFontInfo::GetEncoding() const
728 {
729 return encoding;
730 }
731
732 void wxNativeFontInfo::SetPointSize(int pointsize)
733 {
734 pointSize = pointsize;
735 }
736
737 void wxNativeFontInfo::SetStyle(wxFontStyle style_)
738 {
739 style = style_;
740 }
741
742 void wxNativeFontInfo::SetWeight(wxFontWeight weight_)
743 {
744 weight = weight_;
745 }
746
747 void wxNativeFontInfo::SetUnderlined(bool underlined_)
748 {
749 underlined = underlined_;
750 }
751
752 void wxNativeFontInfo::SetStrikethrough(bool strikethrough_)
753 {
754 strikethrough = strikethrough_;
755 }
756
757 bool wxNativeFontInfo::SetFaceName(const wxString& facename_)
758 {
759 faceName = facename_;
760 return true;
761 }
762
763 void wxNativeFontInfo::SetFamily(wxFontFamily family_)
764 {
765 family = family_;
766 }
767
768 void 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
782 wxString 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
909 bool 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
1104 wxString wxToString(const wxFontBase& font)
1105 {
1106 return font.IsOk() ? font.GetNativeFontInfoDesc()
1107 : wxString();
1108 }
1109
1110 bool 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