]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/fontcmn.cpp
DMC warning fix.
[wxWidgets.git] / src / common / fontcmn.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
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$
8// Copyright: (c) wxWidgets team
9// Licence: wxWindows licence
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__
24#pragma hdrstop
25#endif
26
27#ifndef WX_PRECOMP
28 #include "wx/dc.h"
29 #include "wx/font.h"
30 #include "wx/intl.h"
31 #include "wx/dcscreen.h"
32#endif // WX_PRECOMP
33
34#include "wx/gdicmn.h"
35
36#if defined(__WXMSW__)
37 #include "wx/msw/private.h" // includes windows.h for LOGFONT
38 #include "wx/msw/winundef.h"
39#endif
40
41#include "wx/fontutil.h" // for wxNativeFontInfo
42#include "wx/fontmap.h"
43
44#include "wx/tokenzr.h"
45
46// ============================================================================
47// implementation
48// ============================================================================
49
50// ----------------------------------------------------------------------------
51// helper functions
52// ----------------------------------------------------------------------------
53
54static void AdjustFontSize(wxFont& font, wxDC& dc, const wxSize& pixelSize)
55{
56 int currentSize = 0;
57 int largestGood = 0;
58 int smallestBad = 0;
59
60 bool initialGoodFound = false;
61 bool initialBadFound = false;
62
63 // NB: this assignment was separated from the variable definition
64 // in order to fix a gcc v3.3.3 compiler crash
65 currentSize = font.GetPointSize();
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
108// ----------------------------------------------------------------------------
109// wxFontBase
110// ----------------------------------------------------------------------------
111
112wxFontEncoding wxFontBase::ms_encodingDefault = wxFONTENCODING_SYSTEM;
113
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
125wxFontBase::~wxFontBase()
126{
127 // this destructor is required for Darwin
128}
129
130/* static */
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
142static inline int flags2Style(int flags)
143{
144 return flags & wxFONTFLAG_ITALIC
145 ? wxFONTSTYLE_ITALIC
146 : flags & wxFONTFLAG_SLANT
147 ? wxFONTSTYLE_SLANT
148 : wxFONTSTYLE_NORMAL;
149}
150
151static inline int flags2Weight(int flags)
152{
153 return flags & wxFONTFLAG_LIGHT
154 ? wxFONTWEIGHT_LIGHT
155 : flags & wxFONTFLAG_BOLD
156 ? wxFONTWEIGHT_BOLD
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
189 wxFont *self = New(10, family, style, weight, underlined, face, encoding);
190 wxScreenDC dc;
191 AdjustFontSize(*(wxFont *)self, dc, pixelSize);
192 return self;
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);
223}
224
225/* static */
226wxFont *wxFontBase::New(const wxNativeFontInfo& info)
227{
228 return new wxFont(info);
229}
230
231/* static */
232wxFont *wxFontBase::New(const wxString& strNativeFontDesc)
233{
234 wxNativeFontInfo fontInfo;
235 if ( !fontInfo.FromString(strNativeFontDesc) )
236 return new wxFont(*wxNORMAL_FONT);
237
238 return New(fontInfo);
239}
240
241bool wxFontBase::IsFixedWidth() const
242{
243 return GetFamily() == wxFONTFAMILY_TELETYPE;
244}
245
246void wxFontBase::DoSetNativeFontInfo(const wxNativeFontInfo& info)
247{
248#ifdef wxNO_NATIVE_FONTINFO
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);
256#else
257 (void)info;
258#endif
259}
260
261wxString wxFontBase::GetNativeFontInfoDesc() const
262{
263 wxString fontDesc;
264 const wxNativeFontInfo *fontInfo = GetNativeFontInfo();
265 if ( fontInfo )
266 {
267 fontDesc = fontInfo->ToString();
268 }
269
270 return fontDesc;
271}
272
273wxString wxFontBase::GetNativeFontInfoUserDesc() const
274{
275 wxString fontDesc;
276 const wxNativeFontInfo *fontInfo = GetNativeFontInfo();
277 if ( fontInfo )
278 {
279 fontDesc = fontInfo->ToUserString();
280 }
281
282 return fontDesc;
283}
284
285void wxFontBase::SetNativeFontInfo(const wxString& info)
286{
287 wxNativeFontInfo fontInfo;
288 if ( !info.empty() && fontInfo.FromString(info) )
289 {
290 SetNativeFontInfo(fontInfo);
291 }
292}
293
294void wxFontBase::SetNativeFontInfoUserDesc(const wxString& info)
295{
296 wxNativeFontInfo fontInfo;
297 if ( !info.empty() && fontInfo.FromUserString(info) )
298 {
299 SetNativeFontInfo(fontInfo);
300 }
301}
302
303bool wxFontBase::operator==(const wxFont& font) const
304{
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() &&
313 GetWeight() == font.GetWeight() &&
314 GetUnderlined() == font.GetUnderlined() &&
315 GetFaceName() == font.GetFaceName() &&
316 GetEncoding() == font.GetEncoding()
317 );
318}
319
320bool wxFontBase::operator!=(const wxFont& font) const
321{
322 return !(*this == font);
323}
324
325wxString wxFontBase::GetFamilyString() const
326{
327 wxCHECK_MSG( Ok(), wxT("wxDEFAULT"), wxT("invalid font") );
328
329 switch ( GetFamily() )
330 {
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");
338 }
339}
340
341wxString wxFontBase::GetStyleString() const
342{
343 wxCHECK_MSG( Ok(), wxT("wxDEFAULT"), wxT("invalid font") );
344
345 switch ( GetStyle() )
346 {
347 case wxNORMAL: return wxT("wxNORMAL");
348 case wxSLANT: return wxT("wxSLANT");
349 case wxITALIC: return wxT("wxITALIC");
350 default: return wxT("wxDEFAULT");
351 }
352}
353
354wxString wxFontBase::GetWeightString() const
355{
356 wxCHECK_MSG( Ok(), wxT("wxDEFAULT"), wxT("invalid font") );
357
358 switch ( GetWeight() )
359 {
360 case wxNORMAL: return wxT("wxNORMAL");
361 case wxBOLD: return wxT("wxBOLD");
362 case wxLIGHT: return wxT("wxLIGHT");
363 default: return wxT("wxDEFAULT");
364 }
365}
366
367// ----------------------------------------------------------------------------
368// wxNativeFontInfo
369// ----------------------------------------------------------------------------
370
371#ifdef wxNO_NATIVE_FONTINFO
372
373// These are the generic forms of FromString()/ToString.
374//
375// convert to/from the string representation: format is
376// version;pointsize;family;style;weight;underlined;facename;encoding
377
378bool wxNativeFontInfo::FromString(const wxString& s)
379{
380 long l;
381
382 wxStringTokenizer tokenizer(s, _T(";"));
383
384 wxString token = tokenizer.GetNextToken();
385 //
386 // Ignore the version for now
387 //
388
389 token = tokenizer.GetNextToken();
390 if ( !token.ToLong(&l) )
391 return false;
392 pointSize = (int)l;
393
394 token = tokenizer.GetNextToken();
395 if ( !token.ToLong(&l) )
396 return false;
397 family = (wxFontFamily)l;
398
399 token = tokenizer.GetNextToken();
400 if ( !token.ToLong(&l) )
401 return false;
402 style = (wxFontStyle)l;
403
404 token = tokenizer.GetNextToken();
405 if ( !token.ToLong(&l) )
406 return false;
407 weight = (wxFontWeight)l;
408
409 token = tokenizer.GetNextToken();
410 if ( !token.ToLong(&l) )
411 return false;
412 underlined = l != 0;
413
414 faceName = tokenizer.GetNextToken();
415
416#ifndef __WXMAC__
417 if( !faceName )
418 return false;
419#endif
420
421 token = tokenizer.GetNextToken();
422 if ( !token.ToLong(&l) )
423 return false;
424 encoding = (wxFontEncoding)l;
425
426 return true;
427}
428
429wxString wxNativeFontInfo::ToString() const
430{
431 wxString s;
432
433 s.Printf(_T("%d;%d;%d;%d;%d;%d;%s;%d"),
434 0, // version
435 pointSize,
436 family,
437 (int)style,
438 (int)weight,
439 underlined,
440 faceName.GetData(),
441 (int)encoding);
442
443 return s;
444}
445
446void wxNativeFontInfo::Init()
447{
448 pointSize = 0;
449 family = wxFONTFAMILY_DEFAULT;
450 style = wxFONTSTYLE_NORMAL;
451 weight = wxFONTWEIGHT_NORMAL;
452 underlined = false;
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
482wxFontFamily wxNativeFontInfo::GetFamily() const
483{
484 return family;
485}
486
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
512void wxNativeFontInfo::SetFaceName(const wxString& facename_)
513{
514 faceName = facename_;
515}
516
517void wxNativeFontInfo::SetFamily(wxFontFamily family_)
518{
519 family = family_;
520}
521
522void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding_)
523{
524 encoding = encoding_;
525}
526
527#endif // generic wxNativeFontInfo implementation
528
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
534#if defined(wxNO_NATIVE_FONTINFO) || defined(__WXMSW__) || defined (__WXPM__)
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:
577 desc << _("italic");
578 break;
579 }
580
581 wxString face = GetFaceName();
582 if ( !face.empty() )
583 {
584 desc << _T(' ') << face;
585 }
586
587 int size = GetPointSize();
588 if ( size != wxNORMAL_FONT->GetPointSize() )
589 {
590 desc << _T(' ') << size;
591 }
592
593#if wxUSE_FONTMAP
594 wxFontEncoding enc = GetEncoding();
595 if ( enc != wxFONTENCODING_DEFAULT && enc != wxFONTENCODING_SYSTEM )
596 {
597 desc << _T(' ') << wxFontMapper::GetEncodingName(enc);
598 }
599#endif // wxUSE_FONTMAP
600
601 return desc;
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;
616
617#if wxUSE_FONTMAP
618 wxFontEncoding encoding;
619#endif // wxUSE_FONTMAP
620
621 while ( tokenizer.HasMoreTokens() )
622 {
623 wxString token = tokenizer.GetNextToken();
624
625 // normalize it
626 token.Trim(true).Trim(false).MakeLower();
627
628 // look for the known tokens
629 if ( token == _T("underlined") || token == _("underlined") )
630 {
631 SetUnderlined(true);
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 {
647 SetPointSize(size);
648 }
649#if wxUSE_FONTMAP
650 else if ( (encoding = wxFontMapper::Get()->CharsetToEncoding(token, false))
651 != wxFONTENCODING_DEFAULT )
652 {
653 SetEncoding(encoding);
654 }
655#endif // wxUSE_FONTMAP
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
685 return true;
686}
687
688#endif // generic or wxMSW or wxOS2
689