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