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