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