]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/fontcmn.cpp
Update version to 2.9.4 in version.bkl too and rebake everything.
[wxWidgets.git] / src / common / fontcmn.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/common/fontcmn.cpp
3// Purpose: implementation of wxFontBase methods
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 20.09.99
7// RCS-ID: $Id$
8// Copyright: (c) wxWidgets team
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27#include "wx/font.h"
28
29#ifndef WX_PRECOMP
30 #include "wx/dc.h"
31 #include "wx/intl.h"
32 #include "wx/math.h"
33 #include "wx/dcscreen.h"
34 #include "wx/log.h"
35 #include "wx/gdicmn.h"
36#endif // WX_PRECOMP
37
38#if defined(__WXMSW__)
39 #include "wx/msw/private.h" // includes windows.h for LOGFONT
40 #include "wx/msw/winundef.h"
41#endif
42
43#include "wx/fontutil.h" // for wxNativeFontInfo
44#include "wx/fontmap.h"
45#include "wx/fontenum.h"
46
47#include "wx/tokenzr.h"
48
49// debugger helper: this function can be called from a debugger to show what
50// the date really is
51extern const char *wxDumpFont(const wxFont *font)
52{
53 static char buf[256];
54
55 const wxFontWeight weight = font->GetWeight();
56
57 wxString s;
58 s.Printf(wxS("%s-%s-%s-%d-%d"),
59 font->GetFaceName(),
60 weight == wxFONTWEIGHT_NORMAL
61 ? wxT("normal")
62 : weight == wxFONTWEIGHT_BOLD
63 ? wxT("bold")
64 : wxT("light"),
65 font->GetStyle() == wxFONTSTYLE_NORMAL
66 ? wxT("regular")
67 : wxT("italic"),
68 font->GetPointSize(),
69 font->GetEncoding());
70
71 wxStrlcpy(buf, s.mb_str(), WXSIZEOF(buf));
72 return buf;
73}
74
75// ----------------------------------------------------------------------------
76// XTI
77// ----------------------------------------------------------------------------
78
79wxBEGIN_ENUM( wxFontFamily )
80wxENUM_MEMBER( wxFONTFAMILY_DEFAULT )
81wxENUM_MEMBER( wxFONTFAMILY_DECORATIVE )
82wxENUM_MEMBER( wxFONTFAMILY_ROMAN )
83wxENUM_MEMBER( wxFONTFAMILY_SCRIPT )
84wxENUM_MEMBER( wxFONTFAMILY_SWISS )
85wxENUM_MEMBER( wxFONTFAMILY_MODERN )
86wxENUM_MEMBER( wxFONTFAMILY_TELETYPE )
87wxEND_ENUM( wxFontFamily )
88
89wxBEGIN_ENUM( wxFontStyle )
90wxENUM_MEMBER( wxFONTSTYLE_NORMAL )
91wxENUM_MEMBER( wxFONTSTYLE_ITALIC )
92wxENUM_MEMBER( wxFONTSTYLE_SLANT )
93wxEND_ENUM( wxFontStyle )
94
95wxBEGIN_ENUM( wxFontWeight )
96wxENUM_MEMBER( wxFONTWEIGHT_NORMAL )
97wxENUM_MEMBER( wxFONTWEIGHT_LIGHT )
98wxENUM_MEMBER( wxFONTWEIGHT_BOLD )
99wxEND_ENUM( wxFontWeight )
100
101wxIMPLEMENT_DYNAMIC_CLASS_WITH_COPY_XTI(wxFont, wxGDIObject, "wx/font.h")
102
103//WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxFont>)
104
105wxBEGIN_PROPERTIES_TABLE(wxFont)
106wxPROPERTY( Size,int, SetPointSize, GetPointSize, 12, 0 /*flags*/, \
107 wxT("Helpstring"), wxT("group"))
108wxPROPERTY( Family, wxFontFamily , SetFamily, GetFamily, (wxFontFamily)wxDEFAULT, \
109 0 /*flags*/, wxT("Helpstring"), wxT("group")) // wxFontFamily
110wxPROPERTY( Style, wxFontStyle, SetStyle, GetStyle, (wxFontStyle)wxNORMAL, 0 /*flags*/, \
111 wxT("Helpstring"), wxT("group")) // wxFontStyle
112wxPROPERTY( Weight, wxFontWeight, SetWeight, GetWeight, (wxFontWeight)wxNORMAL, 0 /*flags*/, \
113 wxT("Helpstring"), wxT("group")) // wxFontWeight
114wxPROPERTY( Underlined, bool, SetUnderlined, GetUnderlined, false, 0 /*flags*/, \
115 wxT("Helpstring"), wxT("group"))
116wxPROPERTY( Face, wxString, SetFaceName, GetFaceName, wxEMPTY_PARAMETER_VALUE, \
117 0 /*flags*/, wxT("Helpstring"), wxT("group"))
118wxPROPERTY( Encoding, wxFontEncoding, SetEncoding, GetEncoding, \
119 wxFONTENCODING_DEFAULT, 0 /*flags*/, wxT("Helpstring"), wxT("group"))
120wxEND_PROPERTIES_TABLE()
121
122wxCONSTRUCTOR_6( wxFont, int, Size, wxFontFamily, Family, wxFontStyle, Style, wxFontWeight, Weight, \
123 bool, Underlined, wxString, Face )
124
125wxEMPTY_HANDLERS_TABLE(wxFont)
126
127// ============================================================================
128// implementation
129// ============================================================================
130
131// ----------------------------------------------------------------------------
132// helper functions
133// ----------------------------------------------------------------------------
134
135static 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
144static 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
153static inline bool flags2Underlined(int flags)
154{
155 return (flags & wxFONTFLAG_UNDERLINED) != 0;
156}
157
158// ----------------------------------------------------------------------------
159// wxFontBase
160// ----------------------------------------------------------------------------
161
162wxFontEncoding wxFontBase::ms_encodingDefault = wxFONTENCODING_SYSTEM;
163
164/* static */
165void 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
175wxFontBase::~wxFontBase()
176{
177 // this destructor is required for Darwin
178}
179
180/* static */
181wxFont *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 */
193wxFont *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 */
206wxFont *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 */
217wxFont *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 */
228wxFont *wxFontBase::New(const wxNativeFontInfo& info)
229{
230 return new wxFont(info);
231}
232
233/* static */
234wxFont *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
243bool wxFontBase::IsFixedWidth() const
244{
245 return GetFamily() == wxFONTFAMILY_TELETYPE;
246}
247
248wxSize wxFontBase::GetPixelSize() const
249{
250 wxScreenDC dc;
251 dc.SetFont(*(wxFont *)this);
252 return wxSize(dc.GetCharWidth(), dc.GetCharHeight());
253}
254
255bool wxFontBase::IsUsingSizeInPixels() const
256{
257 return false;
258}
259
260void 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
323void 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
338wxString 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
357wxString 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
376bool 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
388bool 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
400bool 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
423wxFontFamily 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
437wxString 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
454wxString 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
467wxString 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
480bool 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
495void wxFontBase::SetSymbolicSize(wxFontSymbolicSize size)
496{
497 SetSymbolicSizeRelativeTo(size, wxNORMAL_FONT->GetPointSize());
498}
499
500/* static */
501int 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
518wxFont& wxFont::MakeBold()
519{
520 SetWeight(wxFONTWEIGHT_BOLD);
521 return *this;
522}
523
524wxFont wxFont::Bold() const
525{
526 wxFont font(*this);
527 font.MakeBold();
528 return font;
529}
530
531wxFont& wxFont::MakeItalic()
532{
533 SetStyle(wxFONTSTYLE_ITALIC);
534 return *this;
535}
536
537wxFont wxFont::Italic() const
538{
539 wxFont font(*this);
540 font.MakeItalic();
541 return font;
542}
543
544wxFont& wxFont::MakeUnderlined()
545{
546 SetUnderlined(true);
547 return *this;
548}
549
550wxFont wxFont::Underlined() const
551{
552 wxFont font(*this);
553 font.MakeUnderlined();
554 return font;
555}
556
557wxFont& wxFont::Scale(float x)
558{
559 SetPointSize(int(x*GetPointSize() + 0.5));
560 return *this;
561}
562
563wxFont 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:
575void 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
604bool 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
655wxString 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
672void 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
683int wxNativeFontInfo::GetPointSize() const
684{
685 return pointSize;
686}
687
688wxFontStyle wxNativeFontInfo::GetStyle() const
689{
690 return style;
691}
692
693wxFontWeight wxNativeFontInfo::GetWeight() const
694{
695 return weight;
696}
697
698bool wxNativeFontInfo::GetUnderlined() const
699{
700 return underlined;
701}
702
703wxString wxNativeFontInfo::GetFaceName() const
704{
705 return faceName;
706}
707
708wxFontFamily wxNativeFontInfo::GetFamily() const
709{
710 return family;
711}
712
713wxFontEncoding wxNativeFontInfo::GetEncoding() const
714{
715 return encoding;
716}
717
718void wxNativeFontInfo::SetPointSize(int pointsize)
719{
720 pointSize = pointsize;
721}
722
723void wxNativeFontInfo::SetStyle(wxFontStyle style_)
724{
725 style = style_;
726}
727
728void wxNativeFontInfo::SetWeight(wxFontWeight weight_)
729{
730 weight = weight_;
731}
732
733void wxNativeFontInfo::SetUnderlined(bool underlined_)
734{
735 underlined = underlined_;
736}
737
738bool wxNativeFontInfo::SetFaceName(const wxString& facename_)
739{
740 faceName = facename_;
741 return true;
742}
743
744void wxNativeFontInfo::SetFamily(wxFontFamily family_)
745{
746 family = family_;
747}
748
749void 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
763wxString 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
885bool 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
1076wxString wxToString(const wxFontBase& font)
1077{
1078 return font.IsOk() ? font.GetNativeFontInfoDesc()
1079 : wxString();
1080}
1081
1082bool 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