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