1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/motif/font.cpp
3 // Purpose: wxFont class
4 // Author: Julian Smart
7 // Copyright: (c) Julian Smart
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
23 #pragma message disable nosimpint
24 #include "wx/vms_x_fix.h"
28 #pragma message enable nosimpint
34 #include "wx/string.h"
35 #include "wx/utils.h" // for wxGetDisplay()
36 #include "wx/settings.h"
37 #include "wx/gdicmn.h"
40 #include "wx/fontutil.h" // for wxNativeFontInfo
41 #include "wx/tokenzr.h"
42 #include "wx/motif/private.h"
44 // ----------------------------------------------------------------------------
46 // ----------------------------------------------------------------------------
48 // For every wxFont, there must be a font for each display and scale requested.
49 // So these objects are stored in wxFontRefData::m_fonts
50 class wxXFont
: public wxObject
56 #if !wxMOTIF_NEW_FONT_HANDLING
57 WXFontStructPtr m_fontStruct
; // XFontStruct
59 #if !wxMOTIF_USE_RENDER_TABLE
60 WXFontList m_fontList
; // Motif XmFontList
61 #else // if wxMOTIF_USE_RENDER_TABLE
62 WXRenderTable m_renderTable
; // Motif XmRenderTable
63 WXRendition m_rendition
; // Motif XmRendition
65 WXDisplay
* m_display
; // XDisplay
66 int m_scale
; // Scale * 100
69 class wxFontRefData
: public wxGDIRefData
74 wxFontRefData(int size
= wxDEFAULT
,
75 wxFontFamily family
= wxFONTFAMILY_DEFAULT
,
76 wxFontStyle style
= wxFONTSTYLE_NORMAL
,
77 wxFontWeight weight
= wxFONTWEIGHT_NORMAL
,
78 bool underlined
= false,
79 const wxString
& faceName
= wxEmptyString
,
80 wxFontEncoding encoding
= wxFONTENCODING_DEFAULT
)
82 Init(size
, family
, style
, weight
, underlined
, faceName
, encoding
);
85 wxFontRefData(const wxFontRefData
& data
)
87 Init(data
.m_pointSize
, data
.m_family
, data
.m_style
, data
.m_weight
,
88 data
.m_underlined
, data
.m_faceName
, data
.m_encoding
);
91 virtual ~wxFontRefData();
94 // common part of all ctors
100 const wxString
& faceName
,
101 wxFontEncoding encoding
);
105 wxFontFamily m_family
;
107 wxFontWeight m_weight
;
110 wxFontEncoding m_encoding
;
112 wxNativeFontInfo m_nativeFontInfo
;
114 // A list of wxXFonts
118 // ============================================================================
120 // ============================================================================
122 // ----------------------------------------------------------------------------
124 // ----------------------------------------------------------------------------
128 #if !wxMOTIF_NEW_FONT_HANDLING
129 m_fontStruct
= (WXFontStructPtr
) 0;
131 #if !wxMOTIF_USE_RENDER_TABLE
132 m_fontList
= (WXFontList
) 0;
133 #else // if wxMOTIF_USE_RENDER_TABLE
134 m_renderTable
= (WXRenderTable
) 0;
135 m_rendition
= (WXRendition
) 0;
137 m_display
= (WXDisplay
*) 0;
143 #if !wxMOTIF_USE_RENDER_TABLE
145 XmFontListFree ((XmFontList
) m_fontList
);
147 #else // if wxMOTIF_USE_RENDER_TABLE
149 XmRenderTableFree ((XmRenderTable
) m_renderTable
);
150 m_renderTable
= NULL
;
153 // TODO: why does freeing the font produce a segv???
154 // Note that XFreeFont wasn't called in wxWin 1.68 either.
155 // MBN: probably some interaction with fonts being still
156 // in use in some widgets...
157 // XFontStruct* fontStruct = (XFontStruct*) m_fontStruct;
158 // XFreeFont((Display*) m_display, fontStruct);
161 // ----------------------------------------------------------------------------
163 // ----------------------------------------------------------------------------
165 void wxFontRefData::Init(int pointSize
,
170 const wxString
& faceName
,
171 wxFontEncoding encoding
)
173 if (family
== wxDEFAULT
)
174 m_family
= wxFONTFAMILY_SWISS
;
178 m_faceName
= faceName
;
180 if (style
== wxDEFAULT
)
181 m_style
= wxFONTSTYLE_NORMAL
;
185 if (weight
== wxDEFAULT
)
186 m_weight
= wxFONTWEIGHT_NORMAL
;
190 if (pointSize
== wxDEFAULT
)
193 m_pointSize
= pointSize
;
195 m_underlined
= underlined
;
196 m_encoding
= encoding
;
199 wxFontRefData::~wxFontRefData()
201 wxList::compatibility_iterator node
= m_fonts
.GetFirst();
204 wxXFont
* f
= (wxXFont
*) node
->GetData();
206 node
= node
->GetNext();
211 #define M_FONTDATA ((wxFontRefData*)m_refData)
213 // ----------------------------------------------------------------------------
215 // ----------------------------------------------------------------------------
217 wxFont::wxFont(const wxNativeFontInfo
& info
)
219 (void)Create(info
.GetXFontName());
222 bool wxFont::Create(int pointSize
,
227 const wxString
& faceName
,
228 wxFontEncoding encoding
)
231 m_refData
= new wxFontRefData(pointSize
, family
, style
, weight
,
232 underlined
, faceName
, encoding
);
237 bool wxFont::Create(const wxString
& fontname
, wxFontEncoding enc
)
241 *this = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT
);
245 m_refData
= new wxFontRefData();
247 M_FONTDATA
->m_nativeFontInfo
.SetXFontName(fontname
); // X font name
251 wxStringTokenizer
tn( fontname
, wxT("-") );
253 tn
.GetNextToken(); // skip initial empty token
254 tn
.GetNextToken(); // foundry
257 M_FONTDATA
->m_faceName
= tn
.GetNextToken(); // family
259 tmp
= tn
.GetNextToken().MakeUpper(); // weight
260 if (tmp
== wxT("BOLD")) M_FONTDATA
->m_weight
= wxFONTWEIGHT_BOLD
;
261 if (tmp
== wxT("BLACK")) M_FONTDATA
->m_weight
= wxFONTWEIGHT_BOLD
;
262 if (tmp
== wxT("EXTRABOLD")) M_FONTDATA
->m_weight
= wxFONTWEIGHT_BOLD
;
263 if (tmp
== wxT("DEMIBOLD")) M_FONTDATA
->m_weight
= wxFONTWEIGHT_BOLD
;
264 if (tmp
== wxT("ULTRABOLD")) M_FONTDATA
->m_weight
= wxFONTWEIGHT_BOLD
;
266 if (tmp
== wxT("LIGHT")) M_FONTDATA
->m_weight
= wxFONTWEIGHT_LIGHT
;
267 if (tmp
== wxT("THIN")) M_FONTDATA
->m_weight
= wxFONTWEIGHT_LIGHT
;
269 tmp
= tn
.GetNextToken().MakeUpper(); // slant
270 if (tmp
== wxT("I")) M_FONTDATA
->m_style
= wxFONTSTYLE_ITALIC
;
271 if (tmp
== wxT("O")) M_FONTDATA
->m_style
= wxFONTSTYLE_ITALIC
;
273 tn
.GetNextToken(); // set width
274 tn
.GetNextToken(); // add. style
275 tn
.GetNextToken(); // pixel size
277 tmp
= tn
.GetNextToken(); // pointsize
280 long num
= wxStrtol (tmp
.mb_str(), (wxChar
**) NULL
, 10);
281 M_FONTDATA
->m_pointSize
= (int)(num
/ 10);
284 tn
.GetNextToken(); // x-res
285 tn
.GetNextToken(); // y-res
287 tmp
= tn
.GetNextToken().MakeUpper(); // spacing
290 M_FONTDATA
->m_family
= wxFONTFAMILY_MODERN
;
291 else if (M_FONTDATA
->m_faceName
== wxT("TIMES"))
292 M_FONTDATA
->m_family
= wxFONTFAMILY_ROMAN
;
293 else if (M_FONTDATA
->m_faceName
== wxT("HELVETICA"))
294 M_FONTDATA
->m_family
= wxFONTFAMILY_SWISS
;
295 else if (M_FONTDATA
->m_faceName
== wxT("LUCIDATYPEWRITER"))
296 M_FONTDATA
->m_family
= wxFONTFAMILY_TELETYPE
;
297 else if (M_FONTDATA
->m_faceName
== wxT("LUCIDA"))
298 M_FONTDATA
->m_family
= wxFONTFAMILY_DECORATIVE
;
299 else if (M_FONTDATA
->m_faceName
== wxT("UTOPIA"))
300 M_FONTDATA
->m_family
= wxFONTFAMILY_SCRIPT
;
302 tn
.GetNextToken(); // avg width
304 // deal with font encoding
305 M_FONTDATA
->m_encoding
= enc
;
306 if ( M_FONTDATA
->m_encoding
== wxFONTENCODING_SYSTEM
)
308 wxString registry
= tn
.GetNextToken().MakeUpper(),
309 encoding
= tn
.GetNextToken().MakeUpper();
311 if ( registry
== wxT("ISO8859") )
314 if ( wxSscanf(encoding
, wxT("%d"), &cp
) == 1 )
316 M_FONTDATA
->m_encoding
=
317 (wxFontEncoding
)(wxFONTENCODING_ISO8859_1
+ cp
- 1);
320 else if ( registry
== wxT("MICROSOFT") )
323 if ( wxSscanf(encoding
, wxT("cp125%d"), &cp
) == 1 )
325 M_FONTDATA
->m_encoding
=
326 (wxFontEncoding
)(wxFONTENCODING_CP1250
+ cp
);
329 else if ( registry
== wxT("KOI8") )
331 M_FONTDATA
->m_encoding
= wxFONTENCODING_KOI8
;
333 //else: unknown encoding - may be give a warning here?
344 wxGDIRefData
*wxFont::CreateGDIRefData() const
346 return new wxFontRefData
;
349 wxGDIRefData
*wxFont::CloneGDIRefData(const wxGDIRefData
*data
) const
351 return new wxFontRefData(*static_cast<const wxFontRefData
*>(data
));
354 // ----------------------------------------------------------------------------
355 // change the font attributes
356 // ----------------------------------------------------------------------------
358 void wxFont::Unshare()
360 // Don't change shared data
363 m_refData
= new wxFontRefData();
367 wxFontRefData
* ref
= new wxFontRefData(*(wxFontRefData
*)m_refData
);
373 void wxFont::SetPointSize(int pointSize
)
377 M_FONTDATA
->m_pointSize
= pointSize
;
378 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
381 void wxFont::SetFamily(wxFontFamily family
)
385 M_FONTDATA
->m_family
= family
;
386 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
389 void wxFont::SetStyle(wxFontStyle style
)
393 M_FONTDATA
->m_style
= style
;
394 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
397 void wxFont::SetWeight(wxFontWeight weight
)
401 M_FONTDATA
->m_weight
= weight
;
402 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
405 bool wxFont::SetFaceName(const wxString
& faceName
)
409 M_FONTDATA
->m_faceName
= faceName
;
410 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
412 return wxFontBase::SetFaceName(faceName
);
415 void wxFont::SetUnderlined(bool underlined
)
419 M_FONTDATA
->m_underlined
= underlined
;
422 void wxFont::SetEncoding(wxFontEncoding encoding
)
426 M_FONTDATA
->m_encoding
= encoding
;
427 M_FONTDATA
->m_nativeFontInfo
.GetXFontName().Clear(); // invalid now
430 void wxFont::DoSetNativeFontInfo(const wxNativeFontInfo
& info
)
434 M_FONTDATA
->m_nativeFontInfo
= info
;
437 // ----------------------------------------------------------------------------
438 // query font attributes
439 // ----------------------------------------------------------------------------
441 int wxFont::GetPointSize() const
443 wxCHECK_MSG( IsOk(), 0, wxT("invalid font") );
445 return M_FONTDATA
->m_pointSize
;
448 wxString
wxFont::GetFaceName() const
450 wxCHECK_MSG( IsOk(), wxEmptyString
, wxT("invalid font") );
452 return M_FONTDATA
->m_faceName
;
455 wxFontFamily
wxFont::DoGetFamily() const
457 return M_FONTDATA
->m_family
;
460 wxFontStyle
wxFont::GetStyle() const
462 wxCHECK_MSG( IsOk(), wxFONTSTYLE_MAX
, wxT("invalid font") );
464 return M_FONTDATA
->m_style
;
467 wxFontWeight
wxFont::GetWeight() const
469 wxCHECK_MSG( IsOk(), wxFONTWEIGHT_MAX
, wxT("invalid font") );
471 return M_FONTDATA
->m_weight
;
474 bool wxFont::GetUnderlined() const
476 wxCHECK_MSG( IsOk(), false, wxT("invalid font") );
478 return M_FONTDATA
->m_underlined
;
481 wxFontEncoding
wxFont::GetEncoding() const
483 wxCHECK_MSG( IsOk(), wxFONTENCODING_DEFAULT
, wxT("invalid font") );
485 return M_FONTDATA
->m_encoding
;
488 const wxNativeFontInfo
*wxFont::GetNativeFontInfo() const
490 wxCHECK_MSG( IsOk(), NULL
, wxT("invalid font") );
492 if(M_FONTDATA
->m_nativeFontInfo
.GetXFontName().empty())
495 return &(M_FONTDATA
->m_nativeFontInfo
);
498 // ----------------------------------------------------------------------------
499 // real implementation
500 // ----------------------------------------------------------------------------
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.
505 wxXFont
* wxFont::GetInternalFont(double scale
, WXDisplay
* display
) const
510 long intScale
= long(scale
* 100.0 + 0.5); // key for wxXFont
511 int pointSize
= (M_FONTDATA
->m_pointSize
* 10 * intScale
) / 100;
513 // search existing fonts first
514 wxList::compatibility_iterator node
= M_FONTDATA
->m_fonts
.GetFirst();
517 wxXFont
* f
= (wxXFont
*) node
->GetData();
518 if ((!display
|| (f
->m_display
== display
)) && (f
->m_scale
== intScale
))
520 node
= node
->GetNext();
523 // not found, create a new one
525 XFontStruct
*font
= (XFontStruct
*)
526 wxLoadQueryNearestFont(pointSize
,
527 M_FONTDATA
->m_family
,
529 M_FONTDATA
->m_weight
,
530 M_FONTDATA
->m_underlined
,
532 M_FONTDATA
->m_encoding
,
537 wxFAIL_MSG( wxT("Could not allocate even a default font -- something is wrong.") );
542 wxXFont
* f
= new wxXFont
;
543 #if wxMOTIF_NEW_FONT_HANDLING
544 XFreeFont( (Display
*) display
, font
);
546 f
->m_fontStruct
= (WXFontStructPtr
)font
;
548 f
->m_display
= ( display
? display
: wxGetDisplay() );
549 f
->m_scale
= intScale
;
551 #if wxMOTIF_USE_RENDER_TABLE
552 XmRendition rendition
;
553 XmRenderTable renderTable
;
557 #if wxMOTIF_NEW_FONT_HANDLING
558 char* fontSpec
= wxStrdup(xFontSpec
.mb_str());
559 XtSetArg( args
[count
], XmNfontName
, fontSpec
); ++count
;
560 XtSetArg( args
[count
], XmNfontType
, XmFONT_IS_FONTSET
); ++count
;
562 XtSetArg( args
[count
], XmNfont
, font
); ++count
;
564 XtSetArg( args
[count
], XmNunderlineType
,
565 GetUnderlined() ? XmSINGLE_LINE
: XmNO_LINE
); ++count
;
566 rendition
= XmRenditionCreate( XmGetXmDisplay( (Display
*)f
->m_display
),
569 renderTable
= XmRenderTableAddRenditions( NULL
, &rendition
, 1,
572 f
->m_renderTable
= (WXRenderTable
)renderTable
;
573 f
->m_rendition
= (WXRendition
)rendition
;
574 wxASSERT( f
->m_renderTable
!= NULL
);
575 #else // if !wxMOTIF_USE_RENDER_TABLE
576 f
->m_fontList
= XmFontListCreate ((XFontStruct
*) font
, XmSTRING_DEFAULT_CHARSET
);
577 wxASSERT( f
->m_fontList
!= NULL
);
580 M_FONTDATA
->m_fonts
.Append(f
);
585 #if !wxMOTIF_NEW_FONT_HANDLING
587 WXFontStructPtr
wxFont::GetFontStruct(double scale
, WXDisplay
* display
) const
589 wxXFont
* f
= GetInternalFont(scale
, display
);
591 return (f
? f
->m_fontStruct
: (WXFontStructPtr
) 0);
596 #if !wxMOTIF_USE_RENDER_TABLE
598 WXFontList
wxFont::GetFontList(double scale
, WXDisplay
* display
) const
600 wxXFont
* f
= GetInternalFont(scale
, display
);
602 return (f
? f
->m_fontList
: (WXFontList
) 0);
605 #else // if wxMOTIF_USE_RENDER_TABLE
607 WXRenderTable
wxFont::GetRenderTable(WXDisplay
* display
) const
609 wxXFont
* f
= GetInternalFont(1.0, display
);
611 return (f
? f
->m_renderTable
: (WXRenderTable
) 0);
614 #endif // wxMOTIF_USE_RENDER_TABLE
616 WXFontType
wxFont::GetFontType(WXDisplay
* display
) const
618 #if wxMOTIF_USE_RENDER_TABLE
619 return IsOk() ? GetRenderTable(display
) : NULL
;
621 return IsOk() ? GetFontList(1.0, display
) : NULL
;
625 WXFontType
wxFont::GetFontTypeC(WXDisplay
* display
) const
627 #if wxMOTIF_USE_RENDER_TABLE
628 return IsOk() ? GetRenderTable(display
) : NULL
;
630 return IsOk() ? XmFontListCopy( (XmFontList
)GetFontList(1.0, display
) ) : NULL
;
634 /*static*/ WXString
wxFont::GetFontTag()
636 #if wxMOTIF_USE_RENDER_TABLE
637 return (WXString
)XmNrenderTable
;
639 return (WXString
)XmNfontList
;
643 #if wxMOTIF_USE_RENDER_TABLE
645 WXFontSet
wxFont::GetFontSet(double scale
, WXDisplay
* display
) const
647 wxXFont
* f
= GetInternalFont(scale
, display
);
649 if( !f
) return (WXFontSet
) 0;
654 XtSetArg( args
[count
], XmNfont
, 0 ); ++count
;
655 XmRenditionRetrieve( (XmRendition
) f
->m_rendition
, args
, count
);
657 return (WXFontSet
) args
[0].value
;
660 void wxGetTextExtent(WXDisplay
* display
, const wxFont
& font
, double scale
,
662 int* width
, int* height
, int* ascent
, int* descent
)
664 XRectangle ink
, logical
;
665 WXFontSet fset
= font
.GetFontSet(scale
, display
);
667 XmbTextExtents( (XFontSet
)fset
, str
.mb_str(), str
.length(), &ink
, &logical
);
669 if( width
) *width
= logical
.width
;
670 if( height
) *height
= logical
.height
;
671 if( ascent
) *ascent
= -logical
.y
;
672 if( descent
) *descent
= logical
.height
+ logical
.y
;
675 #else // if !wxMOTIF_USE_RENDER_TABLE
677 void wxGetTextExtent(WXDisplay
* display
, const wxFont
& font
,
678 double scale
, const wxString
& str
,
679 int* width
, int* height
, int* ascent
, int* descent
)
681 WXFontStructPtr pFontStruct
= font
.GetFontStruct(scale
, display
);
683 int direction
, ascent2
, descent2
;
685 int slen
= str
.length();
687 XTextExtents((XFontStruct
*) pFontStruct
,
688 const_cast<char*>((const char *)str
.mb_str()), slen
,
689 &direction
, &ascent2
, &descent2
, &overall
);
692 *width
= (overall
.width
);
694 *height
= (ascent2
+ descent2
);
701 #endif // !wxMOTIF_USE_RENDER_TABLE