]> git.saurik.com Git - wxWidgets.git/blame - src/common/fontcmn.cpp
Mention wxGTK wxAnimation implementation limitations in the docs.
[wxWidgets.git] / src / common / fontcmn.cpp
CommitLineData
8f7fa6f8 1/////////////////////////////////////////////////////////////////////////////
da80ae71 2// Name: src/common/fontcmn.cpp
0c5d3e1c
VZ
3// Purpose: implementation of wxFontBase methods
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 20.09.99
7// RCS-ID: $Id$
77ffb593 8// Copyright: (c) wxWidgets team
65571936 9// Licence: wxWindows licence
0c5d3e1c
VZ
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__
da80ae71 24 #pragma hdrstop
0c5d3e1c
VZ
25#endif
26
da80ae71
WS
27#include "wx/font.h"
28
0c5d3e1c 29#ifndef WX_PRECOMP
452aa069 30 #include "wx/dc.h"
9342fdbe 31 #include "wx/intl.h"
f76c3ff6 32 #include "wx/math.h"
9342fdbe 33 #include "wx/dcscreen.h"
8d3ba63b 34 #include "wx/log.h"
dd05139a 35 #include "wx/gdicmn.h"
0c5d3e1c
VZ
36#endif // WX_PRECOMP
37
82ef81ed 38#if defined(__WXMSW__)
7bd236e6
WS
39 #include "wx/msw/private.h" // includes windows.h for LOGFONT
40 #include "wx/msw/winundef.h"
1c193821
JS
41#endif
42
76e23cdb 43#include "wx/fontutil.h" // for wxNativeFontInfo
ab5fe833 44#include "wx/fontmap.h"
85ab460e 45#include "wx/fontenum.h"
76e23cdb 46
30764ab5
VZ
47#include "wx/tokenzr.h"
48
4b6a582b
VZ
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
9a83f860 61 ? wxT("normal")
4b6a582b 62 : weight == wxFONTWEIGHT_BOLD
9a83f860
VZ
63 ? wxT("bold")
64 : wxT("light"),
4b6a582b 65 font->GetStyle() == wxFONTSTYLE_NORMAL
9a83f860
VZ
66 ? wxT("regular")
67 : wxT("italic"),
4b6a582b
VZ
68 font->GetPointSize(),
69 font->GetEncoding());
70
61f24aea 71 wxStrlcpy(buf, s.mb_str(), WXSIZEOF(buf));
4b6a582b
VZ
72 return buf;
73}
74
28953245
SC
75// ----------------------------------------------------------------------------
76// XTI
77// ----------------------------------------------------------------------------
78
79wxBEGIN_ENUM( wxFontFamily )
e765d7ee
SC
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 )
28953245
SC
87wxEND_ENUM( wxFontFamily )
88
89wxBEGIN_ENUM( wxFontStyle )
e765d7ee
SC
90wxENUM_MEMBER( wxFONTSTYLE_NORMAL )
91wxENUM_MEMBER( wxFONTSTYLE_ITALIC )
92wxENUM_MEMBER( wxFONTSTYLE_SLANT )
28953245
SC
93wxEND_ENUM( wxFontStyle )
94
95wxBEGIN_ENUM( wxFontWeight )
e765d7ee
SC
96wxENUM_MEMBER( wxFONTWEIGHT_NORMAL )
97wxENUM_MEMBER( wxFONTWEIGHT_LIGHT )
98wxENUM_MEMBER( wxFONTWEIGHT_BOLD )
28953245
SC
99wxEND_ENUM( wxFontWeight )
100
101wxIMPLEMENT_DYNAMIC_CLASS_WITH_COPY_XTI(wxFont, wxGDIObject, "wx/font.h")
102
e765d7ee
SC
103//WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxFont>)
104
28953245
SC
105wxBEGIN_PROPERTIES_TABLE(wxFont)
106wxPROPERTY( Size,int, SetPointSize, GetPointSize, 12, 0 /*flags*/, \
107 wxT("Helpstring"), wxT("group"))
e765d7ee 108wxPROPERTY( Family, wxFontFamily , SetFamily, GetFamily, (wxFontFamily)wxDEFAULT, \
28953245 109 0 /*flags*/, wxT("Helpstring"), wxT("group")) // wxFontFamily
e765d7ee 110wxPROPERTY( Style, wxFontStyle, SetStyle, GetStyle, (wxFontStyle)wxNORMAL, 0 /*flags*/, \
28953245 111 wxT("Helpstring"), wxT("group")) // wxFontStyle
e765d7ee 112wxPROPERTY( Weight, wxFontWeight, SetWeight, GetWeight, (wxFontWeight)wxNORMAL, 0 /*flags*/, \
28953245
SC
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
e765d7ee 122wxCONSTRUCTOR_6( wxFont, int, Size, wxFontFamily, Family, wxFontStyle, Style, wxFontWeight, Weight, \
28953245
SC
123 bool, Underlined, wxString, Face )
124
125wxEMPTY_HANDLERS_TABLE(wxFont)
126
0c5d3e1c
VZ
127// ============================================================================
128// implementation
129// ============================================================================
130
544229d1
VZ
131// ----------------------------------------------------------------------------
132// helper functions
133// ----------------------------------------------------------------------------
134
b5791cc7 135static inline int flags2Style(int flags)
544229d1 136{
b5791cc7
FM
137 return flags & wxFONTFLAG_ITALIC
138 ? wxFONTSTYLE_ITALIC
139 : flags & wxFONTFLAG_SLANT
140 ? wxFONTSTYLE_SLANT
141 : wxFONTSTYLE_NORMAL;
142}
544229d1 143
b5791cc7
FM
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}
544229d1 152
b5791cc7
FM
153static inline bool flags2Underlined(int flags)
154{
155 return (flags & wxFONTFLAG_UNDERLINED) != 0;
544229d1
VZ
156}
157
0c5d3e1c
VZ
158// ----------------------------------------------------------------------------
159// wxFontBase
160// ----------------------------------------------------------------------------
161
162wxFontEncoding wxFontBase::ms_encodingDefault = wxFONTENCODING_SYSTEM;
163
cafbf6fb
VZ
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,
9a83f860 170 wxT("can't set default encoding to wxFONTENCODING_DEFAULT") );
cafbf6fb
VZ
171
172 ms_encodingDefault = encoding;
173}
174
799ea011
GD
175wxFontBase::~wxFontBase()
176{
177 // this destructor is required for Darwin
178}
179
7beba2fc 180/* static */
0c5d3e1c 181wxFont *wxFontBase::New(int size,
0c14b6c3
FM
182 wxFontFamily family,
183 wxFontStyle style,
184 wxFontWeight weight,
0c5d3e1c
VZ
185 bool underlined,
186 const wxString& face,
187 wxFontEncoding encoding)
188{
189 return new wxFont(size, family, style, weight, underlined, face, encoding);
190}
191
b5791cc7
FM
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)
544229d1 200{
b5791cc7
FM
201 return new wxFont(pixelSize, family, style, weight, underlined,
202 face, encoding);
544229d1
VZ
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,
0c14b6c3 218 wxFontFamily family,
b5791cc7 219 int flags,
544229d1
VZ
220 const wxString& face,
221 wxFontEncoding encoding)
222{
b5791cc7
FM
223 return New(pixelSize, family, flags2Style(flags), flags2Weight(flags),
224 flags2Underlined(flags), face, encoding);
544229d1
VZ
225}
226
227/* static */
b5791cc7 228wxFont *wxFontBase::New(const wxNativeFontInfo& info)
544229d1 229{
b5791cc7
FM
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;
544229d1
VZ
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{
b5791cc7
FM
262 wxCHECK_RET( pixelSize.GetWidth() >= 0 && pixelSize.GetHeight() > 0,
263 "Negative values for the pixel size or zero pixel height are not allowed" );
264
544229d1 265 wxScreenDC dc;
01cb1c26 266
b5791cc7
FM
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.
03647350 270
b5791cc7
FM
271 int largestGood = 0;
272 int smallestBad = 0;
30764ab5 273
b5791cc7
FM
274 bool initialGoodFound = false;
275 bool initialBadFound = false;
7826e2dd 276
b5791cc7
FM
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));
7826e2dd 283
b5791cc7
FM
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);
53f6aab7
VZ
321}
322
9045ad9d 323void wxFontBase::DoSetNativeFontInfo(const wxNativeFontInfo& info)
30764ab5 324{
ab5fe833 325#ifdef wxNO_NATIVE_FONTINFO
30764ab5
VZ
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);
33ac7e6f 333#else
1e6feb95 334 (void)info;
30764ab5
VZ
335#endif
336}
337
7826e2dd
VZ
338wxString wxFontBase::GetNativeFontInfoDesc() const
339{
64932e41
VZ
340 wxCHECK_MSG( IsOk(), wxEmptyString, wxT("invalid font") );
341
7826e2dd 342 wxString fontDesc;
3bf5a59b 343 const wxNativeFontInfo *fontInfo = GetNativeFontInfo();
7826e2dd
VZ
344 if ( fontInfo )
345 {
346 fontDesc = fontInfo->ToString();
dd05139a 347 wxASSERT_MSG(!fontDesc.empty(), wxT("This should be a non-empty string!"));
85ab460e
VZ
348 }
349 else
350 {
7bd236e6 351 wxFAIL_MSG(wxT("Derived class should have created the wxNativeFontInfo!"));
7826e2dd
VZ
352 }
353
354 return fontDesc;
355}
356
ab5fe833
VZ
357wxString wxFontBase::GetNativeFontInfoUserDesc() const
358{
64932e41
VZ
359 wxCHECK_MSG( IsOk(), wxEmptyString, wxT("invalid font") );
360
ab5fe833 361 wxString fontDesc;
3bf5a59b 362 const wxNativeFontInfo *fontInfo = GetNativeFontInfo();
ab5fe833
VZ
363 if ( fontInfo )
364 {
365 fontDesc = fontInfo->ToUserString();
dd05139a 366 wxASSERT_MSG(!fontDesc.empty(), wxT("This should be a non-empty string!"));
85ab460e
VZ
367 }
368 else
369 {
7456f382 370 wxFAIL_MSG(wxT("Derived class should have created the wxNativeFontInfo!"));
ab5fe833
VZ
371 }
372
373 return fontDesc;
374}
375
85ab460e 376bool wxFontBase::SetNativeFontInfo(const wxString& info)
31d1b66e
VZ
377{
378 wxNativeFontInfo fontInfo;
379 if ( !info.empty() && fontInfo.FromString(info) )
380 {
381 SetNativeFontInfo(fontInfo);
85ab460e 382 return true;
31d1b66e 383 }
85ab460e 384
85ab460e 385 return false;
31d1b66e
VZ
386}
387
85ab460e 388bool wxFontBase::SetNativeFontInfoUserDesc(const wxString& info)
ab5fe833
VZ
389{
390 wxNativeFontInfo fontInfo;
391 if ( !info.empty() && fontInfo.FromUserString(info) )
392 {
393 SetNativeFontInfo(fontInfo);
85ab460e 394 return true;
ab5fe833 395 }
85ab460e 396
85ab460e 397 return false;
ab5fe833
VZ
398}
399
0c5d3e1c
VZ
400bool wxFontBase::operator==(const wxFont& font) const
401{
8bf30fe9
VZ
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
a38cd629 404 return IsSameAs(font) ||
8bf30fe9 405 (
70f70818 406 IsOk() == font.IsOk() &&
8bf30fe9 407 GetPointSize() == font.GetPointSize() &&
82d0e7fe
VZ
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__)
cc3de8a3 412 GetPixelSize() == font.GetPixelSize() &&
82d0e7fe 413#endif
8bf30fe9
VZ
414 GetFamily() == font.GetFamily() &&
415 GetStyle() == font.GetStyle() &&
e6adf058 416 GetWeight() == font.GetWeight() &&
8bf30fe9 417 GetUnderlined() == font.GetUnderlined() &&
85ab460e 418 GetFaceName().IsSameAs(font.GetFaceName(), false) &&
8bf30fe9
VZ
419 GetEncoding() == font.GetEncoding()
420 );
0c5d3e1c
VZ
421}
422
59b7da02
VZ
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
0c5d3e1c
VZ
437wxString wxFontBase::GetFamilyString() const
438{
70f70818 439 wxCHECK_MSG( IsOk(), "wxFONTFAMILY_DEFAULT", "invalid font" );
0c5d3e1c
VZ
440
441 switch ( GetFamily() )
442 {
70f70818
FM
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";
f2c1b903 449 case wxFONTFAMILY_UNKNOWN: return "wxFONTFAMILY_UNKNOWN";
70f70818 450 default: return "wxFONTFAMILY_DEFAULT";
0c5d3e1c
VZ
451 }
452}
453
454wxString wxFontBase::GetStyleString() const
455{
70f70818 456 wxCHECK_MSG( IsOk(), "wxFONTSTYLE_DEFAULT", "invalid font" );
0c5d3e1c
VZ
457
458 switch ( GetStyle() )
459 {
70f70818
FM
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";
0c5d3e1c
VZ
464 }
465}
466
467wxString wxFontBase::GetWeightString() const
468{
70f70818 469 wxCHECK_MSG( IsOk(), "wxFONTWEIGHT_DEFAULT", "invalid font" );
0c5d3e1c
VZ
470
471 switch ( GetWeight() )
472 {
70f70818
FM
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";
0c5d3e1c
VZ
477 }
478}
479
ff427585 480bool wxFontBase::SetFaceName(const wxString& facename)
85ab460e 481{
ff427585 482#if wxUSE_FONTENUM
85ab460e
VZ
483 if (!wxFontEnumerator::IsValidFacename(facename))
484 {
70f70818 485 UnRef(); // make IsOk() return false
85ab460e
VZ
486 return false;
487 }
ff427585
VZ
488#else // !wxUSE_FONTENUM
489 wxUnusedVar(facename);
490#endif // wxUSE_FONTENUM/!wxUSE_FONTENUM
85ab460e
VZ
491
492 return true;
493}
494
19da7aaa
VZ
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
f76c3ff6 515 return wxRound(factors[size - wxFONTSIZE_XX_SMALL]*base);
19da7aaa
VZ
516}
517
6e7d2550
VZ
518wxFont& wxFont::MakeBold()
519{
520 SetWeight(wxFONTWEIGHT_BOLD);
521 return *this;
522}
523
524wxFont wxFont::Bold() const
f76c0758
VZ
525{
526 wxFont font(*this);
6e7d2550 527 font.MakeBold();
f76c0758
VZ
528 return font;
529}
530
6e7d2550
VZ
531wxFont& wxFont::MakeItalic()
532{
533 SetStyle(wxFONTSTYLE_ITALIC);
534 return *this;
535}
536
537wxFont wxFont::Italic() const
f76c0758
VZ
538{
539 wxFont font(*this);
801423ee
VZ
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();
f76c0758
VZ
554 return font;
555}
556
6e7d2550
VZ
557wxFont& wxFont::Scale(float x)
558{
559 SetPointSize(int(x*GetPointSize() + 0.5));
560 return *this;
561}
562
563wxFont wxFont::Scaled(float x) const
f76c0758
VZ
564{
565 wxFont font(*this);
6e7d2550 566 font.Scale(x);
f76c0758
VZ
567 return font;
568}
85ab460e 569
30764ab5
VZ
570// ----------------------------------------------------------------------------
571// wxNativeFontInfo
572// ----------------------------------------------------------------------------
573
85ab460e 574// Up to now, there are no native implementations of this function:
ff427585 575void wxNativeFontInfo::SetFaceName(const wxArrayString& facenames)
85ab460e 576{
ff427585 577#if wxUSE_FONTENUM
85ab460e
VZ
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);
ff427585
VZ
591#else // !wxUSE_FONTENUM
592 SetFaceName(facenames[0]);
593#endif // wxUSE_FONTENUM/!wxUSE_FONTENUM
85ab460e
VZ
594}
595
596
ab5fe833
VZ
597#ifdef wxNO_NATIVE_FONTINFO
598
30764ab5
VZ
599// These are the generic forms of FromString()/ToString.
600//
601// convert to/from the string representation: format is
09fcd889 602// version;pointsize;family;style;weight;underlined;facename;encoding
30764ab5
VZ
603
604bool wxNativeFontInfo::FromString(const wxString& s)
605{
606 long l;
607
9a83f860 608 wxStringTokenizer tokenizer(s, wxT(";"));
30764ab5
VZ
609
610 wxString token = tokenizer.GetNextToken();
09fcd889
VZ
611 //
612 // Ignore the version for now
613 //
33ac7e6f 614
09fcd889 615 token = tokenizer.GetNextToken();
30764ab5 616 if ( !token.ToLong(&l) )
a62848fd 617 return false;
30764ab5
VZ
618 pointSize = (int)l;
619
620 token = tokenizer.GetNextToken();
621 if ( !token.ToLong(&l) )
a62848fd 622 return false;
f7b301fa 623 family = (wxFontFamily)l;
30764ab5
VZ
624
625 token = tokenizer.GetNextToken();
626 if ( !token.ToLong(&l) )
a62848fd 627 return false;
ab5fe833 628 style = (wxFontStyle)l;
30764ab5
VZ
629
630 token = tokenizer.GetNextToken();
631 if ( !token.ToLong(&l) )
a62848fd 632 return false;
ab5fe833 633 weight = (wxFontWeight)l;
30764ab5
VZ
634
635 token = tokenizer.GetNextToken();
636 if ( !token.ToLong(&l) )
a62848fd 637 return false;
189e08b4 638 underlined = l != 0;
30764ab5
VZ
639
640 faceName = tokenizer.GetNextToken();
0a9f0ef7
JS
641
642#ifndef __WXMAC__
30764ab5 643 if( !faceName )
a62848fd 644 return false;
0a9f0ef7 645#endif
30764ab5
VZ
646
647 token = tokenizer.GetNextToken();
648 if ( !token.ToLong(&l) )
a62848fd 649 return false;
30764ab5
VZ
650 encoding = (wxFontEncoding)l;
651
a62848fd 652 return true;
30764ab5
VZ
653}
654
655wxString wxNativeFontInfo::ToString() const
656{
657 wxString s;
658
9a83f860 659 s.Printf(wxT("%d;%d;%d;%d;%d;%d;%s;%d"),
09fcd889 660 0, // version
30764ab5
VZ
661 pointSize,
662 family,
ab5fe833
VZ
663 (int)style,
664 (int)weight,
30764ab5
VZ
665 underlined,
666 faceName.GetData(),
667 (int)encoding);
668
669 return s;
670}
671
ab5fe833
VZ
672void wxNativeFontInfo::Init()
673{
3bf5a59b 674 pointSize = 0;
ab5fe833
VZ
675 family = wxFONTFAMILY_DEFAULT;
676 style = wxFONTSTYLE_NORMAL;
677 weight = wxFONTWEIGHT_NORMAL;
a62848fd 678 underlined = false;
ab5fe833
VZ
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
7936354d
VZ
708wxFontFamily wxNativeFontInfo::GetFamily() const
709{
710 return family;
711}
712
ab5fe833
VZ
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
85ab460e 738bool wxNativeFontInfo::SetFaceName(const wxString& facename_)
ab5fe833 739{
f7b301fa 740 faceName = facename_;
85ab460e 741 return true;
ab5fe833
VZ
742}
743
3f1d1373 744void wxNativeFontInfo::SetFamily(wxFontFamily family_)
7936354d
VZ
745{
746 family = family_;
747}
748
ab5fe833
VZ
749void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding_)
750{
751 encoding = encoding_;
752}
753
7826e2dd 754#endif // generic wxNativeFontInfo implementation
30764ab5 755
ab5fe833
VZ
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
f1c40652 761#if defined(wxNO_NATIVE_FONTINFO) || defined(__WXMSW__) || defined (__WXPM__) || defined(__WXOSX__)
ab5fe833
VZ
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 {
85ab460e 771 desc << _("underlined");
ab5fe833
VZ
772 }
773
774 switch ( GetWeight() )
775 {
776 default:
9a83f860 777 wxFAIL_MSG( wxT("unknown font weight") );
ab5fe833
VZ
778 // fall through
779
780 case wxFONTWEIGHT_NORMAL:
781 break;
782
783 case wxFONTWEIGHT_LIGHT:
85ab460e 784 desc << _(" light");
ab5fe833
VZ
785 break;
786
787 case wxFONTWEIGHT_BOLD:
85ab460e 788 desc << _(" bold");
ab5fe833
VZ
789 break;
790 }
791
792 switch ( GetStyle() )
793 {
794 default:
9a83f860 795 wxFAIL_MSG( wxT("unknown font style") );
ab5fe833
VZ
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:
85ab460e 804 desc << _(" italic");
ab5fe833
VZ
805 break;
806 }
807
a9249b2e
VZ
808 wxString face = GetFaceName();
809 if ( !face.empty() )
ab5fe833 810 {
c1ab2be0
FM
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
9a83f860 821 desc << wxT(" '") << face << _("'");
c1ab2be0
FM
822 }
823 else
9a83f860 824 desc << wxT(' ') << face;
ab5fe833 825 }
1a2ca1d6
VZ
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 }
ab5fe833 867
a9249b2e
VZ
868 int size = GetPointSize();
869 if ( size != wxNORMAL_FONT->GetPointSize() )
ab5fe833 870 {
9a83f860 871 desc << wxT(' ') << size;
ab5fe833 872 }
a9249b2e 873
e7e52b6d 874#if wxUSE_FONTMAP
a9249b2e
VZ
875 wxFontEncoding enc = GetEncoding();
876 if ( enc != wxFONTENCODING_DEFAULT && enc != wxFONTENCODING_SYSTEM )
877 {
9a83f860 878 desc << wxT(' ') << wxFontMapper::GetEncodingName(enc);
a9249b2e 879 }
e7e52b6d 880#endif // wxUSE_FONTMAP
a9249b2e 881
85ab460e 882 return desc.Strip(wxString::both).MakeLower();
ab5fe833
VZ
883}
884
885bool wxNativeFontInfo::FromUserString(const wxString& s)
886{
887 // reset to the default state
888 Init();
889
c1ab2be0
FM
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);
c1ab2be0 894
ab5fe833 895 // parse a more or less free form string
9a83f860 896 wxStringTokenizer tokenizer(toparse, wxT(";, "), wxTOKEN_STRTOK);
ab5fe833
VZ
897
898 wxString face;
899 unsigned long size;
77f15ffe
VS
900 bool weightfound = false, pointsizefound = false;
901#if wxUSE_FONTMAP
902 bool encodingfound = false;
903#endif
c1ab2be0 904 bool insideQuotes = false;
ab5fe833
VZ
905
906 while ( tokenizer.HasMoreTokens() )
907 {
908 wxString token = tokenizer.GetNextToken();
909
910 // normalize it
a62848fd 911 token.Trim(true).Trim(false).MakeLower();
c1ab2be0
FM
912 if (insideQuotes)
913 {
03647350 914 if (token.StartsWith("'") ||
c1ab2be0
FM
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 }
ab5fe833
VZ
934
935 // look for the known tokens
c1ab2be0
FM
936 if ( insideQuotes )
937 {
938 // only the facename may be quoted:
939 face += " " + token;
940 continue;
941 }
9a83f860 942 if ( token == wxT("underlined") || token == _("underlined") )
ab5fe833 943 {
a62848fd 944 SetUnderlined(true);
ab5fe833 945 }
9a83f860 946 else if ( token == wxT("light") || token == _("light") )
ab5fe833
VZ
947 {
948 SetWeight(wxFONTWEIGHT_LIGHT);
85ab460e 949 weightfound = true;
ab5fe833 950 }
9a83f860 951 else if ( token == wxT("bold") || token == _("bold") )
ab5fe833
VZ
952 {
953 SetWeight(wxFONTWEIGHT_BOLD);
85ab460e 954 weightfound = true;
ab5fe833 955 }
9a83f860 956 else if ( token == wxT("italic") || token == _("italic") )
ab5fe833
VZ
957 {
958 SetStyle(wxFONTSTYLE_ITALIC);
959 }
960 else if ( token.ToULong(&size) )
961 {
a9249b2e 962 SetPointSize(size);
85ab460e 963 pointsizefound = true;
ab5fe833 964 }
85ab460e
VZ
965 else
966 {
e7e52b6d 967#if wxUSE_FONTMAP
85ab460e
VZ
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
ab5fe833
VZ
972 {
973 SetEncoding(encoding);
85ab460e 974 encodingfound = true;
ab5fe833 975 }
85ab460e 976 else
ab5fe833 977 {
85ab460e
VZ
978#endif // wxUSE_FONTMAP
979
980 // assume it is the face name
ab5fe833
VZ
981 if ( !face.empty() )
982 {
9a83f860 983 face += wxT(' ');
ab5fe833
VZ
984 }
985
986 face += token;
987
988 // skip the code which resets face below
989 continue;
85ab460e
VZ
990
991#if wxUSE_FONTMAP
992 }
993#endif // wxUSE_FONTMAP
ab5fe833
VZ
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 {
1a2ca1d6
VZ
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;
03647350 1020
1a2ca1d6
VZ
1021 SetFamily(family);
1022 }
85ab460e 1023 // NB: the check on the facename is implemented in wxFontBase::SetFaceName
4c51a665 1024 // and not in wxNativeFontInfo::SetFaceName thus we need to explicitly
85ab460e 1025 // call here wxFontEnumerator::IsValidFacename
1a2ca1d6 1026 else if (
ff427585
VZ
1027#if wxUSE_FONTENUM
1028 !wxFontEnumerator::IsValidFacename(face) ||
1029#endif // wxUSE_FONTENUM
1030 !SetFaceName(face) )
1031 {
85ab460e 1032 SetFaceName(wxNORMAL_FONT->GetFaceName());
ff427585
VZ
1033 }
1034
ab5fe833
VZ
1035 face.clear();
1036 }
1037 }
1038
1039 // we might not have flushed it inside the loop
1040 if ( !face.empty() )
1041 {
85ab460e 1042 // NB: the check on the facename is implemented in wxFontBase::SetFaceName
4c51a665 1043 // and not in wxNativeFontInfo::SetFaceName thus we need to explicitly
85ab460e 1044 // call here wxFontEnumerator::IsValidFacename
ff427585
VZ
1045 if (
1046#if wxUSE_FONTENUM
1047 !wxFontEnumerator::IsValidFacename(face) ||
1048#endif // wxUSE_FONTENUM
1049 !SetFaceName(face) )
1050 {
1051 SetFaceName(wxNORMAL_FONT->GetFaceName());
1052 }
ab5fe833
VZ
1053 }
1054
85ab460e
VZ
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
a62848fd 1069 return true;
ab5fe833
VZ
1070}
1071
0eb529d9 1072#endif // generic or wxMSW or wxOS2
fc9361e3
VZ
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{
9a83f860 1084 wxCHECK_MSG( font, false, wxT("NULL output parameter") );
fc9361e3
VZ
1085
1086 if ( str.empty() )
1087 {
1088 *font = wxNullFont;
1089 return true;
1090 }
1091
1092 return font->SetNativeFontInfo(str);
1093}
1094
1095