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