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