]> git.saurik.com Git - wxWidgets.git/blame - src/common/fontcmn.cpp
minor refactoring of menu UpdateUI handling
[wxWidgets.git] / src / common / fontcmn.cpp
CommitLineData
8f7fa6f8 1/////////////////////////////////////////////////////////////////////////////
0c5d3e1c
VZ
2// Name: 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$
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__
01610529 24#pragma hdrstop
0c5d3e1c
VZ
25#endif
26
27#ifndef WX_PRECOMP
452aa069 28 #include "wx/dc.h"
9342fdbe
VZ
29 #include "wx/font.h"
30 #include "wx/intl.h"
31 #include "wx/dcscreen.h"
0c5d3e1c
VZ
32#endif // WX_PRECOMP
33
09fcd889 34#include "wx/gdicmn.h"
1c193821 35
82ef81ed 36#if defined(__WXMSW__)
1c193821
JS
37 #include "wx/msw/private.h" // includes windows.h for LOGFONT
38 #include "wx/msw/winundef.h"
39#endif
40
76e23cdb 41#include "wx/fontutil.h" // for wxNativeFontInfo
ab5fe833 42#include "wx/fontmap.h"
76e23cdb 43
30764ab5
VZ
44#include "wx/tokenzr.h"
45
0c5d3e1c
VZ
46// ============================================================================
47// implementation
48// ============================================================================
49
544229d1
VZ
50// ----------------------------------------------------------------------------
51// helper functions
52// ----------------------------------------------------------------------------
53
8093538c 54static void AdjustFontSize(wxFont& font, wxDC& dc, const wxSize& pixelSize)
544229d1
VZ
55{
56 int currentSize = font.GetPointSize();
8093538c
VZ
57 int largestGood = 0;
58 int smallestBad = 0;
544229d1
VZ
59
60 bool initialGoodFound = false;
61 bool initialBadFound = false;
62
63 while (currentSize > 0)
64 {
65 dc.SetFont(font);
66
67 // if currentSize (in points) results in a font that is smaller
68 // than required by pixelSize it is considered a good size
69 if (dc.GetCharHeight() <= pixelSize.GetHeight() &&
70 (!pixelSize.GetWidth() ||
71 dc.GetCharWidth() <= pixelSize.GetWidth()))
72 {
73 largestGood = currentSize;
74 initialGoodFound = true;
75 }
76 else
77 {
78 smallestBad = currentSize;
79 initialBadFound = true;
80 }
81 if (!initialGoodFound)
82 {
83 currentSize /= 2;
84 }
85 else if (!initialBadFound)
86 {
87 currentSize *= 2;
88 }
89 else
90 {
91 int distance = smallestBad - largestGood;
92 if (distance == 1)
93 break;
94
95 currentSize = largestGood + distance / 2;
96 }
97
98 font.SetPointSize(currentSize);
99 }
100
101 if (currentSize != largestGood)
102 font.SetPointSize(largestGood);
103}
104
0c5d3e1c
VZ
105// ----------------------------------------------------------------------------
106// wxFontBase
107// ----------------------------------------------------------------------------
108
109wxFontEncoding wxFontBase::ms_encodingDefault = wxFONTENCODING_SYSTEM;
110
cafbf6fb
VZ
111/* static */
112void wxFontBase::SetDefaultEncoding(wxFontEncoding encoding)
113{
114 // GetDefaultEncoding() should return something != wxFONTENCODING_DEFAULT
115 // and, besides, using this value here doesn't make any sense
116 wxCHECK_RET( encoding != wxFONTENCODING_DEFAULT,
117 _T("can't set default encoding to wxFONTENCODING_DEFAULT") );
118
119 ms_encodingDefault = encoding;
120}
121
799ea011
GD
122wxFontBase::~wxFontBase()
123{
124 // this destructor is required for Darwin
125}
126
7beba2fc 127/* static */
0c5d3e1c
VZ
128wxFont *wxFontBase::New(int size,
129 int family,
130 int style,
131 int weight,
132 bool underlined,
133 const wxString& face,
134 wxFontEncoding encoding)
135{
136 return new wxFont(size, family, style, weight, underlined, face, encoding);
137}
138
544229d1 139static inline int flags2Style(int flags)
01cb1c26 140{
544229d1 141 return flags & wxFONTFLAG_ITALIC
01cb1c26
VZ
142 ? wxFONTSTYLE_ITALIC
143 : flags & wxFONTFLAG_SLANT
144 ? wxFONTSTYLE_SLANT
544229d1
VZ
145 : wxFONTSTYLE_NORMAL;
146}
147
148static inline int flags2Weight(int flags)
149{
150 return flags & wxFONTFLAG_LIGHT
01cb1c26
VZ
151 ? wxFONTWEIGHT_LIGHT
152 : flags & wxFONTFLAG_BOLD
153 ? wxFONTWEIGHT_BOLD
544229d1
VZ
154 : wxFONTWEIGHT_NORMAL;
155}
156
157static inline bool flags2Underlined(int flags)
158{
159 return (flags & wxFONTFLAG_UNDERLINED) != 0;
160}
161
162/* static */
163wxFont *wxFontBase::New(int pointSize,
164 wxFontFamily family,
165 int flags,
166 const wxString& face,
167 wxFontEncoding encoding)
168{
169 return New(pointSize, family, flags2Style(flags), flags2Weight(flags),
170 flags2Underlined(flags), face, encoding);
171}
172
173/* static */
174wxFont *wxFontBase::New(const wxSize& pixelSize,
175 int family,
176 int style,
177 int weight,
178 bool underlined,
179 const wxString& face,
180 wxFontEncoding encoding)
181{
182#if defined(__WXMSW__)
183 return new wxFont(pixelSize, family, style, weight, underlined,
184 face, encoding);
185#else
9342fdbe 186 wxFont *self = New(10, family, style, weight, underlined, face, encoding);
544229d1 187 wxScreenDC dc;
9342fdbe
VZ
188 AdjustFontSize(*(wxFont *)self, dc, pixelSize);
189 return self;
544229d1
VZ
190#endif
191}
192
193/* static */
194wxFont *wxFontBase::New(const wxSize& pixelSize,
195 wxFontFamily family,
196 int flags,
197 const wxString& face,
198 wxFontEncoding encoding)
199{
200 return New(pixelSize, family, flags2Style(flags), flags2Weight(flags),
201 flags2Underlined(flags), face, encoding);
202}
203
204wxSize wxFontBase::GetPixelSize() const
205{
206 wxScreenDC dc;
207 dc.SetFont(*(wxFont *)this);
208 return wxSize(dc.GetCharWidth(), dc.GetCharHeight());
209}
210
211bool wxFontBase::IsUsingSizeInPixels() const
212{
213 return false;
214}
215
216void wxFontBase::SetPixelSize( const wxSize& pixelSize )
217{
218 wxScreenDC dc;
219 AdjustFontSize(*(wxFont *)this, dc, pixelSize);
01cb1c26
VZ
220}
221
30764ab5
VZ
222/* static */
223wxFont *wxFontBase::New(const wxNativeFontInfo& info)
224{
225 return new wxFont(info);
226}
227
7826e2dd
VZ
228/* static */
229wxFont *wxFontBase::New(const wxString& strNativeFontDesc)
30764ab5 230{
30764ab5 231 wxNativeFontInfo fontInfo;
7826e2dd 232 if ( !fontInfo.FromString(strNativeFontDesc) )
09fcd889 233 return new wxFont(*wxNORMAL_FONT);
7826e2dd
VZ
234
235 return New(fontInfo);
236}
237
53f6aab7
VZ
238bool wxFontBase::IsFixedWidth() const
239{
240 return GetFamily() == wxFONTFAMILY_TELETYPE;
241}
242
9045ad9d 243void wxFontBase::DoSetNativeFontInfo(const wxNativeFontInfo& info)
30764ab5 244{
ab5fe833 245#ifdef wxNO_NATIVE_FONTINFO
30764ab5
VZ
246 SetPointSize(info.pointSize);
247 SetFamily(info.family);
248 SetStyle(info.style);
249 SetWeight(info.weight);
250 SetUnderlined(info.underlined);
251 SetFaceName(info.faceName);
252 SetEncoding(info.encoding);
33ac7e6f 253#else
1e6feb95 254 (void)info;
30764ab5
VZ
255#endif
256}
257
7826e2dd
VZ
258wxString wxFontBase::GetNativeFontInfoDesc() const
259{
260 wxString fontDesc;
3bf5a59b 261 const wxNativeFontInfo *fontInfo = GetNativeFontInfo();
7826e2dd
VZ
262 if ( fontInfo )
263 {
264 fontDesc = fontInfo->ToString();
7826e2dd
VZ
265 }
266
267 return fontDesc;
268}
269
ab5fe833
VZ
270wxString wxFontBase::GetNativeFontInfoUserDesc() const
271{
272 wxString fontDesc;
3bf5a59b 273 const wxNativeFontInfo *fontInfo = GetNativeFontInfo();
ab5fe833
VZ
274 if ( fontInfo )
275 {
276 fontDesc = fontInfo->ToUserString();
ab5fe833
VZ
277 }
278
279 return fontDesc;
280}
281
31d1b66e
VZ
282void wxFontBase::SetNativeFontInfo(const wxString& info)
283{
284 wxNativeFontInfo fontInfo;
285 if ( !info.empty() && fontInfo.FromString(info) )
286 {
287 SetNativeFontInfo(fontInfo);
288 }
289}
290
ab5fe833
VZ
291void wxFontBase::SetNativeFontInfoUserDesc(const wxString& info)
292{
293 wxNativeFontInfo fontInfo;
294 if ( !info.empty() && fontInfo.FromUserString(info) )
295 {
296 SetNativeFontInfo(fontInfo);
297 }
298}
299
0c5d3e1c
VZ
300wxFont& wxFont::operator=(const wxFont& font)
301{
302 if ( this != &font )
303 Ref(font);
304
305 return (wxFont &)*this;
306}
307
0c5d3e1c
VZ
308bool wxFontBase::operator==(const wxFont& font) const
309{
8bf30fe9
VZ
310 // either it is the same font, i.e. they share the same common data or they
311 // have different ref datas but still describe the same font
312 return GetFontData() == font.GetFontData() ||
313 (
314 Ok() == font.Ok() &&
315 GetPointSize() == font.GetPointSize() &&
316 GetFamily() == font.GetFamily() &&
317 GetStyle() == font.GetStyle() &&
e6adf058 318 GetWeight() == font.GetWeight() &&
8bf30fe9
VZ
319 GetUnderlined() == font.GetUnderlined() &&
320 GetFaceName() == font.GetFaceName() &&
321 GetEncoding() == font.GetEncoding()
322 );
0c5d3e1c
VZ
323}
324
325bool wxFontBase::operator!=(const wxFont& font) const
326{
8bf30fe9 327 return !(*this == font);
0c5d3e1c
VZ
328}
329
330wxString wxFontBase::GetFamilyString() const
331{
223d09f6 332 wxCHECK_MSG( Ok(), wxT("wxDEFAULT"), wxT("invalid font") );
0c5d3e1c
VZ
333
334 switch ( GetFamily() )
335 {
223d09f6
KB
336 case wxDECORATIVE: return wxT("wxDECORATIVE");
337 case wxROMAN: return wxT("wxROMAN");
338 case wxSCRIPT: return wxT("wxSCRIPT");
339 case wxSWISS: return wxT("wxSWISS");
340 case wxMODERN: return wxT("wxMODERN");
341 case wxTELETYPE: return wxT("wxTELETYPE");
342 default: return wxT("wxDEFAULT");
0c5d3e1c
VZ
343 }
344}
345
346wxString wxFontBase::GetStyleString() const
347{
223d09f6 348 wxCHECK_MSG( Ok(), wxT("wxDEFAULT"), wxT("invalid font") );
0c5d3e1c
VZ
349
350 switch ( GetStyle() )
351 {
223d09f6
KB
352 case wxNORMAL: return wxT("wxNORMAL");
353 case wxSLANT: return wxT("wxSLANT");
354 case wxITALIC: return wxT("wxITALIC");
355 default: return wxT("wxDEFAULT");
0c5d3e1c
VZ
356 }
357}
358
359wxString wxFontBase::GetWeightString() const
360{
223d09f6 361 wxCHECK_MSG( Ok(), wxT("wxDEFAULT"), wxT("invalid font") );
0c5d3e1c
VZ
362
363 switch ( GetWeight() )
364 {
223d09f6
KB
365 case wxNORMAL: return wxT("wxNORMAL");
366 case wxBOLD: return wxT("wxBOLD");
367 case wxLIGHT: return wxT("wxLIGHT");
368 default: return wxT("wxDEFAULT");
0c5d3e1c
VZ
369 }
370}
371
30764ab5
VZ
372// ----------------------------------------------------------------------------
373// wxNativeFontInfo
374// ----------------------------------------------------------------------------
375
ab5fe833
VZ
376#ifdef wxNO_NATIVE_FONTINFO
377
30764ab5
VZ
378// These are the generic forms of FromString()/ToString.
379//
380// convert to/from the string representation: format is
09fcd889 381// version;pointsize;family;style;weight;underlined;facename;encoding
30764ab5
VZ
382
383bool wxNativeFontInfo::FromString(const wxString& s)
384{
385 long l;
386
387 wxStringTokenizer tokenizer(s, _T(";"));
388
389 wxString token = tokenizer.GetNextToken();
09fcd889
VZ
390 //
391 // Ignore the version for now
392 //
33ac7e6f 393
09fcd889 394 token = tokenizer.GetNextToken();
30764ab5 395 if ( !token.ToLong(&l) )
a62848fd 396 return false;
30764ab5
VZ
397 pointSize = (int)l;
398
399 token = tokenizer.GetNextToken();
400 if ( !token.ToLong(&l) )
a62848fd 401 return false;
f7b301fa 402 family = (wxFontFamily)l;
30764ab5
VZ
403
404 token = tokenizer.GetNextToken();
405 if ( !token.ToLong(&l) )
a62848fd 406 return false;
ab5fe833 407 style = (wxFontStyle)l;
30764ab5
VZ
408
409 token = tokenizer.GetNextToken();
410 if ( !token.ToLong(&l) )
a62848fd 411 return false;
ab5fe833 412 weight = (wxFontWeight)l;
30764ab5
VZ
413
414 token = tokenizer.GetNextToken();
415 if ( !token.ToLong(&l) )
a62848fd 416 return false;
189e08b4 417 underlined = l != 0;
30764ab5
VZ
418
419 faceName = tokenizer.GetNextToken();
0a9f0ef7
JS
420
421#ifndef __WXMAC__
30764ab5 422 if( !faceName )
a62848fd 423 return false;
0a9f0ef7 424#endif
30764ab5
VZ
425
426 token = tokenizer.GetNextToken();
427 if ( !token.ToLong(&l) )
a62848fd 428 return false;
30764ab5
VZ
429 encoding = (wxFontEncoding)l;
430
a62848fd 431 return true;
30764ab5
VZ
432}
433
434wxString wxNativeFontInfo::ToString() const
435{
436 wxString s;
437
09fcd889
VZ
438 s.Printf(_T("%d;%d;%d;%d;%d;%d;%s;%d"),
439 0, // version
30764ab5
VZ
440 pointSize,
441 family,
ab5fe833
VZ
442 (int)style,
443 (int)weight,
30764ab5
VZ
444 underlined,
445 faceName.GetData(),
446 (int)encoding);
447
448 return s;
449}
450
ab5fe833
VZ
451void wxNativeFontInfo::Init()
452{
3bf5a59b 453 pointSize = 0;
ab5fe833
VZ
454 family = wxFONTFAMILY_DEFAULT;
455 style = wxFONTSTYLE_NORMAL;
456 weight = wxFONTWEIGHT_NORMAL;
a62848fd 457 underlined = false;
ab5fe833
VZ
458 faceName.clear();
459 encoding = wxFONTENCODING_DEFAULT;
460}
461
462int wxNativeFontInfo::GetPointSize() const
463{
464 return pointSize;
465}
466
467wxFontStyle wxNativeFontInfo::GetStyle() const
468{
469 return style;
470}
471
472wxFontWeight wxNativeFontInfo::GetWeight() const
473{
474 return weight;
475}
476
477bool wxNativeFontInfo::GetUnderlined() const
478{
479 return underlined;
480}
481
482wxString wxNativeFontInfo::GetFaceName() const
483{
484 return faceName;
485}
486
7936354d
VZ
487wxFontFamily wxNativeFontInfo::GetFamily() const
488{
489 return family;
490}
491
ab5fe833
VZ
492wxFontEncoding wxNativeFontInfo::GetEncoding() const
493{
494 return encoding;
495}
496
497void wxNativeFontInfo::SetPointSize(int pointsize)
498{
499 pointSize = pointsize;
500}
501
502void wxNativeFontInfo::SetStyle(wxFontStyle style_)
503{
504 style = style_;
505}
506
507void wxNativeFontInfo::SetWeight(wxFontWeight weight_)
508{
509 weight = weight_;
510}
511
512void wxNativeFontInfo::SetUnderlined(bool underlined_)
513{
514 underlined = underlined_;
515}
516
fbfb8bcc 517void wxNativeFontInfo::SetFaceName(const wxString& facename_)
ab5fe833 518{
f7b301fa 519 faceName = facename_;
ab5fe833
VZ
520}
521
3f1d1373 522void wxNativeFontInfo::SetFamily(wxFontFamily family_)
7936354d
VZ
523{
524 family = family_;
525}
526
ab5fe833
VZ
527void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding_)
528{
529 encoding = encoding_;
530}
531
7826e2dd 532#endif // generic wxNativeFontInfo implementation
30764ab5 533
ab5fe833
VZ
534// conversion to/from user-readable string: this is used in the generic
535// versions and under MSW as well because there is no standard font description
536// format there anyhow (but there is a well-defined standard for X11 fonts used
537// by wxGTK and wxMotif)
538
0eb529d9 539#if defined(wxNO_NATIVE_FONTINFO) || defined(__WXMSW__) || defined (__WXPM__)
ab5fe833
VZ
540
541wxString wxNativeFontInfo::ToUserString() const
542{
543 wxString desc;
544
545 // first put the adjectives, if any - this is English-centric, of course,
546 // but what else can we do?
547 if ( GetUnderlined() )
548 {
549 desc << _("underlined ");
550 }
551
552 switch ( GetWeight() )
553 {
554 default:
555 wxFAIL_MSG( _T("unknown font weight") );
556 // fall through
557
558 case wxFONTWEIGHT_NORMAL:
559 break;
560
561 case wxFONTWEIGHT_LIGHT:
562 desc << _("light ");
563 break;
564
565 case wxFONTWEIGHT_BOLD:
566 desc << _("bold ");
567 break;
568 }
569
570 switch ( GetStyle() )
571 {
572 default:
573 wxFAIL_MSG( _T("unknown font style") );
574 // fall through
575
576 case wxFONTSTYLE_NORMAL:
577 break;
578
579 // we don't distinguish between the two for now anyhow...
580 case wxFONTSTYLE_ITALIC:
581 case wxFONTSTYLE_SLANT:
a9249b2e 582 desc << _("italic");
ab5fe833
VZ
583 break;
584 }
585
a9249b2e
VZ
586 wxString face = GetFaceName();
587 if ( !face.empty() )
ab5fe833 588 {
a9249b2e 589 desc << _T(' ') << face;
ab5fe833
VZ
590 }
591
a9249b2e
VZ
592 int size = GetPointSize();
593 if ( size != wxNORMAL_FONT->GetPointSize() )
ab5fe833 594 {
a9249b2e 595 desc << _T(' ') << size;
ab5fe833 596 }
a9249b2e 597
e7e52b6d 598#if wxUSE_FONTMAP
a9249b2e
VZ
599 wxFontEncoding enc = GetEncoding();
600 if ( enc != wxFONTENCODING_DEFAULT && enc != wxFONTENCODING_SYSTEM )
601 {
2a1f999f 602 desc << _T(' ') << wxFontMapper::GetEncodingName(enc);
a9249b2e 603 }
e7e52b6d 604#endif // wxUSE_FONTMAP
a9249b2e
VZ
605
606 return desc;
ab5fe833
VZ
607}
608
609bool wxNativeFontInfo::FromUserString(const wxString& s)
610{
611 // reset to the default state
612 Init();
613
614 // parse a more or less free form string
615 //
616 // TODO: we should handle at least the quoted facenames
617 wxStringTokenizer tokenizer(s, _T(";, "), wxTOKEN_STRTOK);
618
619 wxString face;
620 unsigned long size;
e7e52b6d
VZ
621
622#if wxUSE_FONTMAP
ab5fe833 623 wxFontEncoding encoding;
e7e52b6d 624#endif // wxUSE_FONTMAP
ab5fe833
VZ
625
626 while ( tokenizer.HasMoreTokens() )
627 {
628 wxString token = tokenizer.GetNextToken();
629
630 // normalize it
a62848fd 631 token.Trim(true).Trim(false).MakeLower();
ab5fe833
VZ
632
633 // look for the known tokens
634 if ( token == _T("underlined") || token == _("underlined") )
635 {
a62848fd 636 SetUnderlined(true);
ab5fe833
VZ
637 }
638 else if ( token == _T("light") || token == _("light") )
639 {
640 SetWeight(wxFONTWEIGHT_LIGHT);
641 }
642 else if ( token == _T("bold") || token == _("bold") )
643 {
644 SetWeight(wxFONTWEIGHT_BOLD);
645 }
646 else if ( token == _T("italic") || token == _("italic") )
647 {
648 SetStyle(wxFONTSTYLE_ITALIC);
649 }
650 else if ( token.ToULong(&size) )
651 {
a9249b2e 652 SetPointSize(size);
ab5fe833 653 }
e7e52b6d 654#if wxUSE_FONTMAP
a62848fd 655 else if ( (encoding = wxFontMapper::Get()->CharsetToEncoding(token, false))
ab5fe833
VZ
656 != wxFONTENCODING_DEFAULT )
657 {
658 SetEncoding(encoding);
659 }
e7e52b6d 660#endif // wxUSE_FONTMAP
ab5fe833
VZ
661 else // assume it is the face name
662 {
663 if ( !face.empty() )
664 {
665 face += _T(' ');
666 }
667
668 face += token;
669
670 // skip the code which resets face below
671 continue;
672 }
673
674 // if we had had the facename, we shouldn't continue appending tokens
675 // to it (i.e. "foo bold bar" shouldn't result in the facename "foo
676 // bar")
677 if ( !face.empty() )
678 {
679 SetFaceName(face);
680 face.clear();
681 }
682 }
683
684 // we might not have flushed it inside the loop
685 if ( !face.empty() )
686 {
687 SetFaceName(face);
688 }
689
a62848fd 690 return true;
ab5fe833
VZ
691}
692
0eb529d9 693#endif // generic or wxMSW or wxOS2
ab5fe833 694