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