1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/motif/font.cpp
3 // Purpose: wxFont class
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "font.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
30 #pragma message disable nosimpint
31 #include "wx/vms_x_fix.h"
35 #pragma message enable nosimpint
38 #include "wx/string.h"
40 #include "wx/gdicmn.h"
41 #include "wx/utils.h" // for wxGetDisplay()
42 #include "wx/fontutil.h" // for wxNativeFontInfo
43 #include "wx/tokenzr.h"
44 #include "wx/settings.h"
45 #include "wx/motif/private.h"
47 IMPLEMENT_DYNAMIC_CLASS(wxFont
, wxGDIObject
)
49 #if wxCHECK_MOTIF_VERSION( 2, 0 ) && !wxCHECK_LESSTIF()
50 #define wxUSE_RENDER_TABLE 1
52 #define wxUSE_RENDER_TABLE 0
55 // ----------------------------------------------------------------------------
57 // ----------------------------------------------------------------------------
59 // For every wxFont, there must be a font for each display and scale requested.
60 // So these objects are stored in wxFontRefData::m_fonts
61 class wxXFont
: public wxObject
67 WXFontStructPtr m_fontStruct
; // XFontStruct
68 #if !wxUSE_RENDER_TABLE
69 WXFontList m_fontList
; // Motif XmFontList
70 #else // if wxUSE_RENDER_TABLE
71 WXRenderTable m_renderTable
; // Motif XmRenderTable
73 WXDisplay
* m_display
; // XDisplay
74 int m_scale
; // Scale * 100
77 class wxFontRefData
: public wxGDIRefData
82 wxFontRefData(int size
= wxDEFAULT
,
83 int family
= wxDEFAULT
,
84 int style
= wxDEFAULT
,
85 int weight
= wxDEFAULT
,
86 bool underlined
= false,
87 const wxString
& faceName
= wxEmptyString
,
88 wxFontEncoding encoding
= wxFONTENCODING_DEFAULT
)
90 Init(size
, family
, style
, weight
, underlined
, faceName
, encoding
);
93 wxFontRefData(const wxFontRefData
& data
)
95 Init(data
.m_pointSize
, data
.m_family
, data
.m_style
, data
.m_weight
,
96 data
.m_underlined
, data
.m_faceName
, data
.m_encoding
);
102 // common part of all ctors
108 const wxString
& faceName
,
109 wxFontEncoding encoding
);
118 wxFontEncoding m_encoding
;
120 wxNativeFontInfo m_nativeFontInfo
;
122 // A list of wxXFonts
126 // ============================================================================
128 // ============================================================================
130 // ----------------------------------------------------------------------------
132 // ----------------------------------------------------------------------------
136 m_fontStruct
= (WXFontStructPtr
) 0;
137 #if !wxUSE_RENDER_TABLE
138 m_fontList
= (WXFontList
) 0;
139 #else // if wxUSE_RENDER_TABLE
140 m_renderTable
= (WXRenderTable
) 0;
142 m_display
= (WXDisplay
*) 0;
148 #if !wxUSE_RENDER_TABLE
150 XmFontListFree ((XmFontList
) m_fontList
);
152 #else // if wxUSE_RENDER_TABLE
154 XmRenderTableFree ((XmRenderTable
) m_renderTable
);
155 m_renderTable
= NULL
;
158 // TODO: why does freeing the font produce a segv???
159 // Note that XFreeFont wasn't called in wxWin 1.68 either.
160 // MBN: probably some interaction with fonts being still
161 // in use in some widgets...
162 // XFontStruct* fontStruct = (XFontStruct*) m_fontStruct;
163 // XFreeFont((Display*) m_display, fontStruct);
166 // ----------------------------------------------------------------------------
168 // ----------------------------------------------------------------------------
170 void wxFontRefData::Init(int pointSize
,
175 const wxString
& faceName
,
176 wxFontEncoding encoding
)
178 if (family
== wxDEFAULT
)
183 m_faceName
= faceName
;
185 if (style
== wxDEFAULT
)
190 if (weight
== wxDEFAULT
)
195 if (pointSize
== wxDEFAULT
)
198 m_pointSize
= pointSize
;
200 m_underlined
= underlined
;
201 m_encoding
= encoding
;
204 wxFontRefData::~wxFontRefData()
206 wxList::compatibility_iterator node
= m_fonts
.GetFirst();
209 wxXFont
* f
= (wxXFont
*) node
->GetData();
211 node
= node
->GetNext();
216 // ----------------------------------------------------------------------------
218 // ----------------------------------------------------------------------------
220 wxFont::wxFont(const wxNativeFontInfo
& info
)
224 (void)Create(info
.GetXFontName());
231 bool wxFont::Create(int pointSize
,
236 const wxString
& faceName
,
237 wxFontEncoding encoding
)
240 m_refData
= new wxFontRefData(pointSize
, family
, style
, weight
,
241 underlined
, faceName
, encoding
);
248 bool wxFont::Create(const wxString
& fontname
, wxFontEncoding enc
)
252 *this = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT
);
256 m_refData
= new wxFontRefData();
258 M_FONTDATA
->m_nativeFontInfo
.SetXFontName(fontname
); // X font name
262 wxStringTokenizer
tn( fontname
, wxT("-") );
264 tn
.GetNextToken(); // skip initial empty token
265 tn
.GetNextToken(); // foundry
268 M_FONTDATA
->m_faceName
= tn
.GetNextToken(); // family
270 tmp
= tn
.GetNextToken().MakeUpper(); // weight
271 if (tmp
== wxT("BOLD")) M_FONTDATA
->m_weight
= wxBOLD
;
272 if (tmp
== wxT("BLACK")) M_FONTDATA
->m_weight
= wxBOLD
;
273 if (tmp
== wxT("EXTRABOLD")) M_FONTDATA
->m_weight
= wxBOLD
;
274 if (tmp
== wxT("DEMIBOLD")) M_FONTDATA
->m_weight
= wxBOLD
;
275 if (tmp
== wxT("ULTRABOLD")) M_FONTDATA
->m_weight
= wxBOLD
;
277 if (tmp
== wxT("LIGHT")) M_FONTDATA
->m_weight
= wxLIGHT
;
278 if (tmp
== wxT("THIN")) M_FONTDATA
->m_weight
= wxLIGHT
;
280 tmp
= tn
.GetNextToken().MakeUpper(); // slant
281 if (tmp
== wxT("I")) M_FONTDATA
->m_style
= wxITALIC
;
282 if (tmp
== wxT("O")) M_FONTDATA
->m_style
= wxITALIC
;
284 tn
.GetNextToken(); // set width
285 tn
.GetNextToken(); // add. style
286 tn
.GetNextToken(); // pixel size
288 tmp
= tn
.GetNextToken(); // pointsize
291 long num
= wxStrtol (tmp
.c_str(), (wxChar
**) NULL
, 10);
292 M_FONTDATA
->m_pointSize
= (int)(num
/ 10);
295 tn
.GetNextToken(); // x-res
296 tn
.GetNextToken(); // y-res
298 tmp
= tn
.GetNextToken().MakeUpper(); // spacing
301 M_FONTDATA
->m_family
= wxMODERN
;
302 else if (M_FONTDATA
->m_faceName
== wxT("TIMES"))
303 M_FONTDATA
->m_family
= wxROMAN
;
304 else if (M_FONTDATA
->m_faceName
== wxT("HELVETICA"))
305 M_FONTDATA
->m_family
= wxSWISS
;
306 else if (M_FONTDATA
->m_faceName
== wxT("LUCIDATYPEWRITER"))
307 M_FONTDATA
->m_family
= wxTELETYPE
;
308 else if (M_FONTDATA
->m_faceName
== wxT("LUCIDA"))
309 M_FONTDATA
->m_family
= wxDECORATIVE
;
310 else if (M_FONTDATA
->m_faceName
== wxT("UTOPIA"))
311 M_FONTDATA
->m_family
= wxSCRIPT
;
313 tn
.GetNextToken(); // avg width
315 // deal with font encoding
316 M_FONTDATA
->m_encoding
= enc
;
317 if ( M_FONTDATA
->m_encoding
== wxFONTENCODING_SYSTEM
)
319 wxString registry
= tn
.GetNextToken().MakeUpper(),
320 encoding
= tn
.GetNextToken().MakeUpper();
322 if ( registry
== _T("ISO8859") )
325 if ( wxSscanf(encoding
, wxT("%d"), &cp
) == 1 )
327 M_FONTDATA
->m_encoding
=
328 (wxFontEncoding
)(wxFONTENCODING_ISO8859_1
+ cp
- 1);
331 else if ( registry
== _T("MICROSOFT") )
334 if ( wxSscanf(encoding
, wxT("cp125%d"), &cp
) == 1 )
336 M_FONTDATA
->m_encoding
=
337 (wxFontEncoding
)(wxFONTENCODING_CP1250
+ cp
);
340 else if ( registry
== _T("KOI8") )
342 M_FONTDATA
->m_encoding
= wxFONTENCODING_KOI8
;
344 //else: unknown encoding - may be give a warning here?
355 // ----------------------------------------------------------------------------
356 // change the font attributes
357 // ----------------------------------------------------------------------------
359 void wxFont::Unshare()
361 // Don't change shared data
364 m_refData
= new wxFontRefData();
368 wxFontRefData
* ref
= new wxFontRefData(*(wxFontRefData
*)m_refData
);
374 void wxFont::SetPointSize(int pointSize
)
378 M_FONTDATA
->m_pointSize
= pointSize
;
379 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
384 void wxFont::SetFamily(int family
)
388 M_FONTDATA
->m_family
= family
;
389 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
394 void wxFont::SetStyle(int style
)
398 M_FONTDATA
->m_style
= style
;
399 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
404 void wxFont::SetWeight(int weight
)
408 M_FONTDATA
->m_weight
= weight
;
409 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
414 void wxFont::SetFaceName(const wxString
& faceName
)
418 M_FONTDATA
->m_faceName
= faceName
;
419 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
424 void wxFont::SetUnderlined(bool underlined
)
428 M_FONTDATA
->m_underlined
= underlined
;
433 void wxFont::SetEncoding(wxFontEncoding encoding
)
437 M_FONTDATA
->m_encoding
= encoding
;
438 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
443 void wxFont::DoSetNativeFontInfo(const wxNativeFontInfo
& info
)
447 M_FONTDATA
->m_nativeFontInfo
= info
;
450 // ----------------------------------------------------------------------------
451 // query font attributes
452 // ----------------------------------------------------------------------------
454 int wxFont::GetPointSize() const
456 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
458 return M_FONTDATA
->m_pointSize
;
461 wxString
wxFont::GetFaceName() const
463 wxCHECK_MSG( Ok(), wxT(""), wxT("invalid font") );
465 return M_FONTDATA
->m_faceName
;
468 int wxFont::GetFamily() const
470 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
472 return M_FONTDATA
->m_family
;
475 int wxFont::GetStyle() const
477 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
479 return M_FONTDATA
->m_style
;
482 int wxFont::GetWeight() const
484 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
486 return M_FONTDATA
->m_weight
;
489 bool wxFont::GetUnderlined() const
491 wxCHECK_MSG( Ok(), false, wxT("invalid font") );
493 return M_FONTDATA
->m_underlined
;
496 wxFontEncoding
wxFont::GetEncoding() const
498 wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT
, wxT("invalid font") );
500 return M_FONTDATA
->m_encoding
;
503 const wxNativeFontInfo
*wxFont::GetNativeFontInfo() const
505 wxCHECK_MSG( Ok(), (wxNativeFontInfo
*)NULL
, wxT("invalid font") );
507 if(M_FONTDATA
->m_nativeFontInfo
.GetXFontName().IsEmpty())
510 return &(M_FONTDATA
->m_nativeFontInfo
);
513 // ----------------------------------------------------------------------------
514 // real implementation
515 // ----------------------------------------------------------------------------
517 // Find an existing, or create a new, XFontStruct
518 // based on this wxFont and the given scale. Append the
519 // font to list in the private data for future reference.
520 wxXFont
* wxFont::GetInternalFont(double scale
, WXDisplay
* display
) const
523 return (wxXFont
*)NULL
;
525 long intScale
= long(scale
* 100.0 + 0.5); // key for wxXFont
526 int pointSize
= (M_FONTDATA
->m_pointSize
* 10 * intScale
) / 100;
528 // search existing fonts first
529 wxList::compatibility_iterator node
= M_FONTDATA
->m_fonts
.GetFirst();
532 wxXFont
* f
= (wxXFont
*) node
->GetData();
533 if ((!display
|| (f
->m_display
== display
)) && (f
->m_scale
== intScale
))
535 node
= node
->GetNext();
538 // not found, create a new one
539 XFontStruct
*font
= (XFontStruct
*)
540 wxLoadQueryNearestFont(pointSize
,
541 M_FONTDATA
->m_family
,
543 M_FONTDATA
->m_weight
,
544 M_FONTDATA
->m_underlined
,
546 M_FONTDATA
->m_encoding
);
550 wxFAIL_MSG( wxT("Could not allocate even a default font -- something is wrong.") );
552 return (wxXFont
*) NULL
;
555 wxXFont
* f
= new wxXFont
;
556 f
->m_fontStruct
= (WXFontStructPtr
)font
;
557 f
->m_display
= ( display
? display
: wxGetDisplay() );
558 f
->m_scale
= intScale
;
559 #if !wxUSE_RENDER_TABLE
560 f
->m_fontList
= XmFontListCreate ((XFontStruct
*) font
, XmSTRING_DEFAULT_CHARSET
);
561 M_FONTDATA
->m_fonts
.Append(f
);
562 #else // if wxUSE_RENDER_TABLE
563 XmRendition rendition
;
564 XmRenderTable renderTable
;
568 XtSetArg( args
[count
], XmNfont
, font
); ++count
;
569 XtSetArg( args
[count
], XmNunderlineType
,
570 GetUnderlined() ? XmSINGLE_LINE
: XmNO_LINE
); ++count
;
571 rendition
= XmRenditionCreate( XmGetXmDisplay( (Display
*)f
->m_display
),
574 renderTable
= XmRenderTableAddRenditions( NULL
, &rendition
, 1,
577 f
->m_renderTable
= (WXRenderTable
)renderTable
;
583 WXFontStructPtr
wxFont::GetFontStruct(double scale
, WXDisplay
* display
) const
585 wxXFont
* f
= GetInternalFont(scale
, display
);
587 return (f
? f
->m_fontStruct
: (WXFontStructPtr
) 0);
590 WXFontList
wxFont::GetFontList(double scale
, WXDisplay
* display
) const
592 #if !wxUSE_RENDER_TABLE
593 wxXFont
* f
= GetInternalFont(scale
, display
);
595 return (f
? f
->m_fontList
: (WXFontList
) 0);
601 // declared in the header, can't use wxUSE_RENDER_TABLE
602 #if wxCHECK_MOTIF_VERSION( 2, 0 )
604 WXRenderTable
wxFont::GetRenderTable(WXDisplay
* display
) const
606 #if wxUSE_RENDER_TABLE
607 wxXFont
* f
= GetInternalFont(1.0, display
);
609 return (f
? f
->m_renderTable
: (WXFontList
) 0);
617 WXFontType
wxFont::GetFontType(WXDisplay
* display
) const
619 #if wxUSE_RENDER_TABLE
620 return Ok() ? GetRenderTable(display
) : NULL
;
622 return Ok() ? GetFontList(1.0, display
) : NULL
;
626 WXFontType
wxFont::GetFontTypeC(WXDisplay
* display
) const
628 #if wxUSE_RENDER_TABLE
629 return Ok() ? GetRenderTable(display
) : NULL
;
631 return Ok() ? XmFontListCopy( (XmFontList
)GetFontList(1.0, display
) ) : NULL
;
635 /*static*/ WXString
wxFont::GetFontTag()
637 #if wxUSE_RENDER_TABLE
638 return (WXString
)XmNrenderTable
;
640 return (WXString
)XmNfontList
;