]> git.saurik.com Git - wxWidgets.git/blame - src/common/fontcmn.cpp
fix recently introduced memory leak of m_conv (bug 1466559)
[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{
d141b218 56 int currentSize = 0;
8093538c
VZ
57 int largestGood = 0;
58 int smallestBad = 0;
544229d1
VZ
59
60 bool initialGoodFound = false;
61 bool initialBadFound = false;
62
d141b218
DS
63 // NB: this assignment was separated from the variable definition
64 // in order to fix a gcc v3.3.3 compiler crash
bf26e9e0 65 currentSize = font.GetPointSize();
544229d1
VZ
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
303bool wxFontBase::operator==(const wxFont& font) const
304{
8bf30fe9
VZ
305 // either it is the same font, i.e. they share the same common data or they
306 // have different ref datas but still describe the same font
307 return GetFontData() == font.GetFontData() ||
308 (
309 Ok() == font.Ok() &&
310 GetPointSize() == font.GetPointSize() &&
311 GetFamily() == font.GetFamily() &&
312 GetStyle() == font.GetStyle() &&
e6adf058 313 GetWeight() == font.GetWeight() &&
8bf30fe9
VZ
314 GetUnderlined() == font.GetUnderlined() &&
315 GetFaceName() == font.GetFaceName() &&
316 GetEncoding() == font.GetEncoding()
317 );
0c5d3e1c
VZ
318}
319
320bool wxFontBase::operator!=(const wxFont& font) const
321{
8bf30fe9 322 return !(*this == font);
0c5d3e1c
VZ
323}
324
325wxString wxFontBase::GetFamilyString() const
326{
223d09f6 327 wxCHECK_MSG( Ok(), wxT("wxDEFAULT"), wxT("invalid font") );
0c5d3e1c
VZ
328
329 switch ( GetFamily() )
330 {
223d09f6
KB
331 case wxDECORATIVE: return wxT("wxDECORATIVE");
332 case wxROMAN: return wxT("wxROMAN");
333 case wxSCRIPT: return wxT("wxSCRIPT");
334 case wxSWISS: return wxT("wxSWISS");
335 case wxMODERN: return wxT("wxMODERN");
336 case wxTELETYPE: return wxT("wxTELETYPE");
337 default: return wxT("wxDEFAULT");
0c5d3e1c
VZ
338 }
339}
340
341wxString wxFontBase::GetStyleString() const
342{
223d09f6 343 wxCHECK_MSG( Ok(), wxT("wxDEFAULT"), wxT("invalid font") );
0c5d3e1c
VZ
344
345 switch ( GetStyle() )
346 {
223d09f6
KB
347 case wxNORMAL: return wxT("wxNORMAL");
348 case wxSLANT: return wxT("wxSLANT");
349 case wxITALIC: return wxT("wxITALIC");
350 default: return wxT("wxDEFAULT");
0c5d3e1c
VZ
351 }
352}
353
354wxString wxFontBase::GetWeightString() const
355{
223d09f6 356 wxCHECK_MSG( Ok(), wxT("wxDEFAULT"), wxT("invalid font") );
0c5d3e1c
VZ
357
358 switch ( GetWeight() )
359 {
223d09f6
KB
360 case wxNORMAL: return wxT("wxNORMAL");
361 case wxBOLD: return wxT("wxBOLD");
362 case wxLIGHT: return wxT("wxLIGHT");
363 default: return wxT("wxDEFAULT");
0c5d3e1c
VZ
364 }
365}
366
30764ab5
VZ
367// ----------------------------------------------------------------------------
368// wxNativeFontInfo
369// ----------------------------------------------------------------------------
370
ab5fe833
VZ
371#ifdef wxNO_NATIVE_FONTINFO
372
30764ab5
VZ
373// These are the generic forms of FromString()/ToString.
374//
375// convert to/from the string representation: format is
09fcd889 376// version;pointsize;family;style;weight;underlined;facename;encoding
30764ab5
VZ
377
378bool wxNativeFontInfo::FromString(const wxString& s)
379{
380 long l;
381
382 wxStringTokenizer tokenizer(s, _T(";"));
383
384 wxString token = tokenizer.GetNextToken();
09fcd889
VZ
385 //
386 // Ignore the version for now
387 //
33ac7e6f 388
09fcd889 389 token = tokenizer.GetNextToken();
30764ab5 390 if ( !token.ToLong(&l) )
a62848fd 391 return false;
30764ab5
VZ
392 pointSize = (int)l;
393
394 token = tokenizer.GetNextToken();
395 if ( !token.ToLong(&l) )
a62848fd 396 return false;
f7b301fa 397 family = (wxFontFamily)l;
30764ab5
VZ
398
399 token = tokenizer.GetNextToken();
400 if ( !token.ToLong(&l) )
a62848fd 401 return false;
ab5fe833 402 style = (wxFontStyle)l;
30764ab5
VZ
403
404 token = tokenizer.GetNextToken();
405 if ( !token.ToLong(&l) )
a62848fd 406 return false;
ab5fe833 407 weight = (wxFontWeight)l;
30764ab5
VZ
408
409 token = tokenizer.GetNextToken();
410 if ( !token.ToLong(&l) )
a62848fd 411 return false;
189e08b4 412 underlined = l != 0;
30764ab5
VZ
413
414 faceName = tokenizer.GetNextToken();
0a9f0ef7
JS
415
416#ifndef __WXMAC__
30764ab5 417 if( !faceName )
a62848fd 418 return false;
0a9f0ef7 419#endif
30764ab5
VZ
420
421 token = tokenizer.GetNextToken();
422 if ( !token.ToLong(&l) )
a62848fd 423 return false;
30764ab5
VZ
424 encoding = (wxFontEncoding)l;
425
a62848fd 426 return true;
30764ab5
VZ
427}
428
429wxString wxNativeFontInfo::ToString() const
430{
431 wxString s;
432
09fcd889
VZ
433 s.Printf(_T("%d;%d;%d;%d;%d;%d;%s;%d"),
434 0, // version
30764ab5
VZ
435 pointSize,
436 family,
ab5fe833
VZ
437 (int)style,
438 (int)weight,
30764ab5
VZ
439 underlined,
440 faceName.GetData(),
441 (int)encoding);
442
443 return s;
444}
445
ab5fe833
VZ
446void wxNativeFontInfo::Init()
447{
3bf5a59b 448 pointSize = 0;
ab5fe833
VZ
449 family = wxFONTFAMILY_DEFAULT;
450 style = wxFONTSTYLE_NORMAL;
451 weight = wxFONTWEIGHT_NORMAL;
a62848fd 452 underlined = false;
ab5fe833
VZ
453 faceName.clear();
454 encoding = wxFONTENCODING_DEFAULT;
455}
456
457int wxNativeFontInfo::GetPointSize() const
458{
459 return pointSize;
460}
461
462wxFontStyle wxNativeFontInfo::GetStyle() const
463{
464 return style;
465}
466
467wxFontWeight wxNativeFontInfo::GetWeight() const
468{
469 return weight;
470}
471
472bool wxNativeFontInfo::GetUnderlined() const
473{
474 return underlined;
475}
476
477wxString wxNativeFontInfo::GetFaceName() const
478{
479 return faceName;
480}
481
7936354d
VZ
482wxFontFamily wxNativeFontInfo::GetFamily() const
483{
484 return family;
485}
486
ab5fe833
VZ
487wxFontEncoding wxNativeFontInfo::GetEncoding() const
488{
489 return encoding;
490}
491
492void wxNativeFontInfo::SetPointSize(int pointsize)
493{
494 pointSize = pointsize;
495}
496
497void wxNativeFontInfo::SetStyle(wxFontStyle style_)
498{
499 style = style_;
500}
501
502void wxNativeFontInfo::SetWeight(wxFontWeight weight_)
503{
504 weight = weight_;
505}
506
507void wxNativeFontInfo::SetUnderlined(bool underlined_)
508{
509 underlined = underlined_;
510}
511
fbfb8bcc 512void wxNativeFontInfo::SetFaceName(const wxString& facename_)
ab5fe833 513{
f7b301fa 514 faceName = facename_;
ab5fe833
VZ
515}
516
3f1d1373 517void wxNativeFontInfo::SetFamily(wxFontFamily family_)
7936354d
VZ
518{
519 family = family_;
520}
521
ab5fe833
VZ
522void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding_)
523{
524 encoding = encoding_;
525}
526
7826e2dd 527#endif // generic wxNativeFontInfo implementation
30764ab5 528
ab5fe833
VZ
529// conversion to/from user-readable string: this is used in the generic
530// versions and under MSW as well because there is no standard font description
531// format there anyhow (but there is a well-defined standard for X11 fonts used
532// by wxGTK and wxMotif)
533
0eb529d9 534#if defined(wxNO_NATIVE_FONTINFO) || defined(__WXMSW__) || defined (__WXPM__)
ab5fe833
VZ
535
536wxString wxNativeFontInfo::ToUserString() const
537{
538 wxString desc;
539
540 // first put the adjectives, if any - this is English-centric, of course,
541 // but what else can we do?
542 if ( GetUnderlined() )
543 {
544 desc << _("underlined ");
545 }
546
547 switch ( GetWeight() )
548 {
549 default:
550 wxFAIL_MSG( _T("unknown font weight") );
551 // fall through
552
553 case wxFONTWEIGHT_NORMAL:
554 break;
555
556 case wxFONTWEIGHT_LIGHT:
557 desc << _("light ");
558 break;
559
560 case wxFONTWEIGHT_BOLD:
561 desc << _("bold ");
562 break;
563 }
564
565 switch ( GetStyle() )
566 {
567 default:
568 wxFAIL_MSG( _T("unknown font style") );
569 // fall through
570
571 case wxFONTSTYLE_NORMAL:
572 break;
573
574 // we don't distinguish between the two for now anyhow...
575 case wxFONTSTYLE_ITALIC:
576 case wxFONTSTYLE_SLANT:
a9249b2e 577 desc << _("italic");
ab5fe833
VZ
578 break;
579 }
580
a9249b2e
VZ
581 wxString face = GetFaceName();
582 if ( !face.empty() )
ab5fe833 583 {
a9249b2e 584 desc << _T(' ') << face;
ab5fe833
VZ
585 }
586
a9249b2e
VZ
587 int size = GetPointSize();
588 if ( size != wxNORMAL_FONT->GetPointSize() )
ab5fe833 589 {
a9249b2e 590 desc << _T(' ') << size;
ab5fe833 591 }
a9249b2e 592
e7e52b6d 593#if wxUSE_FONTMAP
a9249b2e
VZ
594 wxFontEncoding enc = GetEncoding();
595 if ( enc != wxFONTENCODING_DEFAULT && enc != wxFONTENCODING_SYSTEM )
596 {
2a1f999f 597 desc << _T(' ') << wxFontMapper::GetEncodingName(enc);
a9249b2e 598 }
e7e52b6d 599#endif // wxUSE_FONTMAP
a9249b2e
VZ
600
601 return desc;
ab5fe833
VZ
602}
603
604bool wxNativeFontInfo::FromUserString(const wxString& s)
605{
606 // reset to the default state
607 Init();
608
609 // parse a more or less free form string
610 //
611 // TODO: we should handle at least the quoted facenames
612 wxStringTokenizer tokenizer(s, _T(";, "), wxTOKEN_STRTOK);
613
614 wxString face;
615 unsigned long size;
e7e52b6d
VZ
616
617#if wxUSE_FONTMAP
ab5fe833 618 wxFontEncoding encoding;
e7e52b6d 619#endif // wxUSE_FONTMAP
ab5fe833
VZ
620
621 while ( tokenizer.HasMoreTokens() )
622 {
623 wxString token = tokenizer.GetNextToken();
624
625 // normalize it
a62848fd 626 token.Trim(true).Trim(false).MakeLower();
ab5fe833
VZ
627
628 // look for the known tokens
629 if ( token == _T("underlined") || token == _("underlined") )
630 {
a62848fd 631 SetUnderlined(true);
ab5fe833
VZ
632 }
633 else if ( token == _T("light") || token == _("light") )
634 {
635 SetWeight(wxFONTWEIGHT_LIGHT);
636 }
637 else if ( token == _T("bold") || token == _("bold") )
638 {
639 SetWeight(wxFONTWEIGHT_BOLD);
640 }
641 else if ( token == _T("italic") || token == _("italic") )
642 {
643 SetStyle(wxFONTSTYLE_ITALIC);
644 }
645 else if ( token.ToULong(&size) )
646 {
a9249b2e 647 SetPointSize(size);
ab5fe833 648 }
e7e52b6d 649#if wxUSE_FONTMAP
a62848fd 650 else if ( (encoding = wxFontMapper::Get()->CharsetToEncoding(token, false))
ab5fe833
VZ
651 != wxFONTENCODING_DEFAULT )
652 {
653 SetEncoding(encoding);
654 }
e7e52b6d 655#endif // wxUSE_FONTMAP
ab5fe833
VZ
656 else // assume it is the face name
657 {
658 if ( !face.empty() )
659 {
660 face += _T(' ');
661 }
662
663 face += token;
664
665 // skip the code which resets face below
666 continue;
667 }
668
669 // if we had had the facename, we shouldn't continue appending tokens
670 // to it (i.e. "foo bold bar" shouldn't result in the facename "foo
671 // bar")
672 if ( !face.empty() )
673 {
674 SetFaceName(face);
675 face.clear();
676 }
677 }
678
679 // we might not have flushed it inside the loop
680 if ( !face.empty() )
681 {
682 SetFaceName(face);
683 }
684
a62848fd 685 return true;
ab5fe833
VZ
686}
687
0eb529d9 688#endif // generic or wxMSW or wxOS2
ab5fe833 689