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
35 #include "wx/string.h"
36 #include "wx/utils.h" // for wxGetDisplay()
37 #include "wx/settings.h"
38 #include "wx/gdicmn.h"
41 #include "wx/fontutil.h" // for wxNativeFontInfo
42 #include "wx/tokenzr.h"
43 #include "wx/motif/private.h"
45 IMPLEMENT_DYNAMIC_CLASS(wxFont
, wxGDIObject
)
47 // ----------------------------------------------------------------------------
49 // ----------------------------------------------------------------------------
51 // For every wxFont, there must be a font for each display and scale requested.
52 // So these objects are stored in wxFontRefData::m_fonts
53 class wxXFont
: public wxObject
59 #if !wxMOTIF_NEW_FONT_HANDLING
60 WXFontStructPtr m_fontStruct
; // XFontStruct
62 #if !wxMOTIF_USE_RENDER_TABLE
63 WXFontList m_fontList
; // Motif XmFontList
64 #else // if wxMOTIF_USE_RENDER_TABLE
65 WXRenderTable m_renderTable
; // Motif XmRenderTable
66 WXRendition m_rendition
; // Motif XmRendition
68 WXDisplay
* m_display
; // XDisplay
69 int m_scale
; // Scale * 100
72 class wxFontRefData
: public wxGDIRefData
77 wxFontRefData(int size
= wxDEFAULT
,
78 wxFontFamily family
= wxFONTFAMILY_DEFAULT
,
79 wxFontStyle style
= wxFONTSTYLE_NORMAL
,
80 wxFontWeight weight
= wxFONTWEIGHT_NORMAL
,
81 bool underlined
= false,
82 const wxString
& faceName
= wxEmptyString
,
83 wxFontEncoding encoding
= wxFONTENCODING_DEFAULT
)
85 Init(size
, family
, style
, weight
, underlined
, faceName
, encoding
);
88 wxFontRefData(const wxFontRefData
& data
)
90 Init(data
.m_pointSize
, data
.m_family
, data
.m_style
, data
.m_weight
,
91 data
.m_underlined
, data
.m_faceName
, data
.m_encoding
);
94 virtual ~wxFontRefData();
97 // common part of all ctors
103 const wxString
& faceName
,
104 wxFontEncoding encoding
);
108 wxFontFamily m_family
;
110 wxFontWeight m_weight
;
113 wxFontEncoding m_encoding
;
115 wxNativeFontInfo m_nativeFontInfo
;
117 // A list of wxXFonts
121 // ============================================================================
123 // ============================================================================
125 // ----------------------------------------------------------------------------
127 // ----------------------------------------------------------------------------
131 #if !wxMOTIF_NEW_FONT_HANDLING
132 m_fontStruct
= (WXFontStructPtr
) 0;
134 #if !wxMOTIF_USE_RENDER_TABLE
135 m_fontList
= (WXFontList
) 0;
136 #else // if wxMOTIF_USE_RENDER_TABLE
137 m_renderTable
= (WXRenderTable
) 0;
138 m_rendition
= (WXRendition
) 0;
140 m_display
= (WXDisplay
*) 0;
146 #if !wxMOTIF_USE_RENDER_TABLE
148 XmFontListFree ((XmFontList
) m_fontList
);
150 #else // if wxMOTIF_USE_RENDER_TABLE
152 XmRenderTableFree ((XmRenderTable
) m_renderTable
);
153 m_renderTable
= NULL
;
156 // TODO: why does freeing the font produce a segv???
157 // Note that XFreeFont wasn't called in wxWin 1.68 either.
158 // MBN: probably some interaction with fonts being still
159 // in use in some widgets...
160 // XFontStruct* fontStruct = (XFontStruct*) m_fontStruct;
161 // XFreeFont((Display*) m_display, fontStruct);
164 // ----------------------------------------------------------------------------
166 // ----------------------------------------------------------------------------
168 void wxFontRefData::Init(int pointSize
,
173 const wxString
& faceName
,
174 wxFontEncoding encoding
)
176 if (family
== wxDEFAULT
)
177 m_family
= wxFONTFAMILY_SWISS
;
181 m_faceName
= faceName
;
183 if (style
== wxDEFAULT
)
184 m_style
= wxFONTSTYLE_NORMAL
;
188 if (weight
== wxDEFAULT
)
189 m_weight
= wxFONTWEIGHT_NORMAL
;
193 if (pointSize
== wxDEFAULT
)
196 m_pointSize
= pointSize
;
198 m_underlined
= underlined
;
199 m_encoding
= encoding
;
202 wxFontRefData::~wxFontRefData()
204 wxList::compatibility_iterator node
= m_fonts
.GetFirst();
207 wxXFont
* f
= (wxXFont
*) node
->GetData();
209 node
= node
->GetNext();
214 #define M_FONTDATA ((wxFontRefData*)m_refData)
216 // ----------------------------------------------------------------------------
218 // ----------------------------------------------------------------------------
220 wxFont::wxFont(const wxNativeFontInfo
& info
)
222 (void)Create(info
.GetXFontName());
225 bool wxFont::Create(int pointSize
,
230 const wxString
& faceName
,
231 wxFontEncoding encoding
)
234 m_refData
= new wxFontRefData(pointSize
, family
, style
, weight
,
235 underlined
, faceName
, encoding
);
240 bool wxFont::Create(const wxString
& fontname
, wxFontEncoding enc
)
244 *this = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT
);
248 m_refData
= new wxFontRefData();
250 M_FONTDATA
->m_nativeFontInfo
.SetXFontName(fontname
); // X font name
254 wxStringTokenizer
tn( fontname
, wxT("-") );
256 tn
.GetNextToken(); // skip initial empty token
257 tn
.GetNextToken(); // foundry
260 M_FONTDATA
->m_faceName
= tn
.GetNextToken(); // family
262 tmp
= tn
.GetNextToken().MakeUpper(); // weight
263 if (tmp
== wxT("BOLD")) M_FONTDATA
->m_weight
= wxFONTWEIGHT_BOLD
;
264 if (tmp
== wxT("BLACK")) M_FONTDATA
->m_weight
= wxFONTWEIGHT_BOLD
;
265 if (tmp
== wxT("EXTRABOLD")) M_FONTDATA
->m_weight
= wxFONTWEIGHT_BOLD
;
266 if (tmp
== wxT("DEMIBOLD")) M_FONTDATA
->m_weight
= wxFONTWEIGHT_BOLD
;
267 if (tmp
== wxT("ULTRABOLD")) M_FONTDATA
->m_weight
= wxFONTWEIGHT_BOLD
;
269 if (tmp
== wxT("LIGHT")) M_FONTDATA
->m_weight
= wxFONTWEIGHT_LIGHT
;
270 if (tmp
== wxT("THIN")) M_FONTDATA
->m_weight
= wxFONTWEIGHT_LIGHT
;
272 tmp
= tn
.GetNextToken().MakeUpper(); // slant
273 if (tmp
== wxT("I")) M_FONTDATA
->m_style
= wxFONTSTYLE_ITALIC
;
274 if (tmp
== wxT("O")) M_FONTDATA
->m_style
= wxFONTSTYLE_ITALIC
;
276 tn
.GetNextToken(); // set width
277 tn
.GetNextToken(); // add. style
278 tn
.GetNextToken(); // pixel size
280 tmp
= tn
.GetNextToken(); // pointsize
283 long num
= wxStrtol (tmp
.mb_str(), (wxChar
**) NULL
, 10);
284 M_FONTDATA
->m_pointSize
= (int)(num
/ 10);
287 tn
.GetNextToken(); // x-res
288 tn
.GetNextToken(); // y-res
290 tmp
= tn
.GetNextToken().MakeUpper(); // spacing
293 M_FONTDATA
->m_family
= wxFONTFAMILY_MODERN
;
294 else if (M_FONTDATA
->m_faceName
== wxT("TIMES"))
295 M_FONTDATA
->m_family
= wxFONTFAMILY_ROMAN
;
296 else if (M_FONTDATA
->m_faceName
== wxT("HELVETICA"))
297 M_FONTDATA
->m_family
= wxFONTFAMILY_SWISS
;
298 else if (M_FONTDATA
->m_faceName
== wxT("LUCIDATYPEWRITER"))
299 M_FONTDATA
->m_family
= wxFONTFAMILY_TELETYPE
;
300 else if (M_FONTDATA
->m_faceName
== wxT("LUCIDA"))
301 M_FONTDATA
->m_family
= wxFONTFAMILY_DECORATIVE
;
302 else if (M_FONTDATA
->m_faceName
== wxT("UTOPIA"))
303 M_FONTDATA
->m_family
= wxFONTFAMILY_SCRIPT
;
305 tn
.GetNextToken(); // avg width
307 // deal with font encoding
308 M_FONTDATA
->m_encoding
= enc
;
309 if ( M_FONTDATA
->m_encoding
== wxFONTENCODING_SYSTEM
)
311 wxString registry
= tn
.GetNextToken().MakeUpper(),
312 encoding
= tn
.GetNextToken().MakeUpper();
314 if ( registry
== wxT("ISO8859") )
317 if ( wxSscanf(encoding
, wxT("%d"), &cp
) == 1 )
319 M_FONTDATA
->m_encoding
=
320 (wxFontEncoding
)(wxFONTENCODING_ISO8859_1
+ cp
- 1);
323 else if ( registry
== wxT("MICROSOFT") )
326 if ( wxSscanf(encoding
, wxT("cp125%d"), &cp
) == 1 )
328 M_FONTDATA
->m_encoding
=
329 (wxFontEncoding
)(wxFONTENCODING_CP1250
+ cp
);
332 else if ( registry
== wxT("KOI8") )
334 M_FONTDATA
->m_encoding
= wxFONTENCODING_KOI8
;
336 //else: unknown encoding - may be give a warning here?
347 wxGDIRefData
*wxFont::CreateGDIRefData() const
349 return new wxFontRefData
;
352 wxGDIRefData
*wxFont::CloneGDIRefData(const wxGDIRefData
*data
) const
354 return new wxFontRefData(*static_cast<const wxFontRefData
*>(data
));
357 // ----------------------------------------------------------------------------
358 // change the font attributes
359 // ----------------------------------------------------------------------------
361 void wxFont::Unshare()
363 // Don't change shared data
366 m_refData
= new wxFontRefData();
370 wxFontRefData
* ref
= new wxFontRefData(*(wxFontRefData
*)m_refData
);
376 void wxFont::SetPointSize(int pointSize
)
380 M_FONTDATA
->m_pointSize
= pointSize
;
381 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
384 void wxFont::SetFamily(wxFontFamily family
)
388 M_FONTDATA
->m_family
= family
;
389 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
392 void wxFont::SetStyle(wxFontStyle style
)
396 M_FONTDATA
->m_style
= style
;
397 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
400 void wxFont::SetWeight(wxFontWeight weight
)
404 M_FONTDATA
->m_weight
= weight
;
405 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
408 bool wxFont::SetFaceName(const wxString
& faceName
)
412 M_FONTDATA
->m_faceName
= faceName
;
413 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
415 return wxFontBase::SetFaceName(faceName
);
418 void wxFont::SetUnderlined(bool underlined
)
422 M_FONTDATA
->m_underlined
= underlined
;
425 void wxFont::SetEncoding(wxFontEncoding encoding
)
429 M_FONTDATA
->m_encoding
= encoding
;
430 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
433 void wxFont::DoSetNativeFontInfo(const wxNativeFontInfo
& info
)
437 M_FONTDATA
->m_nativeFontInfo
= info
;
440 // ----------------------------------------------------------------------------
441 // query font attributes
442 // ----------------------------------------------------------------------------
444 int wxFont::GetPointSize() const
446 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
448 return M_FONTDATA
->m_pointSize
;
451 wxString
wxFont::GetFaceName() const
453 wxCHECK_MSG( Ok(), wxEmptyString
, wxT("invalid font") );
455 return M_FONTDATA
->m_faceName
;
458 wxFontFamily
wxFont::DoGetFamily() const
460 return M_FONTDATA
->m_family
;
463 wxFontStyle
wxFont::GetStyle() const
465 wxCHECK_MSG( Ok(), wxFONTSTYLE_MAX
, wxT("invalid font") );
467 return M_FONTDATA
->m_style
;
470 wxFontWeight
wxFont::GetWeight() const
472 wxCHECK_MSG( Ok(), wxFONTWEIGHT_MAX
, wxT("invalid font") );
474 return M_FONTDATA
->m_weight
;
477 bool wxFont::GetUnderlined() const
479 wxCHECK_MSG( Ok(), false, wxT("invalid font") );
481 return M_FONTDATA
->m_underlined
;
484 wxFontEncoding
wxFont::GetEncoding() const
486 wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT
, wxT("invalid font") );
488 return M_FONTDATA
->m_encoding
;
491 const wxNativeFontInfo
*wxFont::GetNativeFontInfo() const
493 wxCHECK_MSG( Ok(), NULL
, wxT("invalid font") );
495 if(M_FONTDATA
->m_nativeFontInfo
.GetXFontName().empty())
498 return &(M_FONTDATA
->m_nativeFontInfo
);
501 // ----------------------------------------------------------------------------
502 // real implementation
503 // ----------------------------------------------------------------------------
505 // Find an existing, or create a new, XFontStruct
506 // based on this wxFont and the given scale. Append the
507 // font to list in the private data for future reference.
508 wxXFont
* wxFont::GetInternalFont(double scale
, WXDisplay
* display
) const
513 long intScale
= long(scale
* 100.0 + 0.5); // key for wxXFont
514 int pointSize
= (M_FONTDATA
->m_pointSize
* 10 * intScale
) / 100;
516 // search existing fonts first
517 wxList::compatibility_iterator node
= M_FONTDATA
->m_fonts
.GetFirst();
520 wxXFont
* f
= (wxXFont
*) node
->GetData();
521 if ((!display
|| (f
->m_display
== display
)) && (f
->m_scale
== intScale
))
523 node
= node
->GetNext();
526 // not found, create a new one
528 XFontStruct
*font
= (XFontStruct
*)
529 wxLoadQueryNearestFont(pointSize
,
530 M_FONTDATA
->m_family
,
532 M_FONTDATA
->m_weight
,
533 M_FONTDATA
->m_underlined
,
535 M_FONTDATA
->m_encoding
,
540 wxFAIL_MSG( wxT("Could not allocate even a default font -- something is wrong.") );
545 wxXFont
* f
= new wxXFont
;
546 #if wxMOTIF_NEW_FONT_HANDLING
547 XFreeFont( (Display
*) display
, font
);
549 f
->m_fontStruct
= (WXFontStructPtr
)font
;
551 f
->m_display
= ( display
? display
: wxGetDisplay() );
552 f
->m_scale
= intScale
;
554 #if wxMOTIF_USE_RENDER_TABLE
555 XmRendition rendition
;
556 XmRenderTable renderTable
;
560 #if wxMOTIF_NEW_FONT_HANDLING
561 char* fontSpec
= wxStrdup(xFontSpec
.mb_str());
562 XtSetArg( args
[count
], XmNfontName
, fontSpec
); ++count
;
563 XtSetArg( args
[count
], XmNfontType
, XmFONT_IS_FONTSET
); ++count
;
565 XtSetArg( args
[count
], XmNfont
, font
); ++count
;
567 XtSetArg( args
[count
], XmNunderlineType
,
568 GetUnderlined() ? XmSINGLE_LINE
: XmNO_LINE
); ++count
;
569 rendition
= XmRenditionCreate( XmGetXmDisplay( (Display
*)f
->m_display
),
572 renderTable
= XmRenderTableAddRenditions( NULL
, &rendition
, 1,
575 f
->m_renderTable
= (WXRenderTable
)renderTable
;
576 f
->m_rendition
= (WXRendition
)rendition
;
577 wxASSERT( f
->m_renderTable
!= NULL
);
578 #else // if !wxMOTIF_USE_RENDER_TABLE
579 f
->m_fontList
= XmFontListCreate ((XFontStruct
*) font
, XmSTRING_DEFAULT_CHARSET
);
580 wxASSERT( f
->m_fontList
!= NULL
);
583 M_FONTDATA
->m_fonts
.Append(f
);
588 #if !wxMOTIF_NEW_FONT_HANDLING
590 WXFontStructPtr
wxFont::GetFontStruct(double scale
, WXDisplay
* display
) const
592 wxXFont
* f
= GetInternalFont(scale
, display
);
594 return (f
? f
->m_fontStruct
: (WXFontStructPtr
) 0);
599 #if !wxMOTIF_USE_RENDER_TABLE
601 WXFontList
wxFont::GetFontList(double scale
, WXDisplay
* display
) const
603 wxXFont
* f
= GetInternalFont(scale
, display
);
605 return (f
? f
->m_fontList
: (WXFontList
) 0);
608 #else // if wxMOTIF_USE_RENDER_TABLE
610 WXRenderTable
wxFont::GetRenderTable(WXDisplay
* display
) const
612 wxXFont
* f
= GetInternalFont(1.0, display
);
614 return (f
? f
->m_renderTable
: (WXRenderTable
) 0);
617 #endif // wxMOTIF_USE_RENDER_TABLE
619 WXFontType
wxFont::GetFontType(WXDisplay
* display
) const
621 #if wxMOTIF_USE_RENDER_TABLE
622 return Ok() ? GetRenderTable(display
) : NULL
;
624 return Ok() ? GetFontList(1.0, display
) : NULL
;
628 WXFontType
wxFont::GetFontTypeC(WXDisplay
* display
) const
630 #if wxMOTIF_USE_RENDER_TABLE
631 return Ok() ? GetRenderTable(display
) : NULL
;
633 return Ok() ? XmFontListCopy( (XmFontList
)GetFontList(1.0, display
) ) : NULL
;
637 /*static*/ WXString
wxFont::GetFontTag()
639 #if wxMOTIF_USE_RENDER_TABLE
640 return (WXString
)XmNrenderTable
;
642 return (WXString
)XmNfontList
;
646 #if wxMOTIF_USE_RENDER_TABLE
648 WXFontSet
wxFont::GetFontSet(double scale
, WXDisplay
* display
) const
650 wxXFont
* f
= GetInternalFont(scale
, display
);
652 if( !f
) return (WXFontSet
) 0;
657 XtSetArg( args
[count
], XmNfont
, 0 ); ++count
;
658 XmRenditionRetrieve( (XmRendition
) f
->m_rendition
, args
, count
);
660 return (WXFontSet
) args
[0].value
;
663 void wxGetTextExtent(WXDisplay
* display
, const wxFont
& font
, double scale
,
665 int* width
, int* height
, int* ascent
, int* descent
)
667 XRectangle ink
, logical
;
668 WXFontSet fset
= font
.GetFontSet(scale
, display
);
670 XmbTextExtents( (XFontSet
)fset
, str
.mb_str(), str
.length(), &ink
, &logical
);
672 if( width
) *width
= logical
.width
;
673 if( height
) *height
= logical
.height
;
674 if( ascent
) *ascent
= -logical
.y
;
675 if( descent
) *descent
= logical
.height
+ logical
.y
;
678 #else // if !wxMOTIF_USE_RENDER_TABLE
680 void wxGetTextExtent(WXDisplay
* display
, const wxFont
& font
,
681 double scale
, const wxString
& str
,
682 int* width
, int* height
, int* ascent
, int* descent
)
684 WXFontStructPtr pFontStruct
= font
.GetFontStruct(scale
, display
);
686 int direction
, ascent2
, descent2
;
688 int slen
= str
.length();
690 XTextExtents((XFontStruct
*) pFontStruct
,
691 const_cast<char*>((const char *)str
.mb_str()), slen
,
692 &direction
, &ascent2
, &descent2
, &overall
);
695 *width
= (overall
.width
);
697 *height
= (ascent2
+ descent2
);
704 #endif // !wxMOTIF_USE_RENDER_TABLE