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