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