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