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