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