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