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