Correct deafult GUI font is now found when querying
[wxWidgets.git] / src / gtk1 / 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 <gtk/gtk.h>
35
36 // ----------------------------------------------------------------------------
37 // wxFontRefData
38 // ----------------------------------------------------------------------------
39
40 class wxFontRefData : public wxObjectRefData
41 {
42 public:
43 wxFontRefData(int size = wxDEFAULT,
44 int family = wxDEFAULT,
45 int style = wxDEFAULT,
46 int weight = wxDEFAULT,
47 bool underlined = FALSE,
48 const wxString& faceName = wxEmptyString,
49 wxFontEncoding encoding = wxFONTENCODING_DEFAULT);
50 wxFontRefData( const wxFontRefData& data );
51 virtual ~wxFontRefData();
52
53 protected:
54 // common part of all ctors
55 void Init(int pointSize,
56 int family,
57 int style,
58 int weight,
59 bool underlined,
60 const wxString& faceName,
61 wxFontEncoding encoding);
62
63 private:
64 wxList m_scaled_xfonts;
65 int m_pointSize;
66 int m_family,
67 m_style,
68 m_weight;
69 bool m_underlined;
70 wxString m_faceName;
71 wxFontEncoding m_encoding;
72
73 friend wxFont;
74 };
75
76 // ============================================================================
77 // implementation
78 // ============================================================================
79
80 // ----------------------------------------------------------------------------
81 // wxFontRefData
82 // ----------------------------------------------------------------------------
83
84 void wxFontRefData::Init(int pointSize,
85 int family,
86 int style,
87 int weight,
88 bool underlined,
89 const wxString& faceName,
90 wxFontEncoding encoding)
91 {
92 if (family == wxDEFAULT)
93 m_family = wxSWISS;
94 else
95 m_family = family;
96
97 m_faceName = faceName;
98
99 if (style == wxDEFAULT)
100 m_style = wxNORMAL;
101 else
102 m_style = style;
103
104 if (weight == wxDEFAULT)
105 m_weight = wxNORMAL;
106 else
107 m_weight = weight;
108
109 if (pointSize == wxDEFAULT)
110 m_pointSize = 12;
111 else
112 m_pointSize = pointSize;
113
114 m_underlined = underlined;
115 m_encoding = encoding;
116 }
117
118 wxFontRefData::wxFontRefData( const wxFontRefData& data )
119 : m_scaled_xfonts(wxKEY_INTEGER)
120 {
121 Init(data.m_pointSize, data.m_family, data.m_style, data.m_weight,
122 data.m_underlined, data.m_faceName, data.m_encoding);
123 }
124
125 wxFontRefData::wxFontRefData(int size, int family, int style,
126 int weight, bool underlined, const wxString& faceName, wxFontEncoding encoding )
127 : m_scaled_xfonts(wxKEY_INTEGER)
128 {
129 Init(size, family, style, weight,
130 underlined, faceName, encoding);
131 }
132
133 wxFontRefData::~wxFontRefData()
134 {
135 wxNode *node = m_scaled_xfonts.First();
136 while (node)
137 {
138 GdkFont *font = (GdkFont*)node->Data();
139 wxNode *next = node->Next();
140 gdk_font_unref( font );
141 node = next;
142 }
143 }
144
145 // ----------------------------------------------------------------------------
146 // wxFont
147 // ----------------------------------------------------------------------------
148
149 IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject)
150
151 void wxFont::Init()
152 {
153 if (wxTheFontList)
154 wxTheFontList->Append( this );
155 }
156
157 wxFont::wxFont( const wxString& fontname, const wxFontData& fontdata )
158 {
159 Init();
160
161 wxCHECK_RET( !!fontname, _T("invalid font spec") );
162
163 m_refData = new wxFontRefData();
164
165 wxString tmp;
166
167 wxStringTokenizer tn( fontname, wxT("-") );
168
169 tn.GetNextToken(); // foundry
170
171 M_FONTDATA->m_faceName = tn.GetNextToken(); // family
172
173 tmp = tn.GetNextToken().MakeUpper(); // weight
174 if (tmp == wxT("BOLD")) M_FONTDATA->m_weight = wxBOLD;
175 if (tmp == wxT("BLACK")) M_FONTDATA->m_weight = wxBOLD;
176 if (tmp == wxT("EXTRABOLD")) M_FONTDATA->m_weight = wxBOLD;
177 if (tmp == wxT("DEMIBOLD")) M_FONTDATA->m_weight = wxBOLD;
178 if (tmp == wxT("ULTRABOLD")) M_FONTDATA->m_weight = wxBOLD;
179
180 if (tmp == wxT("LIGHT")) M_FONTDATA->m_weight = wxLIGHT;
181 if (tmp == wxT("THIN")) M_FONTDATA->m_weight = wxLIGHT;
182
183 tmp = tn.GetNextToken().MakeUpper(); // slant
184 if (tmp == wxT("I")) M_FONTDATA->m_style = wxITALIC;
185 if (tmp == wxT("O")) M_FONTDATA->m_style = wxITALIC;
186
187 tn.GetNextToken(); // set width
188 tn.GetNextToken(); // add. style
189 tn.GetNextToken(); // pixel size
190
191 tmp = tn.GetNextToken(); // pointsize
192 long num = wxStrtol (tmp.c_str(), (wxChar **) NULL, 10);
193 M_FONTDATA->m_pointSize = (int)(num / 10);
194
195 tn.GetNextToken(); // x-res
196 tn.GetNextToken(); // y-res
197
198 tmp = tn.GetNextToken().MakeUpper(); // spacing
199
200 if (tmp == wxT("M"))
201 M_FONTDATA->m_family = wxMODERN;
202 else if (M_FONTDATA->m_faceName == wxT("TIMES"))
203 M_FONTDATA->m_family = wxROMAN;
204 else if (M_FONTDATA->m_faceName == wxT("HELVETICA"))
205 M_FONTDATA->m_family = wxSWISS;
206 else if (M_FONTDATA->m_faceName == wxT("LUCIDATYPEWRITER"))
207 M_FONTDATA->m_family = wxTELETYPE;
208 else if (M_FONTDATA->m_faceName == wxT("LUCIDA"))
209 M_FONTDATA->m_family = wxDECORATIVE;
210 else if (M_FONTDATA->m_faceName == wxT("UTOPIA"))
211 M_FONTDATA->m_family = wxSCRIPT;
212
213 tn.GetNextToken(); // avg width
214
215 // deal with font encoding
216 M_FONTDATA->m_encoding = fontdata.GetEncoding();
217 if ( M_FONTDATA->m_encoding == wxFONTENCODING_SYSTEM )
218 {
219 wxString registry = tn.GetNextToken().MakeUpper(),
220 encoding = tn.GetNextToken().MakeUpper();
221
222 if ( registry == _T("ISO8859") )
223 {
224 int cp;
225 if ( wxSscanf(encoding, wxT("%d"), &cp) == 1 )
226 {
227 M_FONTDATA->m_encoding =
228 (wxFontEncoding)(wxFONTENCODING_ISO8859_1 + cp - 1);
229 }
230 }
231 else if ( registry == _T("MICROSOFT") )
232 {
233 int cp;
234 if ( wxSscanf(encoding, wxT("cp125%d"), &cp) == 1 )
235 {
236 M_FONTDATA->m_encoding =
237 (wxFontEncoding)(wxFONTENCODING_CP1250 + cp);
238 }
239 }
240 else if ( registry == _T("KOI8") )
241 {
242 M_FONTDATA->m_encoding = wxFONTENCODING_KOI8;
243 }
244 //else: unknown encoding - may be give a warning here?
245 }
246 }
247
248 bool wxFont::Create( int pointSize,
249 int family,
250 int style,
251 int weight,
252 bool underlined,
253 const wxString& face,
254 wxFontEncoding encoding )
255 {
256 m_refData = new wxFontRefData(pointSize, family, style, weight,
257 underlined, face, encoding);
258
259 return TRUE;
260 }
261
262 void wxFont::Unshare()
263 {
264 if (!m_refData)
265 {
266 m_refData = new wxFontRefData();
267 }
268 else
269 {
270 wxFontRefData* ref = new wxFontRefData(*(wxFontRefData*)m_refData);
271 UnRef();
272 m_refData = ref;
273 }
274 }
275
276 wxFont::~wxFont()
277 {
278 if (wxTheFontList)
279 wxTheFontList->DeleteObject( this );
280 }
281
282 // ----------------------------------------------------------------------------
283 // accessors
284 // ----------------------------------------------------------------------------
285
286 int wxFont::GetPointSize() const
287 {
288 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
289
290 return M_FONTDATA->m_pointSize;
291 }
292
293 wxString wxFont::GetFaceName() const
294 {
295 wxCHECK_MSG( Ok(), wxT(""), wxT("invalid font") );
296
297 return M_FONTDATA->m_faceName;
298 }
299
300 int wxFont::GetFamily() const
301 {
302 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
303
304 return M_FONTDATA->m_family;
305 }
306
307 int wxFont::GetStyle() const
308 {
309 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
310
311 return M_FONTDATA->m_style;
312 }
313
314 int wxFont::GetWeight() const
315 {
316 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
317
318 return M_FONTDATA->m_weight;
319 }
320
321 bool wxFont::GetUnderlined() const
322 {
323 wxCHECK_MSG( Ok(), FALSE, wxT("invalid font") );
324
325 return M_FONTDATA->m_underlined;
326 }
327
328
329 wxFontEncoding wxFont::GetEncoding() const
330 {
331 wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT, wxT("invalid font") );
332
333 return M_FONTDATA->m_encoding;
334 }
335
336 // ----------------------------------------------------------------------------
337 // change font attributes
338 // ----------------------------------------------------------------------------
339
340 void wxFont::SetPointSize(int pointSize)
341 {
342 Unshare();
343
344 M_FONTDATA->m_pointSize = pointSize;
345 }
346
347 void wxFont::SetFamily(int family)
348 {
349 Unshare();
350
351 M_FONTDATA->m_family = family;
352 }
353
354 void wxFont::SetStyle(int style)
355 {
356 Unshare();
357
358 M_FONTDATA->m_style = style;
359 }
360
361 void wxFont::SetWeight(int weight)
362 {
363 Unshare();
364
365 M_FONTDATA->m_weight = weight;
366 }
367
368 void wxFont::SetFaceName(const wxString& faceName)
369 {
370 Unshare();
371
372 M_FONTDATA->m_faceName = faceName;
373 }
374
375 void wxFont::SetUnderlined(bool underlined)
376 {
377 Unshare();
378
379 M_FONTDATA->m_underlined = underlined;
380 }
381
382 void wxFont::SetEncoding(wxFontEncoding encoding)
383 {
384 Unshare();
385
386 M_FONTDATA->m_encoding = encoding;
387 }
388
389 // ----------------------------------------------------------------------------
390 // get internal representation of font
391 // ----------------------------------------------------------------------------
392
393 static GdkFont *g_systemDefaultGuiFont = (GdkFont*) NULL;
394
395 static GdkFont *GtkGetDefaultGuiFont()
396 {
397 if (!g_systemDefaultGuiFont)
398 {
399 GtkWidget *widget = gtk_button_new();
400 GtkStyle *def = gtk_rc_get_style( widget );
401 g_systemDefaultGuiFont = gdk_font_ref( def->font );
402 gtk_widget_destroy( widget );
403 }
404 return g_systemDefaultGuiFont;
405 }
406
407 GdkFont *wxFont::GetInternalFont( float scale ) const
408 {
409 if (!Ok())
410 {
411 wxFAIL_MSG( wxT("invalid font") );
412
413 return (GdkFont*) NULL;
414 }
415
416 long int_scale = long(scale * 100.0 + 0.5); /* key for fontlist */
417 int point_scale = (int)((M_FONTDATA->m_pointSize * 10 * int_scale) / 100);
418 GdkFont *font = (GdkFont *) NULL;
419
420 wxNode *node = M_FONTDATA->m_scaled_xfonts.Find(int_scale);
421 if (node)
422 {
423 font = (GdkFont*)node->Data();
424 }
425 else
426 {
427 if (*this == wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT))
428 {
429 font = GtkGetDefaultGuiFont();
430 }
431 else
432 {
433 font = wxLoadQueryNearestFont( point_scale,
434 M_FONTDATA->m_family,
435 M_FONTDATA->m_style,
436 M_FONTDATA->m_weight,
437 M_FONTDATA->m_underlined,
438 M_FONTDATA->m_faceName,
439 M_FONTDATA->m_encoding );
440 }
441
442 M_FONTDATA->m_scaled_xfonts.Append( int_scale, (wxObject*)font );
443 }
444
445 // it's quite useless to make it a wxCHECK because we're going to crash
446 // anyhow...
447 wxASSERT_MSG( font, wxT("could not load any font?") );
448
449 return font;
450 }
451