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