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