]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/font.cpp
implemented Alex's <object_ref> symlinks in XRC
[wxWidgets.git] / src / gtk1 / 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
0c5d3e1c
VZ
149// ----------------------------------------------------------------------------
150// wxFont
151// ----------------------------------------------------------------------------
c801d85f
KB
152
153IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject)
154
0c5d3e1c 155void wxFont::Init()
c801d85f 156{
ff7b1510 157}
c801d85f 158
30764ab5
VZ
159wxFont::wxFont(const wxNativeFontInfo& info)
160{
7826e2dd
VZ
161 Init();
162
09fcd889 163 Create(info.xFontName);
7826e2dd
VZ
164}
165
166bool wxFont::Create(const wxNativeFontInfo& info)
167{
168 return Create(info.xFontName);
30764ab5
VZ
169}
170
171bool wxFont::Create( int pointSize,
172 int family,
173 int style,
174 int weight,
175 bool underlined,
176 const wxString& face,
7826e2dd 177 wxFontEncoding encoding)
30764ab5
VZ
178{
179 m_refData = new wxFontRefData(pointSize, family, style, weight,
7826e2dd 180 underlined, face, encoding);
30764ab5
VZ
181
182 return TRUE;
183}
184
7826e2dd 185bool wxFont::Create(const wxString& fontname, wxFontEncoding enc)
c801d85f 186{
7826e2dd 187 if( !fontname )
30764ab5 188 {
a756f210 189 *this = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT);
30764ab5
VZ
190 return TRUE;
191 }
7beba2fc 192
8bbe427f
VZ
193 m_refData = new wxFontRefData();
194
30764ab5
VZ
195 M_FONTDATA->m_nativeFontInfo.xFontName = fontname; // X font name
196
8636aed8 197 wxString tmp;
284b4c88 198
223d09f6 199 wxStringTokenizer tn( fontname, wxT("-") );
284b4c88 200
a7987cc1 201 tn.GetNextToken(); // skip initial empty token
8636aed8 202 tn.GetNextToken(); // foundry
284b4c88 203
30764ab5 204
36f210c8 205 M_FONTDATA->m_faceName = tn.GetNextToken(); // family
8636aed8 206
36f210c8 207 tmp = tn.GetNextToken().MakeUpper(); // weight
223d09f6 208 if (tmp == wxT("BOLD")) M_FONTDATA->m_weight = wxBOLD;
30760ce7
RR
209 if (tmp == wxT("BLACK")) M_FONTDATA->m_weight = wxBOLD;
210 if (tmp == wxT("EXTRABOLD")) M_FONTDATA->m_weight = wxBOLD;
211 if (tmp == wxT("DEMIBOLD")) M_FONTDATA->m_weight = wxBOLD;
212 if (tmp == wxT("ULTRABOLD")) M_FONTDATA->m_weight = wxBOLD;
213
214 if (tmp == wxT("LIGHT")) M_FONTDATA->m_weight = wxLIGHT;
215 if (tmp == wxT("THIN")) M_FONTDATA->m_weight = wxLIGHT;
7beba2fc 216
36f210c8 217 tmp = tn.GetNextToken().MakeUpper(); // slant
223d09f6
KB
218 if (tmp == wxT("I")) M_FONTDATA->m_style = wxITALIC;
219 if (tmp == wxT("O")) M_FONTDATA->m_style = wxITALIC;
284b4c88 220
8636aed8 221 tn.GetNextToken(); // set width
36f210c8 222 tn.GetNextToken(); // add. style
8636aed8 223 tn.GetNextToken(); // pixel size
284b4c88 224
8636aed8 225 tmp = tn.GetNextToken(); // pointsize
d06b34a7
RR
226 if (tmp != wxT("*"))
227 {
228 long num = wxStrtol (tmp.c_str(), (wxChar **) NULL, 10);
229 M_FONTDATA->m_pointSize = (int)(num / 10);
230 }
284b4c88 231
8636aed8
RR
232 tn.GetNextToken(); // x-res
233 tn.GetNextToken(); // y-res
284b4c88 234
36f210c8
VZ
235 tmp = tn.GetNextToken().MakeUpper(); // spacing
236
237 if (tmp == wxT("M"))
238 M_FONTDATA->m_family = wxMODERN;
239 else if (M_FONTDATA->m_faceName == wxT("TIMES"))
240 M_FONTDATA->m_family = wxROMAN;
241 else if (M_FONTDATA->m_faceName == wxT("HELVETICA"))
242 M_FONTDATA->m_family = wxSWISS;
243 else if (M_FONTDATA->m_faceName == wxT("LUCIDATYPEWRITER"))
244 M_FONTDATA->m_family = wxTELETYPE;
245 else if (M_FONTDATA->m_faceName == wxT("LUCIDA"))
246 M_FONTDATA->m_family = wxDECORATIVE;
247 else if (M_FONTDATA->m_faceName == wxT("UTOPIA"))
248 M_FONTDATA->m_family = wxSCRIPT;
249
250 tn.GetNextToken(); // avg width
251
252 // deal with font encoding
7826e2dd 253 M_FONTDATA->m_encoding = enc;
7beba2fc 254 if ( M_FONTDATA->m_encoding == wxFONTENCODING_SYSTEM )
36f210c8 255 {
7beba2fc
VZ
256 wxString registry = tn.GetNextToken().MakeUpper(),
257 encoding = tn.GetNextToken().MakeUpper();
258
259 if ( registry == _T("ISO8859") )
36f210c8 260 {
7beba2fc
VZ
261 int cp;
262 if ( wxSscanf(encoding, wxT("%d"), &cp) == 1 )
263 {
264 M_FONTDATA->m_encoding =
265 (wxFontEncoding)(wxFONTENCODING_ISO8859_1 + cp - 1);
266 }
36f210c8 267 }
7beba2fc 268 else if ( registry == _T("MICROSOFT") )
36f210c8 269 {
7beba2fc
VZ
270 int cp;
271 if ( wxSscanf(encoding, wxT("cp125%d"), &cp) == 1 )
272 {
273 M_FONTDATA->m_encoding =
274 (wxFontEncoding)(wxFONTENCODING_CP1250 + cp);
275 }
36f210c8 276 }
7beba2fc
VZ
277 else if ( registry == _T("KOI8") )
278 {
279 M_FONTDATA->m_encoding = wxFONTENCODING_KOI8;
280 }
281 //else: unknown encoding - may be give a warning here?
30764ab5
VZ
282 else
283 return FALSE;
36f210c8 284 }
0c5d3e1c 285 return TRUE;
ff7b1510 286}
c801d85f 287
0c5d3e1c 288void wxFont::Unshare()
8bbe427f 289{
0c5d3e1c
VZ
290 if (!m_refData)
291 {
292 m_refData = new wxFontRefData();
293 }
294 else
295 {
296 wxFontRefData* ref = new wxFontRefData(*(wxFontRefData*)m_refData);
297 UnRef();
298 m_refData = ref;
299 }
ff7b1510 300}
c801d85f 301
8bbe427f 302wxFont::~wxFont()
c801d85f 303{
ff7b1510 304}
c801d85f 305
0c5d3e1c
VZ
306// ----------------------------------------------------------------------------
307// accessors
308// ----------------------------------------------------------------------------
c801d85f 309
53f6aab7
VZ
310bool wxFont::HasNativeFont() const
311{
312 return !M_FONTDATA->m_nativeFontInfo.xFontName.empty();
313}
314
8bbe427f 315int wxFont::GetPointSize() const
c801d85f 316{
223d09f6 317 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
8bbe427f
VZ
318
319 return M_FONTDATA->m_pointSize;
ff7b1510 320}
c801d85f 321
8bbe427f 322wxString wxFont::GetFaceName() const
c801d85f 323{
223d09f6 324 wxCHECK_MSG( Ok(), wxT(""), wxT("invalid font") );
8bbe427f 325
36b3b54a 326 return M_FONTDATA->m_faceName;
ff7b1510 327}
c801d85f 328
8bbe427f 329int wxFont::GetFamily() const
c801d85f 330{
223d09f6 331 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
8bbe427f
VZ
332
333 return M_FONTDATA->m_family;
ff7b1510 334}
c801d85f 335
8bbe427f 336int wxFont::GetStyle() const
c801d85f 337{
223d09f6 338 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
d84eb083 339
8bbe427f 340 return M_FONTDATA->m_style;
ff7b1510 341}
c801d85f 342
8bbe427f 343int wxFont::GetWeight() const
c801d85f 344{
223d09f6 345 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
8bbe427f
VZ
346
347 return M_FONTDATA->m_weight;
348}
349
8bbe427f
VZ
350bool wxFont::GetUnderlined() const
351{
223d09f6 352 wxCHECK_MSG( Ok(), FALSE, wxT("invalid font") );
8bbe427f
VZ
353
354 return M_FONTDATA->m_underlined;
ff7b1510 355}
c801d85f 356
0c5d3e1c
VZ
357
358wxFontEncoding wxFont::GetEncoding() const
358fc25c 359{
223d09f6 360 wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT, wxT("invalid font") );
0c5d3e1c
VZ
361
362 return M_FONTDATA->m_encoding;
358fc25c
RR
363}
364
7826e2dd 365wxNativeFontInfo *wxFont::GetNativeFontInfo() const
30764ab5 366{
7826e2dd 367 wxCHECK_MSG( Ok(), (wxNativeFontInfo *)NULL, wxT("invalid font") );
30764ab5
VZ
368
369 if(M_FONTDATA->m_nativeFontInfo.xFontName.IsEmpty())
370 GetInternalFont();
7826e2dd
VZ
371
372 return new wxNativeFontInfo(M_FONTDATA->m_nativeFontInfo);
30764ab5
VZ
373}
374
53f6aab7
VZ
375bool wxFont::IsFixedWidth() const
376{
377 wxCHECK_MSG( Ok(), FALSE, wxT("invalid font") );
378
379 if ( HasNativeFont() )
380 {
381 // the monospace fonts are supposed to have "M" in the spacing field
382 wxString spacing = M_FONTDATA->
383 m_nativeFontInfo.GetXFontComponent(wxXLFD_SPACING);
384
385 return spacing.Upper() == _T('M');
386 }
387
388 return wxFontBase::IsFixedWidth();
389}
30764ab5 390
0c5d3e1c
VZ
391// ----------------------------------------------------------------------------
392// change font attributes
393// ----------------------------------------------------------------------------
394
358fc25c
RR
395void wxFont::SetPointSize(int pointSize)
396{
397 Unshare();
398
399 M_FONTDATA->m_pointSize = pointSize;
30764ab5 400 M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now
358fc25c
RR
401}
402
403void wxFont::SetFamily(int family)
404{
405 Unshare();
406
407 M_FONTDATA->m_family = family;
30764ab5 408 M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now
358fc25c
RR
409}
410
411void wxFont::SetStyle(int style)
412{
413 Unshare();
414
415 M_FONTDATA->m_style = style;
30764ab5 416 M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now
358fc25c
RR
417}
418
419void wxFont::SetWeight(int weight)
420{
421 Unshare();
422
423 M_FONTDATA->m_weight = weight;
30764ab5 424 M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now
358fc25c
RR
425}
426
427void wxFont::SetFaceName(const wxString& faceName)
428{
429 Unshare();
430
431 M_FONTDATA->m_faceName = faceName;
30764ab5 432 M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now
358fc25c
RR
433}
434
435void wxFont::SetUnderlined(bool underlined)
436{
437 Unshare();
438
439 M_FONTDATA->m_underlined = underlined;
440}
441
0c5d3e1c
VZ
442void wxFont::SetEncoding(wxFontEncoding encoding)
443{
444 Unshare();
c801d85f 445
0c5d3e1c 446 M_FONTDATA->m_encoding = encoding;
30764ab5
VZ
447 M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now
448}
449
450void wxFont::SetNativeFontInfo(const wxNativeFontInfo& info)
451{
452 Unshare();
453
454 M_FONTDATA->m_nativeFontInfo = info;
0c5d3e1c
VZ
455}
456
457// ----------------------------------------------------------------------------
458// get internal representation of font
459// ----------------------------------------------------------------------------
c801d85f 460
c7985368
RR
461static GdkFont *g_systemDefaultGuiFont = (GdkFont*) NULL;
462
f6bcfd97 463GdkFont *GtkGetDefaultGuiFont()
c7985368
RR
464{
465 if (!g_systemDefaultGuiFont)
466 {
467 GtkWidget *widget = gtk_button_new();
468 GtkStyle *def = gtk_rc_get_style( widget );
e6527f9d
RR
469 if (def)
470 {
471 g_systemDefaultGuiFont = gdk_font_ref( def->font );
472 }
473 else
474 {
475 def = gtk_widget_get_default_style();
476 if (def)
477 g_systemDefaultGuiFont = gdk_font_ref( def->font );
478 }
c7985368
RR
479 gtk_widget_destroy( widget );
480 }
b1d1dc51
VZ
481 else
482 {
483 // already have it, but ref it once more before returning
484 gdk_font_ref(g_systemDefaultGuiFont);
485 }
486
c7985368
RR
487 return g_systemDefaultGuiFont;
488}
489
36b3b54a 490GdkFont *wxFont::GetInternalFont( float scale ) const
c801d85f 491{
8bbe427f
VZ
492 if (!Ok())
493 {
223d09f6 494 wxFAIL_MSG( wxT("invalid font") );
0c5d3e1c 495
8bbe427f
VZ
496 return (GdkFont*) NULL;
497 }
498
36b3b54a 499 long int_scale = long(scale * 100.0 + 0.5); /* key for fontlist */
b02da6b1 500 int point_scale = (int)((M_FONTDATA->m_pointSize * 10 * int_scale) / 100);
8bbe427f
VZ
501 GdkFont *font = (GdkFont *) NULL;
502
503 wxNode *node = M_FONTDATA->m_scaled_xfonts.Find(int_scale);
504 if (node)
505 {
506 font = (GdkFont*)node->Data();
507 }
508 else
509 {
a756f210 510 if (*this == wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT))
8bbe427f 511 {
c7985368 512 font = GtkGetDefaultGuiFont();
8bbe427f 513 }
e6527f9d 514 if (!font)
8bbe427f 515 {
0c5d3e1c
VZ
516 font = wxLoadQueryNearestFont( point_scale,
517 M_FONTDATA->m_family,
518 M_FONTDATA->m_style,
519 M_FONTDATA->m_weight,
520 M_FONTDATA->m_underlined,
521 M_FONTDATA->m_faceName,
30764ab5
VZ
522 M_FONTDATA->m_encoding,
523 &M_FONTDATA->m_nativeFontInfo.xFontName );
8bbe427f 524 }
0c5d3e1c 525
8bbe427f
VZ
526 M_FONTDATA->m_scaled_xfonts.Append( int_scale, (wxObject*)font );
527 }
284b4c88 528
7beba2fc
VZ
529 // it's quite useless to make it a wxCHECK because we're going to crash
530 // anyhow...
531 wxASSERT_MSG( font, wxT("could not load any font?") );
284b4c88 532
8bbe427f 533 return font;
ff7b1510 534}
c801d85f 535