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