]> git.saurik.com Git - wxWidgets.git/blob - src/common/fontcmn.cpp
another custom draw fix: leave space for the image even if the current item doesn...
[wxWidgets.git] / src / common / fontcmn.cpp
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
54 static 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
112 wxFontEncoding wxFontBase::ms_encodingDefault = wxFONTENCODING_SYSTEM;
113
114 /* static */
115 void 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
125 wxFontBase::~wxFontBase()
126 {
127 // this destructor is required for Darwin
128 }
129
130 /* static */
131 wxFont *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
142 static 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
151 static 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
160 static inline bool flags2Underlined(int flags)
161 {
162 return (flags & wxFONTFLAG_UNDERLINED) != 0;
163 }
164
165 /* static */
166 wxFont *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 */
177 wxFont *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 */
197 wxFont *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
207 wxSize wxFontBase::GetPixelSize() const
208 {
209 wxScreenDC dc;
210 dc.SetFont(*(wxFont *)this);
211 return wxSize(dc.GetCharWidth(), dc.GetCharHeight());
212 }
213
214 bool wxFontBase::IsUsingSizeInPixels() const
215 {
216 return false;
217 }
218
219 void wxFontBase::SetPixelSize( const wxSize& pixelSize )
220 {
221 wxScreenDC dc;
222 AdjustFontSize(*(wxFont *)this, dc, pixelSize);
223 }
224
225 /* static */
226 wxFont *wxFontBase::New(const wxNativeFontInfo& info)
227 {
228 return new wxFont(info);
229 }
230
231 /* static */
232 wxFont *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
241 bool wxFontBase::IsFixedWidth() const
242 {
243 return GetFamily() == wxFONTFAMILY_TELETYPE;
244 }
245
246 void 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
261 wxString 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
273 wxString 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
285 void wxFontBase::SetNativeFontInfo(const wxString& info)
286 {
287 wxNativeFontInfo fontInfo;
288 if ( !info.empty() && fontInfo.FromString(info) )
289 {
290 SetNativeFontInfo(fontInfo);
291 }
292 }
293
294 void wxFontBase::SetNativeFontInfoUserDesc(const wxString& info)
295 {
296 wxNativeFontInfo fontInfo;
297 if ( !info.empty() && fontInfo.FromUserString(info) )
298 {
299 SetNativeFontInfo(fontInfo);
300 }
301 }
302
303 bool 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
320 bool wxFontBase::operator!=(const wxFont& font) const
321 {
322 return !(*this == font);
323 }
324
325 wxString 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
341 wxString 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
354 wxString 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
378 bool 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
429 wxString 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
446 void 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
457 int wxNativeFontInfo::GetPointSize() const
458 {
459 return pointSize;
460 }
461
462 wxFontStyle wxNativeFontInfo::GetStyle() const
463 {
464 return style;
465 }
466
467 wxFontWeight wxNativeFontInfo::GetWeight() const
468 {
469 return weight;
470 }
471
472 bool wxNativeFontInfo::GetUnderlined() const
473 {
474 return underlined;
475 }
476
477 wxString wxNativeFontInfo::GetFaceName() const
478 {
479 return faceName;
480 }
481
482 wxFontFamily wxNativeFontInfo::GetFamily() const
483 {
484 return family;
485 }
486
487 wxFontEncoding wxNativeFontInfo::GetEncoding() const
488 {
489 return encoding;
490 }
491
492 void wxNativeFontInfo::SetPointSize(int pointsize)
493 {
494 pointSize = pointsize;
495 }
496
497 void wxNativeFontInfo::SetStyle(wxFontStyle style_)
498 {
499 style = style_;
500 }
501
502 void wxNativeFontInfo::SetWeight(wxFontWeight weight_)
503 {
504 weight = weight_;
505 }
506
507 void wxNativeFontInfo::SetUnderlined(bool underlined_)
508 {
509 underlined = underlined_;
510 }
511
512 void wxNativeFontInfo::SetFaceName(const wxString& facename_)
513 {
514 faceName = facename_;
515 }
516
517 void wxNativeFontInfo::SetFamily(wxFontFamily family_)
518 {
519 family = family_;
520 }
521
522 void 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
536 wxString 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
604 bool 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