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