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 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
24 #pragma message disable nosimpint
25 #include "wx/vms_x_fix.h"
29 #pragma message enable nosimpint
32 #include "wx/string.h"
34 #include "wx/gdicmn.h"
35 #include "wx/utils.h" // for wxGetDisplay()
36 #include "wx/fontutil.h" // for wxNativeFontInfo
37 #include "wx/tokenzr.h"
38 #include "wx/settings.h"
39 #include "wx/motif/private.h"
41 IMPLEMENT_DYNAMIC_CLASS(wxFont
, wxGDIObject
)
43 // ----------------------------------------------------------------------------
45 // ----------------------------------------------------------------------------
47 // For every wxFont, there must be a font for each display and scale requested.
48 // So these objects are stored in wxFontRefData::m_fonts
49 class wxXFont
: public wxObject
55 #if !wxMOTIF_NEW_FONT_HANDLING
56 WXFontStructPtr m_fontStruct
; // XFontStruct
58 #if !wxMOTIF_USE_RENDER_TABLE && !wxMOTIF_NEW_FONT_HANDLING
59 WXFontList m_fontList
; // Motif XmFontList
60 #else // if wxUSE_RENDER_TABLE
61 WXRenderTable m_renderTable
; // Motif XmRenderTable
62 WXRendition m_rendition
; // Motif XmRendition
64 WXDisplay
* m_display
; // XDisplay
65 int m_scale
; // Scale * 100
68 class wxFontRefData
: public wxGDIRefData
73 wxFontRefData(int size
= wxDEFAULT
,
74 int family
= wxDEFAULT
,
75 int style
= wxDEFAULT
,
76 int weight
= wxDEFAULT
,
77 bool underlined
= false,
78 const wxString
& faceName
= wxEmptyString
,
79 wxFontEncoding encoding
= wxFONTENCODING_DEFAULT
)
81 Init(size
, family
, style
, weight
, underlined
, faceName
, encoding
);
84 wxFontRefData(const wxFontRefData
& data
)
86 Init(data
.m_pointSize
, data
.m_family
, data
.m_style
, data
.m_weight
,
87 data
.m_underlined
, data
.m_faceName
, data
.m_encoding
);
93 // common part of all ctors
99 const wxString
& faceName
,
100 wxFontEncoding encoding
);
109 wxFontEncoding m_encoding
;
111 wxNativeFontInfo m_nativeFontInfo
;
113 // A list of wxXFonts
117 // ============================================================================
119 // ============================================================================
121 // ----------------------------------------------------------------------------
123 // ----------------------------------------------------------------------------
127 #if !wxMOTIF_NEW_FONT_HANDLING
128 m_fontStruct
= (WXFontStructPtr
) 0;
130 #if !wxMOTIF_USE_RENDER_TABLE && !wxMOTIF_NEW_FONT_HANDLING
131 m_fontList
= (WXFontList
) 0;
132 #else // if wxMOTIF_USE_RENDER_TABLE
133 m_renderTable
= (WXRenderTable
) 0;
134 m_rendition
= (WXRendition
) 0;
136 m_display
= (WXDisplay
*) 0;
142 #if !wxMOTIF_USE_RENDER_TABLE
144 XmFontListFree ((XmFontList
) m_fontList
);
146 #else // if wxUSE_RENDER_TABLE
148 XmRenderTableFree ((XmRenderTable
) m_renderTable
);
149 m_renderTable
= NULL
;
152 // TODO: why does freeing the font produce a segv???
153 // Note that XFreeFont wasn't called in wxWin 1.68 either.
154 // MBN: probably some interaction with fonts being still
155 // in use in some widgets...
156 // XFontStruct* fontStruct = (XFontStruct*) m_fontStruct;
157 // XFreeFont((Display*) m_display, fontStruct);
160 // ----------------------------------------------------------------------------
162 // ----------------------------------------------------------------------------
164 void wxFontRefData::Init(int pointSize
,
169 const wxString
& faceName
,
170 wxFontEncoding encoding
)
172 if (family
== wxDEFAULT
)
177 m_faceName
= faceName
;
179 if (style
== wxDEFAULT
)
184 if (weight
== wxDEFAULT
)
189 if (pointSize
== wxDEFAULT
)
192 m_pointSize
= pointSize
;
194 m_underlined
= underlined
;
195 m_encoding
= encoding
;
198 wxFontRefData::~wxFontRefData()
200 wxList::compatibility_iterator node
= m_fonts
.GetFirst();
203 wxXFont
* f
= (wxXFont
*) node
->GetData();
205 node
= node
->GetNext();
210 // ----------------------------------------------------------------------------
212 // ----------------------------------------------------------------------------
214 wxFont::wxFont(const wxNativeFontInfo
& info
)
216 (void)Create(info
.GetXFontName());
219 bool wxFont::Create(int pointSize
,
224 const wxString
& faceName
,
225 wxFontEncoding encoding
)
228 m_refData
= new wxFontRefData(pointSize
, family
, style
, weight
,
229 underlined
, faceName
, encoding
);
234 bool wxFont::Create(const wxString
& fontname
, wxFontEncoding enc
)
238 *this = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT
);
242 m_refData
= new wxFontRefData();
244 M_FONTDATA
->m_nativeFontInfo
.SetXFontName(fontname
); // X font name
248 wxStringTokenizer
tn( fontname
, wxT("-") );
250 tn
.GetNextToken(); // skip initial empty token
251 tn
.GetNextToken(); // foundry
254 M_FONTDATA
->m_faceName
= tn
.GetNextToken(); // family
256 tmp
= tn
.GetNextToken().MakeUpper(); // weight
257 if (tmp
== wxT("BOLD")) M_FONTDATA
->m_weight
= wxBOLD
;
258 if (tmp
== wxT("BLACK")) M_FONTDATA
->m_weight
= wxBOLD
;
259 if (tmp
== wxT("EXTRABOLD")) M_FONTDATA
->m_weight
= wxBOLD
;
260 if (tmp
== wxT("DEMIBOLD")) M_FONTDATA
->m_weight
= wxBOLD
;
261 if (tmp
== wxT("ULTRABOLD")) M_FONTDATA
->m_weight
= wxBOLD
;
263 if (tmp
== wxT("LIGHT")) M_FONTDATA
->m_weight
= wxLIGHT
;
264 if (tmp
== wxT("THIN")) M_FONTDATA
->m_weight
= wxLIGHT
;
266 tmp
= tn
.GetNextToken().MakeUpper(); // slant
267 if (tmp
== wxT("I")) M_FONTDATA
->m_style
= wxITALIC
;
268 if (tmp
== wxT("O")) M_FONTDATA
->m_style
= wxITALIC
;
270 tn
.GetNextToken(); // set width
271 tn
.GetNextToken(); // add. style
272 tn
.GetNextToken(); // pixel size
274 tmp
= tn
.GetNextToken(); // pointsize
277 long num
= wxStrtol (tmp
.c_str(), (wxChar
**) NULL
, 10);
278 M_FONTDATA
->m_pointSize
= (int)(num
/ 10);
281 tn
.GetNextToken(); // x-res
282 tn
.GetNextToken(); // y-res
284 tmp
= tn
.GetNextToken().MakeUpper(); // spacing
287 M_FONTDATA
->m_family
= wxMODERN
;
288 else if (M_FONTDATA
->m_faceName
== wxT("TIMES"))
289 M_FONTDATA
->m_family
= wxROMAN
;
290 else if (M_FONTDATA
->m_faceName
== wxT("HELVETICA"))
291 M_FONTDATA
->m_family
= wxSWISS
;
292 else if (M_FONTDATA
->m_faceName
== wxT("LUCIDATYPEWRITER"))
293 M_FONTDATA
->m_family
= wxTELETYPE
;
294 else if (M_FONTDATA
->m_faceName
== wxT("LUCIDA"))
295 M_FONTDATA
->m_family
= wxDECORATIVE
;
296 else if (M_FONTDATA
->m_faceName
== wxT("UTOPIA"))
297 M_FONTDATA
->m_family
= wxSCRIPT
;
299 tn
.GetNextToken(); // avg width
301 // deal with font encoding
302 M_FONTDATA
->m_encoding
= enc
;
303 if ( M_FONTDATA
->m_encoding
== wxFONTENCODING_SYSTEM
)
305 wxString registry
= tn
.GetNextToken().MakeUpper(),
306 encoding
= tn
.GetNextToken().MakeUpper();
308 if ( registry
== _T("ISO8859") )
311 if ( wxSscanf(encoding
, wxT("%d"), &cp
) == 1 )
313 M_FONTDATA
->m_encoding
=
314 (wxFontEncoding
)(wxFONTENCODING_ISO8859_1
+ cp
- 1);
317 else if ( registry
== _T("MICROSOFT") )
320 if ( wxSscanf(encoding
, wxT("cp125%d"), &cp
) == 1 )
322 M_FONTDATA
->m_encoding
=
323 (wxFontEncoding
)(wxFONTENCODING_CP1250
+ cp
);
326 else if ( registry
== _T("KOI8") )
328 M_FONTDATA
->m_encoding
= wxFONTENCODING_KOI8
;
330 //else: unknown encoding - may be give a warning here?
341 // ----------------------------------------------------------------------------
342 // change the font attributes
343 // ----------------------------------------------------------------------------
345 void wxFont::Unshare()
347 // Don't change shared data
350 m_refData
= new wxFontRefData();
354 wxFontRefData
* ref
= new wxFontRefData(*(wxFontRefData
*)m_refData
);
360 void wxFont::SetPointSize(int pointSize
)
364 M_FONTDATA
->m_pointSize
= pointSize
;
365 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
368 void wxFont::SetFamily(int family
)
372 M_FONTDATA
->m_family
= family
;
373 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
376 void wxFont::SetStyle(int style
)
380 M_FONTDATA
->m_style
= style
;
381 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
384 void wxFont::SetWeight(int weight
)
388 M_FONTDATA
->m_weight
= weight
;
389 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
392 void wxFont::SetFaceName(const wxString
& faceName
)
396 M_FONTDATA
->m_faceName
= faceName
;
397 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
400 void wxFont::SetUnderlined(bool underlined
)
404 M_FONTDATA
->m_underlined
= underlined
;
407 void wxFont::SetEncoding(wxFontEncoding encoding
)
411 M_FONTDATA
->m_encoding
= encoding
;
412 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
415 void wxFont::DoSetNativeFontInfo(const wxNativeFontInfo
& info
)
419 M_FONTDATA
->m_nativeFontInfo
= info
;
422 // ----------------------------------------------------------------------------
423 // query font attributes
424 // ----------------------------------------------------------------------------
426 int wxFont::GetPointSize() const
428 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
430 return M_FONTDATA
->m_pointSize
;
433 wxString
wxFont::GetFaceName() const
435 wxCHECK_MSG( Ok(), wxEmptyString
, wxT("invalid font") );
437 return M_FONTDATA
->m_faceName
;
440 int wxFont::GetFamily() const
442 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
444 return M_FONTDATA
->m_family
;
447 int wxFont::GetStyle() const
449 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
451 return M_FONTDATA
->m_style
;
454 int wxFont::GetWeight() const
456 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
458 return M_FONTDATA
->m_weight
;
461 bool wxFont::GetUnderlined() const
463 wxCHECK_MSG( Ok(), false, wxT("invalid font") );
465 return M_FONTDATA
->m_underlined
;
468 wxFontEncoding
wxFont::GetEncoding() const
470 wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT
, wxT("invalid font") );
472 return M_FONTDATA
->m_encoding
;
475 const wxNativeFontInfo
*wxFont::GetNativeFontInfo() const
477 wxCHECK_MSG( Ok(), (wxNativeFontInfo
*)NULL
, wxT("invalid font") );
479 if(M_FONTDATA
->m_nativeFontInfo
.GetXFontName().empty())
482 return &(M_FONTDATA
->m_nativeFontInfo
);
485 // ----------------------------------------------------------------------------
486 // real implementation
487 // ----------------------------------------------------------------------------
489 // Find an existing, or create a new, XFontStruct
490 // based on this wxFont and the given scale. Append the
491 // font to list in the private data for future reference.
492 wxXFont
* wxFont::GetInternalFont(double scale
, WXDisplay
* display
) const
495 return (wxXFont
*)NULL
;
497 long intScale
= long(scale
* 100.0 + 0.5); // key for wxXFont
498 int pointSize
= (M_FONTDATA
->m_pointSize
* 10 * intScale
) / 100;
500 // search existing fonts first
501 wxList::compatibility_iterator node
= M_FONTDATA
->m_fonts
.GetFirst();
504 wxXFont
* f
= (wxXFont
*) node
->GetData();
505 if ((!display
|| (f
->m_display
== display
)) && (f
->m_scale
== intScale
))
507 node
= node
->GetNext();
510 // not found, create a new one
512 XFontStruct
*font
= (XFontStruct
*)
513 wxLoadQueryNearestFont(pointSize
,
514 M_FONTDATA
->m_family
,
516 M_FONTDATA
->m_weight
,
517 M_FONTDATA
->m_underlined
,
519 M_FONTDATA
->m_encoding
,
524 wxFAIL_MSG( wxT("Could not allocate even a default font -- something is wrong.") );
526 return (wxXFont
*) NULL
;
529 wxXFont
* f
= new wxXFont
;
530 #if wxMOTIF_NEW_FONT_HANDLING
531 XFreeFont( (Display
*) display
, font
);
533 f
->m_fontStruct
= (WXFontStructPtr
)font
;
535 f
->m_display
= ( display
? display
: wxGetDisplay() );
536 f
->m_scale
= intScale
;
538 #if wxMOTIF_USE_RENDER_TABLE
539 XmRendition rendition
;
540 XmRenderTable renderTable
;
544 #if wxMOTIF_NEW_FONT_HANDLING
545 wxChar
* fontSpec
= wxStrdup( xFontSpec
.c_str() );
546 XtSetArg( args
[count
], XmNfontName
, fontSpec
); ++count
;
547 XtSetArg( args
[count
], XmNfontType
, XmFONT_IS_FONTSET
); ++count
;
549 XtSetArg( args
[count
], XmNfont
, font
); ++count
;
551 XtSetArg( args
[count
], XmNunderlineType
,
552 GetUnderlined() ? XmSINGLE_LINE
: XmNO_LINE
); ++count
;
553 rendition
= XmRenditionCreate( XmGetXmDisplay( (Display
*)f
->m_display
),
556 renderTable
= XmRenderTableAddRenditions( NULL
, &rendition
, 1,
559 f
->m_renderTable
= (WXRenderTable
)renderTable
;
560 f
->m_rendition
= (WXRendition
)rendition
;
561 wxASSERT( f
->m_renderTable
!= NULL
);
562 #else // if !wxMOTIF_USE_RENDER_TABLE
563 f
->m_fontList
= XmFontListCreate ((XFontStruct
*) font
, XmSTRING_DEFAULT_CHARSET
);
564 wxASSERT( f
->m_fontList
!= NULL
);
567 M_FONTDATA
->m_fonts
.Append(f
);
572 #if !wxMOTIF_NEW_FONT_HANDLING
574 WXFontStructPtr
wxFont::GetFontStruct(double scale
, WXDisplay
* display
) const
576 wxXFont
* f
= GetInternalFont(scale
, display
);
578 return (f
? f
->m_fontStruct
: (WXFontStructPtr
) 0);
583 #if !wxMOTIF_USE_RENDER_TABLE
585 WXFontList
wxFont::GetFontList(double scale
, WXDisplay
* display
) const
587 wxXFont
* f
= GetInternalFont(scale
, display
);
589 return (f
? f
->m_fontList
: (WXFontList
) 0);
592 #else // if wxMOTIF_USE_RENDER_TABLE
594 WXRenderTable
wxFont::GetRenderTable(WXDisplay
* display
) const
596 wxXFont
* f
= GetInternalFont(1.0, display
);
598 return (f
? f
->m_renderTable
: (WXRenderTable
) 0);
601 #endif // wxMOTIF_USE_RENDER_TABLE
603 WXFontType
wxFont::GetFontType(WXDisplay
* display
) const
605 #if wxMOTIF_USE_RENDER_TABLE
606 return Ok() ? GetRenderTable(display
) : NULL
;
608 return Ok() ? GetFontList(1.0, display
) : NULL
;
612 WXFontType
wxFont::GetFontTypeC(WXDisplay
* display
) const
614 #if wxMOTIF_USE_RENDER_TABLE
615 return Ok() ? GetRenderTable(display
) : NULL
;
617 return Ok() ? XmFontListCopy( (XmFontList
)GetFontList(1.0, display
) ) : NULL
;
621 /*static*/ WXString
wxFont::GetFontTag()
623 #if wxMOTIF_USE_RENDER_TABLE
624 return (WXString
)XmNrenderTable
;
626 return (WXString
)XmNfontList
;
630 #if wxMOTIF_NEW_FONT_HANDLING
632 WXFontSet
wxFont::GetFontSet(double scale
, WXDisplay
* display
) const
634 wxXFont
* f
= GetInternalFont(scale
, display
);
636 if( !f
) return (WXFontSet
) 0;
641 XtSetArg( args
[count
], XmNfont
, 0 ); ++count
;
642 XmRenditionRetrieve( (XmRendition
) f
->m_rendition
, args
, count
);
644 return (WXFontSet
) args
[0].value
;
647 void wxGetTextExtent(WXDisplay
* display
, const wxFont
& font
, double scale
,
649 int* width
, int* height
, int* ascent
, int* descent
)
651 XRectangle ink
, logical
;
652 WXFontSet fset
= font
.GetFontSet(scale
, display
);
654 XmbTextExtents( (XFontSet
)fset
, str
.c_str(), str
.length(), &ink
, &logical
);
656 if( width
) *width
= logical
.width
;
657 if( height
) *height
= logical
.height
;
658 if( ascent
) *ascent
= -logical
.y
;
659 if( descent
) *descent
= logical
.height
+ logical
.y
;
662 #else // if !wxMOTIF_NEW_FONT_HANDLING
664 void wxGetTextExtent(WXDisplay
* display
, const wxFont
& font
,
665 double scale
, const wxString
& str
,
666 int* width
, int* height
, int* ascent
, int* descent
)
668 WXFontStructPtr pFontStruct
= font
.GetFontStruct(scale
, display
);
670 int direction
, ascent2
, descent2
;
672 int slen
= str
.Len();
674 XTextExtents((XFontStruct
*) pFontStruct
, (char*) str
.c_str(), slen
,
675 &direction
, &ascent2
, &descent2
, &overall
);
678 *width
= (overall
.width
);
680 *height
= (ascent2
+ descent2
);
687 #endif // !wxMOTIF_NEW_FONT_HANDLING