]> git.saurik.com Git - wxWidgets.git/blob - src/x11/font.cpp
survive delete within Notify
[wxWidgets.git] / src / x11 / font.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/x11/font.cpp
3 // Purpose: wxFont class
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 17/09/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "font.h"
22 #endif
23
24 #ifdef __VMS
25 #pragma message disable nosimpint
26 #include "wx/vms_x_fix.h"
27 #endif
28
29 #ifdef __VMS
30 #pragma message enable nosimpint
31 #endif
32
33 #include "wx/defs.h"
34 #include "wx/string.h"
35 #include "wx/font.h"
36 #include "wx/gdicmn.h"
37 #include "wx/utils.h" // for wxGetDisplay()
38 #include "wx/fontutil.h" // for wxNativeFontInfo
39 #include "wx/tokenzr.h"
40 #include "wx/settings.h"
41 #include "wx/x11/private.h"
42
43 IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject)
44
45 // ----------------------------------------------------------------------------
46 // private classes
47 // ----------------------------------------------------------------------------
48
49 // For every wxFont, there must be a font for each display and scale requested.
50 // So these objects are stored in wxFontRefData::m_fonts
51 class wxXFont : public wxObject
52 {
53 public:
54 wxXFont();
55 ~wxXFont();
56
57 WXFontStructPtr m_fontStruct; // XFontStruct
58 WXDisplay* m_display; // XDisplay
59 int m_scale; // Scale * 100
60 };
61
62 class wxFontRefData: public wxGDIRefData
63 {
64 friend class wxFont;
65
66 public:
67 wxFontRefData(int size = wxDEFAULT,
68 int family = wxDEFAULT,
69 int style = wxDEFAULT,
70 int weight = wxDEFAULT,
71 bool underlined = FALSE,
72 const wxString& faceName = wxEmptyString,
73 wxFontEncoding encoding = wxFONTENCODING_DEFAULT)
74 {
75 Init(size, family, style, weight, underlined, faceName, encoding);
76 }
77
78 wxFontRefData(const wxFontRefData& data)
79 {
80 Init(data.m_pointSize, data.m_family, data.m_style, data.m_weight,
81 data.m_underlined, data.m_faceName, data.m_encoding);
82 }
83
84 ~wxFontRefData();
85
86 protected:
87 // common part of all ctors
88 void Init(int size,
89 int family,
90 int style,
91 int weight,
92 bool underlined,
93 const wxString& faceName,
94 wxFontEncoding encoding);
95
96 // font attributes
97 int m_pointSize;
98 int m_family;
99 int m_style;
100 int m_weight;
101 bool m_underlined;
102 wxString m_faceName;
103 wxFontEncoding m_encoding;
104
105 wxNativeFontInfo m_nativeFontInfo;
106
107 // A list of wxXFonts
108 wxList m_fonts;
109 };
110
111 // ============================================================================
112 // implementation
113 // ============================================================================
114
115 // ----------------------------------------------------------------------------
116 // wxXFont
117 // ----------------------------------------------------------------------------
118
119 wxXFont::wxXFont()
120 {
121 m_fontStruct = (WXFontStructPtr) 0;
122 m_display = (WXDisplay*) 0;
123 m_scale = 100;
124 }
125
126 wxXFont::~wxXFont()
127 {
128 // TODO: why does freeing the font produce a segv???
129 // Note that XFreeFont wasn't called in wxWin 1.68 either.
130 // XFontStruct* fontStruct = (XFontStruct*) m_fontStruct;
131 // XFreeFont((Display*) m_display, fontStruct);
132 }
133
134 // ----------------------------------------------------------------------------
135 // wxFontRefData
136 // ----------------------------------------------------------------------------
137
138 void wxFontRefData::Init(int pointSize,
139 int family,
140 int style,
141 int weight,
142 bool underlined,
143 const wxString& faceName,
144 wxFontEncoding encoding)
145 {
146 if (family == wxDEFAULT)
147 m_family = wxSWISS;
148 else
149 m_family = family;
150
151 m_faceName = faceName;
152
153 if (style == wxDEFAULT)
154 m_style = wxNORMAL;
155 else
156 m_style = style;
157
158 if (weight == wxDEFAULT)
159 m_weight = wxNORMAL;
160 else
161 m_weight = weight;
162
163 if (pointSize == wxDEFAULT)
164 m_pointSize = 12;
165 else
166 m_pointSize = pointSize;
167
168 m_underlined = underlined;
169 m_encoding = encoding;
170 }
171
172 wxFontRefData::~wxFontRefData()
173 {
174 wxNode* node = m_fonts.First();
175 while (node)
176 {
177 wxXFont* f = (wxXFont*) node->Data();
178 delete f;
179 node = node->Next();
180 }
181 m_fonts.Clear();
182 }
183
184 // ----------------------------------------------------------------------------
185 // wxFont
186 // ----------------------------------------------------------------------------
187
188 wxFont::wxFont(const wxNativeFontInfo& info)
189 {
190 Init();
191
192 (void)Create(info.GetXFontName());
193 }
194
195 void wxFont::Init()
196 {
197 }
198
199 bool wxFont::Create(int pointSize,
200 int family,
201 int style,
202 int weight,
203 bool underlined,
204 const wxString& faceName,
205 wxFontEncoding encoding)
206 {
207 UnRef();
208 m_refData = new wxFontRefData(pointSize, family, style, weight,
209 underlined, faceName, encoding);
210
211 RealizeResource();
212
213 return TRUE;
214 }
215
216 bool wxFont::Create(const wxString& fontname, wxFontEncoding enc)
217 {
218 if( !fontname )
219 {
220 *this = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT);
221 return TRUE;
222 }
223
224 m_refData = new wxFontRefData();
225
226 M_FONTDATA->m_nativeFontInfo.SetXFontName(fontname); // X font name
227
228 wxString tmp;
229
230 wxStringTokenizer tn( fontname, wxT("-") );
231
232 tn.GetNextToken(); // skip initial empty token
233 tn.GetNextToken(); // foundry
234
235
236 M_FONTDATA->m_faceName = tn.GetNextToken(); // family
237
238 tmp = tn.GetNextToken().MakeUpper(); // weight
239 if (tmp == wxT("BOLD")) M_FONTDATA->m_weight = wxBOLD;
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;
247
248 tmp = tn.GetNextToken().MakeUpper(); // slant
249 if (tmp == wxT("I")) M_FONTDATA->m_style = wxITALIC;
250 if (tmp == wxT("O")) M_FONTDATA->m_style = wxITALIC;
251
252 tn.GetNextToken(); // set width
253 tn.GetNextToken(); // add. style
254 tn.GetNextToken(); // pixel size
255
256 tmp = tn.GetNextToken(); // pointsize
257 if (tmp != wxT("*"))
258 {
259 long num = wxStrtol (tmp.c_str(), (wxChar **) NULL, 10);
260 M_FONTDATA->m_pointSize = (int)(num / 10);
261 }
262
263 tn.GetNextToken(); // x-res
264 tn.GetNextToken(); // y-res
265
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
284 M_FONTDATA->m_encoding = enc;
285 if ( M_FONTDATA->m_encoding == wxFONTENCODING_SYSTEM )
286 {
287 wxString registry = tn.GetNextToken().MakeUpper(),
288 encoding = tn.GetNextToken().MakeUpper();
289
290 if ( registry == _T("ISO8859") )
291 {
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 }
298 }
299 else if ( registry == _T("MICROSOFT") )
300 {
301 int cp;
302 if ( wxSscanf(encoding, wxT("cp125%d"), &cp) == 1 )
303 {
304 M_FONTDATA->m_encoding =
305 (wxFontEncoding)(wxFONTENCODING_CP1250 + cp);
306 }
307 }
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?
313 else
314 return FALSE;
315 }
316 return TRUE;
317 }
318
319 wxFont::~wxFont()
320 {
321 }
322
323 // ----------------------------------------------------------------------------
324 // change the font attributes
325 // ----------------------------------------------------------------------------
326
327 void wxFont::Unshare()
328 {
329 // Don't change shared data
330 if (!m_refData)
331 {
332 m_refData = new wxFontRefData();
333 }
334 else
335 {
336 wxFontRefData* ref = new wxFontRefData(*(wxFontRefData*)m_refData);
337 UnRef();
338 m_refData = ref;
339 }
340 }
341
342 void wxFont::SetPointSize(int pointSize)
343 {
344 Unshare();
345
346 M_FONTDATA->m_pointSize = pointSize;
347 M_FONTDATA->m_nativeFontInfo.GetXFontName().Clear(); // invalid now
348
349 RealizeResource();
350 }
351
352 void wxFont::SetFamily(int family)
353 {
354 Unshare();
355
356 M_FONTDATA->m_family = family;
357 M_FONTDATA->m_nativeFontInfo.GetXFontName().Clear(); // invalid now
358
359 RealizeResource();
360 }
361
362 void wxFont::SetStyle(int style)
363 {
364 Unshare();
365
366 M_FONTDATA->m_style = style;
367 M_FONTDATA->m_nativeFontInfo.GetXFontName().Clear(); // invalid now
368
369 RealizeResource();
370 }
371
372 void wxFont::SetWeight(int weight)
373 {
374 Unshare();
375
376 M_FONTDATA->m_weight = weight;
377 M_FONTDATA->m_nativeFontInfo.GetXFontName().Clear(); // invalid now
378
379 RealizeResource();
380 }
381
382 void wxFont::SetFaceName(const wxString& faceName)
383 {
384 Unshare();
385
386 M_FONTDATA->m_faceName = faceName;
387 M_FONTDATA->m_nativeFontInfo.GetXFontName().Clear(); // invalid now
388
389 RealizeResource();
390 }
391
392 void wxFont::SetUnderlined(bool underlined)
393 {
394 Unshare();
395
396 M_FONTDATA->m_underlined = underlined;
397
398 RealizeResource();
399 }
400
401 void wxFont::SetEncoding(wxFontEncoding encoding)
402 {
403 Unshare();
404
405 M_FONTDATA->m_encoding = encoding;
406 M_FONTDATA->m_nativeFontInfo.GetXFontName().Clear(); // invalid now
407
408 RealizeResource();
409 }
410
411 void wxFont::SetNativeFontInfo(const wxNativeFontInfo& info)
412 {
413 Unshare();
414
415 M_FONTDATA->m_nativeFontInfo = info;
416 }
417
418 // ----------------------------------------------------------------------------
419 // query font attributes
420 // ----------------------------------------------------------------------------
421
422 int wxFont::GetPointSize() const
423 {
424 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
425
426 return M_FONTDATA->m_pointSize;
427 }
428
429 wxString wxFont::GetFaceName() const
430 {
431 wxCHECK_MSG( Ok(), wxT(""), wxT("invalid font") );
432
433 return M_FONTDATA->m_faceName ;
434 }
435
436 int wxFont::GetFamily() const
437 {
438 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
439
440 return M_FONTDATA->m_family;
441 }
442
443 int wxFont::GetStyle() const
444 {
445 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
446
447 return M_FONTDATA->m_style;
448 }
449
450 int wxFont::GetWeight() const
451 {
452 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
453
454 return M_FONTDATA->m_weight;
455 }
456
457 bool wxFont::GetUnderlined() const
458 {
459 wxCHECK_MSG( Ok(), FALSE, wxT("invalid font") );
460
461 return M_FONTDATA->m_underlined;
462 }
463
464 wxFontEncoding wxFont::GetEncoding() const
465 {
466 wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT, wxT("invalid font") );
467
468 return M_FONTDATA->m_encoding;
469 }
470
471 wxNativeFontInfo *wxFont::GetNativeFontInfo() const
472 {
473 wxCHECK_MSG( Ok(), (wxNativeFontInfo *)NULL, wxT("invalid font") );
474
475 if(M_FONTDATA->m_nativeFontInfo.GetXFontName().IsEmpty())
476 GetInternalFont();
477
478 return new wxNativeFontInfo(M_FONTDATA->m_nativeFontInfo);
479 }
480
481 // ----------------------------------------------------------------------------
482 // real implementation
483 // ----------------------------------------------------------------------------
484
485 // Find an existing, or create a new, XFontStruct
486 // based on this wxFont and the given scale. Append the
487 // font to list in the private data for future reference.
488 wxXFont* wxFont::GetInternalFont(double scale, WXDisplay* display) const
489 {
490 if ( !Ok() )
491 return (wxXFont *)NULL;
492
493 long intScale = long(scale * 100.0 + 0.5); // key for wxXFont
494 int pointSize = (M_FONTDATA->m_pointSize * 10 * intScale) / 100;
495
496 // search existing fonts first
497 wxNode* node = M_FONTDATA->m_fonts.First();
498 while (node)
499 {
500 wxXFont* f = (wxXFont*) node->Data();
501 if ((!display || (f->m_display == display)) && (f->m_scale == intScale))
502 return f;
503 node = node->Next();
504 }
505
506 // not found, create a new one
507 XFontStruct *font = (XFontStruct *)
508 wxLoadQueryNearestFont(pointSize,
509 M_FONTDATA->m_family,
510 M_FONTDATA->m_style,
511 M_FONTDATA->m_weight,
512 M_FONTDATA->m_underlined,
513 wxT(""),
514 M_FONTDATA->m_encoding);
515
516 if ( !font )
517 {
518 wxFAIL_MSG( wxT("Could not allocate even a default font -- something is wrong.") );
519
520 return (wxXFont*) NULL;
521 }
522
523 wxXFont* f = new wxXFont;
524 f->m_fontStruct = (WXFontStructPtr)font;
525 f->m_display = ( display ? display : wxGetDisplay() );
526 f->m_scale = intScale;
527 M_FONTDATA->m_fonts.Append(f);
528
529 return f;
530 }
531
532 WXFontStructPtr wxFont::GetFontStruct(double scale, WXDisplay* display) const
533 {
534 wxXFont* f = GetInternalFont(scale, display);
535
536 return (f ? f->m_fontStruct : (WXFontStructPtr) 0);
537 }
538