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 #if !wxMOTIF_NEW_FONT_HANDLING
68 WXFontStructPtr m_fontStruct
; // XFontStruct
70 #if !wxUSE_RENDER_TABLE && !wxMOTIF_NEW_FONT_HANDLING
71 WXFontList m_fontList
; // Motif XmFontList
72 #else // if wxUSE_RENDER_TABLE
73 WXRenderTable m_renderTable
; // Motif XmRenderTable
74 WXRendition m_rendition
; // Motif XmRendition
76 WXDisplay
* m_display
; // XDisplay
77 int m_scale
; // Scale * 100
80 class wxFontRefData
: public wxGDIRefData
85 wxFontRefData(int size
= wxDEFAULT
,
86 int family
= wxDEFAULT
,
87 int style
= wxDEFAULT
,
88 int weight
= wxDEFAULT
,
89 bool underlined
= false,
90 const wxString
& faceName
= wxEmptyString
,
91 wxFontEncoding encoding
= wxFONTENCODING_DEFAULT
)
93 Init(size
, family
, style
, weight
, underlined
, faceName
, encoding
);
96 wxFontRefData(const wxFontRefData
& data
)
98 Init(data
.m_pointSize
, data
.m_family
, data
.m_style
, data
.m_weight
,
99 data
.m_underlined
, data
.m_faceName
, data
.m_encoding
);
105 // common part of all ctors
111 const wxString
& faceName
,
112 wxFontEncoding encoding
);
121 wxFontEncoding m_encoding
;
123 wxNativeFontInfo m_nativeFontInfo
;
125 // A list of wxXFonts
129 // ============================================================================
131 // ============================================================================
133 // ----------------------------------------------------------------------------
135 // ----------------------------------------------------------------------------
139 #if !wxMOTIF_NEW_FONT_HANDLING
140 m_fontStruct
= (WXFontStructPtr
) 0;
142 #if !wxUSE_RENDER_TABLE && !wxMOTIF_NEW_FONT_HANDLING
143 m_fontList
= (WXFontList
) 0;
144 #else // if wxUSE_RENDER_TABLE
145 m_renderTable
= (WXRenderTable
) 0;
146 m_rendition
= (WXRendition
) 0;
148 m_display
= (WXDisplay
*) 0;
154 #if !wxUSE_RENDER_TABLE
156 XmFontListFree ((XmFontList
) m_fontList
);
158 #else // if wxUSE_RENDER_TABLE
160 XmRenderTableFree ((XmRenderTable
) m_renderTable
);
161 m_renderTable
= NULL
;
164 // TODO: why does freeing the font produce a segv???
165 // Note that XFreeFont wasn't called in wxWin 1.68 either.
166 // MBN: probably some interaction with fonts being still
167 // in use in some widgets...
168 // XFontStruct* fontStruct = (XFontStruct*) m_fontStruct;
169 // XFreeFont((Display*) m_display, fontStruct);
172 // ----------------------------------------------------------------------------
174 // ----------------------------------------------------------------------------
176 void wxFontRefData::Init(int pointSize
,
181 const wxString
& faceName
,
182 wxFontEncoding encoding
)
184 if (family
== wxDEFAULT
)
189 m_faceName
= faceName
;
191 if (style
== wxDEFAULT
)
196 if (weight
== wxDEFAULT
)
201 if (pointSize
== wxDEFAULT
)
204 m_pointSize
= pointSize
;
206 m_underlined
= underlined
;
207 m_encoding
= encoding
;
210 wxFontRefData::~wxFontRefData()
212 wxList::compatibility_iterator node
= m_fonts
.GetFirst();
215 wxXFont
* f
= (wxXFont
*) node
->GetData();
217 node
= node
->GetNext();
222 // ----------------------------------------------------------------------------
224 // ----------------------------------------------------------------------------
226 wxFont::wxFont(const wxNativeFontInfo
& info
)
230 (void)Create(info
.GetXFontName());
237 bool wxFont::Create(int pointSize
,
242 const wxString
& faceName
,
243 wxFontEncoding encoding
)
246 m_refData
= new wxFontRefData(pointSize
, family
, style
, weight
,
247 underlined
, faceName
, encoding
);
254 bool wxFont::Create(const wxString
& fontname
, wxFontEncoding enc
)
258 *this = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT
);
262 m_refData
= new wxFontRefData();
264 M_FONTDATA
->m_nativeFontInfo
.SetXFontName(fontname
); // X font name
268 wxStringTokenizer
tn( fontname
, wxT("-") );
270 tn
.GetNextToken(); // skip initial empty token
271 tn
.GetNextToken(); // foundry
274 M_FONTDATA
->m_faceName
= tn
.GetNextToken(); // family
276 tmp
= tn
.GetNextToken().MakeUpper(); // weight
277 if (tmp
== wxT("BOLD")) M_FONTDATA
->m_weight
= wxBOLD
;
278 if (tmp
== wxT("BLACK")) M_FONTDATA
->m_weight
= wxBOLD
;
279 if (tmp
== wxT("EXTRABOLD")) M_FONTDATA
->m_weight
= wxBOLD
;
280 if (tmp
== wxT("DEMIBOLD")) M_FONTDATA
->m_weight
= wxBOLD
;
281 if (tmp
== wxT("ULTRABOLD")) M_FONTDATA
->m_weight
= wxBOLD
;
283 if (tmp
== wxT("LIGHT")) M_FONTDATA
->m_weight
= wxLIGHT
;
284 if (tmp
== wxT("THIN")) M_FONTDATA
->m_weight
= wxLIGHT
;
286 tmp
= tn
.GetNextToken().MakeUpper(); // slant
287 if (tmp
== wxT("I")) M_FONTDATA
->m_style
= wxITALIC
;
288 if (tmp
== wxT("O")) M_FONTDATA
->m_style
= wxITALIC
;
290 tn
.GetNextToken(); // set width
291 tn
.GetNextToken(); // add. style
292 tn
.GetNextToken(); // pixel size
294 tmp
= tn
.GetNextToken(); // pointsize
297 long num
= wxStrtol (tmp
.c_str(), (wxChar
**) NULL
, 10);
298 M_FONTDATA
->m_pointSize
= (int)(num
/ 10);
301 tn
.GetNextToken(); // x-res
302 tn
.GetNextToken(); // y-res
304 tmp
= tn
.GetNextToken().MakeUpper(); // spacing
307 M_FONTDATA
->m_family
= wxMODERN
;
308 else if (M_FONTDATA
->m_faceName
== wxT("TIMES"))
309 M_FONTDATA
->m_family
= wxROMAN
;
310 else if (M_FONTDATA
->m_faceName
== wxT("HELVETICA"))
311 M_FONTDATA
->m_family
= wxSWISS
;
312 else if (M_FONTDATA
->m_faceName
== wxT("LUCIDATYPEWRITER"))
313 M_FONTDATA
->m_family
= wxTELETYPE
;
314 else if (M_FONTDATA
->m_faceName
== wxT("LUCIDA"))
315 M_FONTDATA
->m_family
= wxDECORATIVE
;
316 else if (M_FONTDATA
->m_faceName
== wxT("UTOPIA"))
317 M_FONTDATA
->m_family
= wxSCRIPT
;
319 tn
.GetNextToken(); // avg width
321 // deal with font encoding
322 M_FONTDATA
->m_encoding
= enc
;
323 if ( M_FONTDATA
->m_encoding
== wxFONTENCODING_SYSTEM
)
325 wxString registry
= tn
.GetNextToken().MakeUpper(),
326 encoding
= tn
.GetNextToken().MakeUpper();
328 if ( registry
== _T("ISO8859") )
331 if ( wxSscanf(encoding
, wxT("%d"), &cp
) == 1 )
333 M_FONTDATA
->m_encoding
=
334 (wxFontEncoding
)(wxFONTENCODING_ISO8859_1
+ cp
- 1);
337 else if ( registry
== _T("MICROSOFT") )
340 if ( wxSscanf(encoding
, wxT("cp125%d"), &cp
) == 1 )
342 M_FONTDATA
->m_encoding
=
343 (wxFontEncoding
)(wxFONTENCODING_CP1250
+ cp
);
346 else if ( registry
== _T("KOI8") )
348 M_FONTDATA
->m_encoding
= wxFONTENCODING_KOI8
;
350 //else: unknown encoding - may be give a warning here?
361 // ----------------------------------------------------------------------------
362 // change the font attributes
363 // ----------------------------------------------------------------------------
365 void wxFont::Unshare()
367 // Don't change shared data
370 m_refData
= new wxFontRefData();
374 wxFontRefData
* ref
= new wxFontRefData(*(wxFontRefData
*)m_refData
);
380 void wxFont::SetPointSize(int pointSize
)
384 M_FONTDATA
->m_pointSize
= pointSize
;
385 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
390 void wxFont::SetFamily(int family
)
394 M_FONTDATA
->m_family
= family
;
395 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
400 void wxFont::SetStyle(int style
)
404 M_FONTDATA
->m_style
= style
;
405 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
410 void wxFont::SetWeight(int weight
)
414 M_FONTDATA
->m_weight
= weight
;
415 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
420 void wxFont::SetFaceName(const wxString
& faceName
)
424 M_FONTDATA
->m_faceName
= faceName
;
425 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
430 void wxFont::SetUnderlined(bool underlined
)
434 M_FONTDATA
->m_underlined
= underlined
;
439 void wxFont::SetEncoding(wxFontEncoding encoding
)
443 M_FONTDATA
->m_encoding
= encoding
;
444 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
449 void wxFont::DoSetNativeFontInfo(const wxNativeFontInfo
& info
)
453 M_FONTDATA
->m_nativeFontInfo
= info
;
456 // ----------------------------------------------------------------------------
457 // query font attributes
458 // ----------------------------------------------------------------------------
460 int wxFont::GetPointSize() const
462 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
464 return M_FONTDATA
->m_pointSize
;
467 wxString
wxFont::GetFaceName() const
469 wxCHECK_MSG( Ok(), wxT(""), wxT("invalid font") );
471 return M_FONTDATA
->m_faceName
;
474 int wxFont::GetFamily() const
476 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
478 return M_FONTDATA
->m_family
;
481 int wxFont::GetStyle() const
483 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
485 return M_FONTDATA
->m_style
;
488 int wxFont::GetWeight() const
490 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
492 return M_FONTDATA
->m_weight
;
495 bool wxFont::GetUnderlined() const
497 wxCHECK_MSG( Ok(), false, wxT("invalid font") );
499 return M_FONTDATA
->m_underlined
;
502 wxFontEncoding
wxFont::GetEncoding() const
504 wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT
, wxT("invalid font") );
506 return M_FONTDATA
->m_encoding
;
509 const wxNativeFontInfo
*wxFont::GetNativeFontInfo() const
511 wxCHECK_MSG( Ok(), (wxNativeFontInfo
*)NULL
, wxT("invalid font") );
513 if(M_FONTDATA
->m_nativeFontInfo
.GetXFontName().IsEmpty())
516 return &(M_FONTDATA
->m_nativeFontInfo
);
519 // ----------------------------------------------------------------------------
520 // real implementation
521 // ----------------------------------------------------------------------------
523 // Find an existing, or create a new, XFontStruct
524 // based on this wxFont and the given scale. Append the
525 // font to list in the private data for future reference.
526 wxXFont
* wxFont::GetInternalFont(double scale
, WXDisplay
* display
) const
529 return (wxXFont
*)NULL
;
531 long intScale
= long(scale
* 100.0 + 0.5); // key for wxXFont
532 int pointSize
= (M_FONTDATA
->m_pointSize
* 10 * intScale
) / 100;
534 // search existing fonts first
535 wxList::compatibility_iterator node
= M_FONTDATA
->m_fonts
.GetFirst();
538 wxXFont
* f
= (wxXFont
*) node
->GetData();
539 if ((!display
|| (f
->m_display
== display
)) && (f
->m_scale
== intScale
))
541 node
= node
->GetNext();
544 // not found, create a new one
546 XFontStruct
*font
= (XFontStruct
*)
547 wxLoadQueryNearestFont(pointSize
,
548 M_FONTDATA
->m_family
,
550 M_FONTDATA
->m_weight
,
551 M_FONTDATA
->m_underlined
,
553 M_FONTDATA
->m_encoding
,
558 wxFAIL_MSG( wxT("Could not allocate even a default font -- something is wrong.") );
560 return (wxXFont
*) NULL
;
563 wxXFont
* f
= new wxXFont
;
564 #if wxMOTIF_NEW_FONT_HANDLING
565 XFreeFont( (Display
*) display
, font
);
567 f
->m_fontStruct
= (WXFontStructPtr
)font
;
569 f
->m_display
= ( display
? display
: wxGetDisplay() );
570 f
->m_scale
= intScale
;
572 #if wxUSE_RENDER_TABLE
573 XmRendition rendition
;
574 XmRenderTable renderTable
;
578 #if wxMOTIF_NEW_FONT_HANDLING
579 wxChar
* fontSpec
= wxStrdup( xFontSpec
.c_str() );
580 XtSetArg( args
[count
], XmNfontName
, fontSpec
); ++count
;
581 XtSetArg( args
[count
], XmNfontType
, XmFONT_IS_FONTSET
); ++count
;
583 XtSetArg( args
[count
], XmNfont
, font
); ++count
;
585 XtSetArg( args
[count
], XmNunderlineType
,
586 GetUnderlined() ? XmSINGLE_LINE
: XmNO_LINE
); ++count
;
587 rendition
= XmRenditionCreate( XmGetXmDisplay( (Display
*)f
->m_display
),
590 renderTable
= XmRenderTableAddRenditions( NULL
, &rendition
, 1,
593 f
->m_renderTable
= (WXRenderTable
)renderTable
;
594 f
->m_rendition
= (WXRendition
)rendition
;
595 wxASSERT( f
->m_renderTable
!= NULL
);
596 #else // if !wxUSE_RENDER_TABLE
597 f
->m_fontList
= XmFontListCreate ((XFontStruct
*) font
, XmSTRING_DEFAULT_CHARSET
);
598 wxASSERT( f
->m_fontList
!= NULL
);
601 M_FONTDATA
->m_fonts
.Append(f
);
606 #if !wxMOTIF_NEW_FONT_HANDLING
608 WXFontStructPtr
wxFont::GetFontStruct(double scale
, WXDisplay
* display
) const
610 wxXFont
* f
= GetInternalFont(scale
, display
);
612 return (f
? f
->m_fontStruct
: (WXFontStructPtr
) 0);
615 WXFontList
wxFont::GetFontList(double scale
, WXDisplay
* display
) const
617 #if !wxUSE_RENDER_TABLE
618 wxXFont
* f
= GetInternalFont(scale
, display
);
620 return (f
? f
->m_fontList
: (WXFontList
) 0);
626 #endif // !wxMOTIF_NEW_FONT_HANDLING
628 // declared in the header, can't use wxUSE_RENDER_TABLE
629 #if wxCHECK_MOTIF_VERSION( 2, 0 )
631 WXRenderTable
wxFont::GetRenderTable(WXDisplay
* display
) const
633 #if wxUSE_RENDER_TABLE
634 wxXFont
* f
= GetInternalFont(1.0, display
);
636 return (f
? f
->m_renderTable
: (WXFontList
) 0);
642 #endif // wxCHECK_MOTIF_VERSION( 2, 0 )
644 WXFontType
wxFont::GetFontType(WXDisplay
* display
) const
646 #if wxUSE_RENDER_TABLE
647 return Ok() ? GetRenderTable(display
) : NULL
;
649 return Ok() ? GetFontList(1.0, display
) : NULL
;
653 WXFontType
wxFont::GetFontTypeC(WXDisplay
* display
) const
655 #if wxUSE_RENDER_TABLE
656 return Ok() ? GetRenderTable(display
) : NULL
;
658 return Ok() ? XmFontListCopy( (XmFontList
)GetFontList(1.0, display
) ) : NULL
;
662 /*static*/ WXString
wxFont::GetFontTag()
664 #if wxUSE_RENDER_TABLE
665 return (WXString
)XmNrenderTable
;
667 return (WXString
)XmNfontList
;
671 #if wxMOTIF_NEW_FONT_HANDLING
673 WXFontSet
wxFont::GetFontSet(double scale
, WXDisplay
* display
) const
675 wxXFont
* f
= GetInternalFont(scale
, display
);
677 if( !f
) return (WXFontSet
) 0;
682 XtSetArg( args
[count
], XmNfont
, 0 ); ++count
;
683 XmRenditionRetrieve( (XmRendition
) f
->m_rendition
, args
, count
);
685 return (WXFontSet
) args
[0].value
;
688 void wxGetTextExtent(WXDisplay
* display
, const wxFont
& font
, double scale
,
690 int* width
, int* height
, int* ascent
, int* descent
)
692 XRectangle ink
, logical
;
693 WXFontSet fset
= font
.GetFontSet(scale
, display
);
695 XmbTextExtents( (XFontSet
)fset
, str
.c_str(), str
.length(), &ink
, &logical
);
697 if( width
) *width
= logical
.width
;
698 if( height
) *height
= logical
.height
;
699 if( ascent
) *ascent
= -logical
.y
;
700 if( descent
) *descent
= logical
.height
+ logical
.y
;
703 #else // if !wxMOTIF_NEW_FONT_HANDLING
705 void wxGetTextExtent(WXDisplay
* display
, const wxFont
& font
,
706 double scale
, const wxString
& str
,
707 int* width
, int* height
, int* ascent
, int* descent
)
709 WXFontStructPtr pFontStruct
= font
.GetFontStruct(scale
, display
);
711 int direction
, ascent2
, descent2
;
713 int slen
= str
.Len();
715 XTextExtents((XFontStruct
*) pFontStruct
, (char*) str
.c_str(), slen
,
716 &direction
, &ascent2
, &descent2
, &overall
);
719 *width
= (overall
.width
);
721 *height
= (ascent2
+ descent2
);
728 #endif // !wxMOTIF_NEW_FONT_HANDLING