]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/font.cpp
don't crash when invalid colour is set as fg/bg colour
[wxWidgets.git] / src / gtk / font.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: font.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 // ============================================================================
11 // declarations
12 // ============================================================================
13
14 // ----------------------------------------------------------------------------
15 // headers
16 // ----------------------------------------------------------------------------
17
18 #ifdef __GNUG__
19 #pragma implementation "font.h"
20 #endif
21
22 #include "wx/font.h"
23 #include "wx/fontutil.h"
24 #include "wx/cmndata.h"
25 #include "wx/utils.h"
26 #include "wx/log.h"
27 #include "wx/gdicmn.h"
28 #include "wx/tokenzr.h"
29 #include "wx/settings.h"
30
31 #include <strings.h>
32
33 #include <gdk/gdk.h>
34 #include <gdk/gdkprivate.h>
35 #include <gtk/gtk.h>
36
37 // ----------------------------------------------------------------------------
38 // wxFontRefData
39 // ----------------------------------------------------------------------------
40
41 class wxFontRefData : public wxObjectRefData
42 {
43 public:
44 wxFontRefData(int size = wxDEFAULT,
45 int family = wxDEFAULT,
46 int style = wxDEFAULT,
47 int weight = wxDEFAULT,
48 bool underlined = FALSE,
49 const wxString& faceName = wxEmptyString,
50 wxFontEncoding encoding = wxFONTENCODING_DEFAULT);
51 wxFontRefData( const wxFontRefData& data );
52 virtual ~wxFontRefData();
53
54 protected:
55 // common part of all ctors
56 void Init(int pointSize,
57 int family,
58 int style,
59 int weight,
60 bool underlined,
61 const wxString& faceName,
62 wxFontEncoding encoding);
63
64 private:
65 wxList m_scaled_xfonts;
66 int m_pointSize;
67 int m_family,
68 m_style,
69 m_weight;
70 bool m_underlined;
71 wxString m_faceName;
72 wxFontEncoding m_encoding;
73
74 wxNativeFontInfo m_nativeFontInfo;
75
76 friend class wxFont;
77 };
78
79 // ============================================================================
80 // implementation
81 // ============================================================================
82
83 // ----------------------------------------------------------------------------
84 // wxFontRefData
85 // ----------------------------------------------------------------------------
86
87 void wxFontRefData::Init(int pointSize,
88 int family,
89 int style,
90 int weight,
91 bool underlined,
92 const wxString& faceName,
93 wxFontEncoding encoding)
94 {
95 if (family == wxDEFAULT)
96 m_family = wxSWISS;
97 else
98 m_family = family;
99
100 m_faceName = faceName;
101
102 if (style == wxDEFAULT)
103 m_style = wxNORMAL;
104 else
105 m_style = style;
106
107 if (weight == wxDEFAULT)
108 m_weight = wxNORMAL;
109 else
110 m_weight = weight;
111
112 if (pointSize == wxDEFAULT)
113 m_pointSize = 12;
114 else
115 m_pointSize = pointSize;
116
117 m_underlined = underlined;
118 m_encoding = encoding;
119 }
120
121 wxFontRefData::wxFontRefData( const wxFontRefData& data )
122 : m_scaled_xfonts(wxKEY_INTEGER)
123 {
124 Init(data.m_pointSize, data.m_family, data.m_style, data.m_weight,
125 data.m_underlined, data.m_faceName, data.m_encoding);
126 }
127
128 wxFontRefData::wxFontRefData(int size, int family, int style,
129 int weight, bool underlined,
130 const wxString& faceName,
131 wxFontEncoding encoding)
132 : m_scaled_xfonts(wxKEY_INTEGER)
133 {
134 Init(size, family, style, weight, underlined, faceName, encoding);
135 }
136
137 wxFontRefData::~wxFontRefData()
138 {
139 wxNode *node = m_scaled_xfonts.First();
140 while (node)
141 {
142 GdkFont *font = (GdkFont*)node->Data();
143 wxNode *next = node->Next();
144 gdk_font_unref( font );
145 node = next;
146 }
147 }
148
149 // ----------------------------------------------------------------------------
150 // wxNativeFontInfo
151 // ----------------------------------------------------------------------------
152
153 bool wxNativeFontInfo::FromString(const wxString& s)
154 {
155 wxStringTokenizer tokenizer(s, _T(";"));
156
157 wxString token = tokenizer.GetNextToken();
158 //
159 // Ignore the version for now
160 //
161
162 xFontName = tokenizer.GetNextToken();
163 if(!xFontName)
164 return FALSE;
165
166 return TRUE;
167 }
168
169 wxString wxNativeFontInfo::ToString() const
170 {
171 wxString s;
172
173 s.Printf(_T("%d;%s"),
174 0, // version
175 xFontName.c_str());
176
177 return s;
178 }
179
180 // ----------------------------------------------------------------------------
181 // wxFont
182 // ----------------------------------------------------------------------------
183
184 IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject)
185
186 void wxFont::Init()
187 {
188 if (wxTheFontList)
189 wxTheFontList->Append( this );
190 }
191
192 wxFont::wxFont(const wxNativeFontInfo& info)
193 {
194 Init();
195
196 Create(info.xFontName);
197 }
198
199 bool wxFont::Create(const wxNativeFontInfo& info)
200 {
201 return Create(info.xFontName);
202 }
203
204 bool wxFont::Create( int pointSize,
205 int family,
206 int style,
207 int weight,
208 bool underlined,
209 const wxString& face,
210 wxFontEncoding encoding)
211 {
212 m_refData = new wxFontRefData(pointSize, family, style, weight,
213 underlined, face, encoding);
214
215 return TRUE;
216 }
217
218 bool wxFont::Create(const wxString& fontname, wxFontEncoding enc)
219 {
220 if( !fontname )
221 {
222 *this = wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT);
223 return TRUE;
224 }
225
226 m_refData = new wxFontRefData();
227
228 M_FONTDATA->m_nativeFontInfo.xFontName = fontname; // X font name
229
230 wxString tmp;
231
232 wxStringTokenizer tn( fontname, wxT("-") );
233
234 tn.GetNextToken(); // skip initial empty token
235 tn.GetNextToken(); // foundry
236
237
238 M_FONTDATA->m_faceName = tn.GetNextToken(); // family
239
240 tmp = tn.GetNextToken().MakeUpper(); // weight
241 if (tmp == wxT("BOLD")) M_FONTDATA->m_weight = wxBOLD;
242 if (tmp == wxT("BLACK")) M_FONTDATA->m_weight = wxBOLD;
243 if (tmp == wxT("EXTRABOLD")) M_FONTDATA->m_weight = wxBOLD;
244 if (tmp == wxT("DEMIBOLD")) M_FONTDATA->m_weight = wxBOLD;
245 if (tmp == wxT("ULTRABOLD")) M_FONTDATA->m_weight = wxBOLD;
246
247 if (tmp == wxT("LIGHT")) M_FONTDATA->m_weight = wxLIGHT;
248 if (tmp == wxT("THIN")) M_FONTDATA->m_weight = wxLIGHT;
249
250 tmp = tn.GetNextToken().MakeUpper(); // slant
251 if (tmp == wxT("I")) M_FONTDATA->m_style = wxITALIC;
252 if (tmp == wxT("O")) M_FONTDATA->m_style = wxITALIC;
253
254 tn.GetNextToken(); // set width
255 tn.GetNextToken(); // add. style
256 tn.GetNextToken(); // pixel size
257
258 tmp = tn.GetNextToken(); // pointsize
259 if (tmp != wxT("*"))
260 {
261 long num = wxStrtol (tmp.c_str(), (wxChar **) NULL, 10);
262 M_FONTDATA->m_pointSize = (int)(num / 10);
263 }
264
265 tn.GetNextToken(); // x-res
266 tn.GetNextToken(); // y-res
267
268 tmp = tn.GetNextToken().MakeUpper(); // spacing
269
270 if (tmp == wxT("M"))
271 M_FONTDATA->m_family = wxMODERN;
272 else if (M_FONTDATA->m_faceName == wxT("TIMES"))
273 M_FONTDATA->m_family = wxROMAN;
274 else if (M_FONTDATA->m_faceName == wxT("HELVETICA"))
275 M_FONTDATA->m_family = wxSWISS;
276 else if (M_FONTDATA->m_faceName == wxT("LUCIDATYPEWRITER"))
277 M_FONTDATA->m_family = wxTELETYPE;
278 else if (M_FONTDATA->m_faceName == wxT("LUCIDA"))
279 M_FONTDATA->m_family = wxDECORATIVE;
280 else if (M_FONTDATA->m_faceName == wxT("UTOPIA"))
281 M_FONTDATA->m_family = wxSCRIPT;
282
283 tn.GetNextToken(); // avg width
284
285 // deal with font encoding
286 M_FONTDATA->m_encoding = enc;
287 if ( M_FONTDATA->m_encoding == wxFONTENCODING_SYSTEM )
288 {
289 wxString registry = tn.GetNextToken().MakeUpper(),
290 encoding = tn.GetNextToken().MakeUpper();
291
292 if ( registry == _T("ISO8859") )
293 {
294 int cp;
295 if ( wxSscanf(encoding, wxT("%d"), &cp) == 1 )
296 {
297 M_FONTDATA->m_encoding =
298 (wxFontEncoding)(wxFONTENCODING_ISO8859_1 + cp - 1);
299 }
300 }
301 else if ( registry == _T("MICROSOFT") )
302 {
303 int cp;
304 if ( wxSscanf(encoding, wxT("cp125%d"), &cp) == 1 )
305 {
306 M_FONTDATA->m_encoding =
307 (wxFontEncoding)(wxFONTENCODING_CP1250 + cp);
308 }
309 }
310 else if ( registry == _T("KOI8") )
311 {
312 M_FONTDATA->m_encoding = wxFONTENCODING_KOI8;
313 }
314 //else: unknown encoding - may be give a warning here?
315 else
316 return FALSE;
317 }
318 return TRUE;
319 }
320
321 void wxFont::Unshare()
322 {
323 if (!m_refData)
324 {
325 m_refData = new wxFontRefData();
326 }
327 else
328 {
329 wxFontRefData* ref = new wxFontRefData(*(wxFontRefData*)m_refData);
330 UnRef();
331 m_refData = ref;
332 }
333 }
334
335 wxFont::~wxFont()
336 {
337 if (wxTheFontList)
338 wxTheFontList->DeleteObject( this );
339 }
340
341 // ----------------------------------------------------------------------------
342 // accessors
343 // ----------------------------------------------------------------------------
344
345 int wxFont::GetPointSize() const
346 {
347 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
348
349 return M_FONTDATA->m_pointSize;
350 }
351
352 wxString wxFont::GetFaceName() const
353 {
354 wxCHECK_MSG( Ok(), wxT(""), wxT("invalid font") );
355
356 return M_FONTDATA->m_faceName;
357 }
358
359 int wxFont::GetFamily() const
360 {
361 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
362
363 return M_FONTDATA->m_family;
364 }
365
366 int wxFont::GetStyle() const
367 {
368 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
369
370 return M_FONTDATA->m_style;
371 }
372
373 int wxFont::GetWeight() const
374 {
375 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
376
377 return M_FONTDATA->m_weight;
378 }
379
380 bool wxFont::GetUnderlined() const
381 {
382 wxCHECK_MSG( Ok(), FALSE, wxT("invalid font") );
383
384 return M_FONTDATA->m_underlined;
385 }
386
387
388 wxFontEncoding wxFont::GetEncoding() const
389 {
390 wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT, wxT("invalid font") );
391
392 return M_FONTDATA->m_encoding;
393 }
394
395 wxNativeFontInfo *wxFont::GetNativeFontInfo() const
396 {
397 wxCHECK_MSG( Ok(), (wxNativeFontInfo *)NULL, wxT("invalid font") );
398
399 if(M_FONTDATA->m_nativeFontInfo.xFontName.IsEmpty())
400 GetInternalFont();
401
402 return new wxNativeFontInfo(M_FONTDATA->m_nativeFontInfo);
403 }
404
405
406 // ----------------------------------------------------------------------------
407 // change font attributes
408 // ----------------------------------------------------------------------------
409
410 void wxFont::SetPointSize(int pointSize)
411 {
412 Unshare();
413
414 M_FONTDATA->m_pointSize = pointSize;
415 M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now
416 }
417
418 void wxFont::SetFamily(int family)
419 {
420 Unshare();
421
422 M_FONTDATA->m_family = family;
423 M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now
424 }
425
426 void wxFont::SetStyle(int style)
427 {
428 Unshare();
429
430 M_FONTDATA->m_style = style;
431 M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now
432 }
433
434 void wxFont::SetWeight(int weight)
435 {
436 Unshare();
437
438 M_FONTDATA->m_weight = weight;
439 M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now
440 }
441
442 void wxFont::SetFaceName(const wxString& faceName)
443 {
444 Unshare();
445
446 M_FONTDATA->m_faceName = faceName;
447 M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now
448 }
449
450 void wxFont::SetUnderlined(bool underlined)
451 {
452 Unshare();
453
454 M_FONTDATA->m_underlined = underlined;
455 }
456
457 void wxFont::SetEncoding(wxFontEncoding encoding)
458 {
459 Unshare();
460
461 M_FONTDATA->m_encoding = encoding;
462 M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now
463 }
464
465 void wxFont::SetNativeFontInfo(const wxNativeFontInfo& info)
466 {
467 Unshare();
468
469 M_FONTDATA->m_nativeFontInfo = info;
470 }
471
472 // ----------------------------------------------------------------------------
473 // get internal representation of font
474 // ----------------------------------------------------------------------------
475
476 static GdkFont *g_systemDefaultGuiFont = (GdkFont*) NULL;
477
478 GdkFont *GtkGetDefaultGuiFont()
479 {
480 if (!g_systemDefaultGuiFont)
481 {
482 GtkWidget *widget = gtk_button_new();
483 GtkStyle *def = gtk_rc_get_style( widget );
484 if (def)
485 {
486 g_systemDefaultGuiFont = gdk_font_ref( def->font );
487 }
488 else
489 {
490 def = gtk_widget_get_default_style();
491 if (def)
492 g_systemDefaultGuiFont = gdk_font_ref( def->font );
493 }
494 gtk_widget_destroy( widget );
495 }
496 else
497 {
498 // already have it, but ref it once more before returning
499 gdk_font_ref(g_systemDefaultGuiFont);
500 }
501
502 return g_systemDefaultGuiFont;
503 }
504
505 GdkFont *wxFont::GetInternalFont( float scale ) const
506 {
507 if (!Ok())
508 {
509 wxFAIL_MSG( wxT("invalid font") );
510
511 return (GdkFont*) NULL;
512 }
513
514 long int_scale = long(scale * 100.0 + 0.5); /* key for fontlist */
515 int point_scale = (int)((M_FONTDATA->m_pointSize * 10 * int_scale) / 100);
516 GdkFont *font = (GdkFont *) NULL;
517
518 wxNode *node = M_FONTDATA->m_scaled_xfonts.Find(int_scale);
519 if (node)
520 {
521 font = (GdkFont*)node->Data();
522 }
523 else
524 {
525 if (*this == wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT))
526 {
527 font = GtkGetDefaultGuiFont();
528 }
529 if (!font)
530 {
531 font = wxLoadQueryNearestFont( point_scale,
532 M_FONTDATA->m_family,
533 M_FONTDATA->m_style,
534 M_FONTDATA->m_weight,
535 M_FONTDATA->m_underlined,
536 M_FONTDATA->m_faceName,
537 M_FONTDATA->m_encoding,
538 &M_FONTDATA->m_nativeFontInfo.xFontName );
539 }
540
541 M_FONTDATA->m_scaled_xfonts.Append( int_scale, (wxObject*)font );
542 }
543
544 // it's quite useless to make it a wxCHECK because we're going to crash
545 // anyhow...
546 wxASSERT_MSG( font, wxT("could not load any font?") );
547
548 return font;
549 }
550