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 // ----------------------------------------------------------------------------
21 #pragma implementation "font.h"
25 #pragma message disable nosimpint
26 #include "wx/vms_x_fix.h"
30 #pragma message enable nosimpint
34 #include "wx/string.h"
36 #include "wx/gdicmn.h"
37 #include "wx/utils.h" // for wxGetDisplay()
38 #include "wx/fontutil.h" // for wxNativeFontInfo
39 #include "wx/tokenzr.h"
40 #include "wx/settings.h"
42 IMPLEMENT_DYNAMIC_CLASS(wxFont
, wxGDIObject
)
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 WXFontStructPtr m_fontStruct
; // XFontStruct
57 WXFontList m_fontList
; // Motif XmFontList
58 WXDisplay
* m_display
; // XDisplay
59 int m_scale
; // Scale * 100
62 class wxFontRefData
: public wxGDIRefData
67 wxFontRefData(int size
= wxDEFAULT
,
68 int family
= wxDEFAULT
,
69 int style
= wxDEFAULT
,
70 int weight
= wxDEFAULT
,
71 bool underlined
= FALSE
,
72 const wxString
& faceName
= wxEmptyString
,
73 wxFontEncoding encoding
= wxFONTENCODING_DEFAULT
)
75 Init(size
, family
, style
, weight
, underlined
, faceName
, encoding
);
78 wxFontRefData(const wxFontRefData
& data
)
80 Init(data
.m_pointSize
, data
.m_family
, data
.m_style
, data
.m_weight
,
81 data
.m_underlined
, data
.m_faceName
, data
.m_encoding
);
87 // common part of all ctors
93 const wxString
& faceName
,
94 wxFontEncoding encoding
);
103 wxFontEncoding m_encoding
;
105 wxNativeFontInfo m_nativeFontInfo
;
107 // A list of wxXFonts
111 // ============================================================================
113 // ============================================================================
115 // ----------------------------------------------------------------------------
117 // ----------------------------------------------------------------------------
121 m_fontStruct
= (WXFontStructPtr
) 0;
122 m_fontList
= (WXFontList
) 0;
123 m_display
= (WXDisplay
*) 0;
129 XmFontList fontList
= (XmFontList
) m_fontList
;
131 XmFontListFree (fontList
);
133 // TODO: why does freeing the font produce a segv???
134 // Note that XFreeFont wasn't called in wxWin 1.68 either.
135 // XFontStruct* fontStruct = (XFontStruct*) m_fontStruct;
136 // XFreeFont((Display*) m_display, fontStruct);
139 // ----------------------------------------------------------------------------
141 // ----------------------------------------------------------------------------
143 void wxFontRefData::Init(int pointSize
,
148 const wxString
& faceName
,
149 wxFontEncoding encoding
)
151 if (family
== wxDEFAULT
)
156 m_faceName
= faceName
;
158 if (style
== wxDEFAULT
)
163 if (weight
== wxDEFAULT
)
168 if (pointSize
== wxDEFAULT
)
171 m_pointSize
= pointSize
;
173 m_underlined
= underlined
;
174 m_encoding
= encoding
;
177 wxFontRefData::~wxFontRefData()
179 wxNode
* node
= m_fonts
.First();
182 wxXFont
* f
= (wxXFont
*) node
->Data();
189 // ----------------------------------------------------------------------------
191 // ----------------------------------------------------------------------------
193 wxFont::wxFont(const wxNativeFontInfo
& info
)
197 (void)Create(info
.xFontName
);
204 bool wxFont::Create(int pointSize
,
209 const wxString
& faceName
,
210 wxFontEncoding encoding
)
213 m_refData
= new wxFontRefData(pointSize
, family
, style
, weight
,
214 underlined
, faceName
, encoding
);
221 bool wxFont::Create(const wxString
& fontname
, wxFontEncoding enc
)
225 *this = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT
);
229 m_refData
= new wxFontRefData();
231 M_FONTDATA
->m_nativeFontInfo
.xFontName
= fontname
; // X font name
235 wxStringTokenizer
tn( fontname
, wxT("-") );
237 tn
.GetNextToken(); // skip initial empty token
238 tn
.GetNextToken(); // foundry
241 M_FONTDATA
->m_faceName
= tn
.GetNextToken(); // family
243 tmp
= tn
.GetNextToken().MakeUpper(); // weight
244 if (tmp
== wxT("BOLD")) M_FONTDATA
->m_weight
= wxBOLD
;
245 if (tmp
== wxT("BLACK")) M_FONTDATA
->m_weight
= wxBOLD
;
246 if (tmp
== wxT("EXTRABOLD")) M_FONTDATA
->m_weight
= wxBOLD
;
247 if (tmp
== wxT("DEMIBOLD")) M_FONTDATA
->m_weight
= wxBOLD
;
248 if (tmp
== wxT("ULTRABOLD")) M_FONTDATA
->m_weight
= wxBOLD
;
250 if (tmp
== wxT("LIGHT")) M_FONTDATA
->m_weight
= wxLIGHT
;
251 if (tmp
== wxT("THIN")) M_FONTDATA
->m_weight
= wxLIGHT
;
253 tmp
= tn
.GetNextToken().MakeUpper(); // slant
254 if (tmp
== wxT("I")) M_FONTDATA
->m_style
= wxITALIC
;
255 if (tmp
== wxT("O")) M_FONTDATA
->m_style
= wxITALIC
;
257 tn
.GetNextToken(); // set width
258 tn
.GetNextToken(); // add. style
259 tn
.GetNextToken(); // pixel size
261 tmp
= tn
.GetNextToken(); // pointsize
264 long num
= wxStrtol (tmp
.c_str(), (wxChar
**) NULL
, 10);
265 M_FONTDATA
->m_pointSize
= (int)(num
/ 10);
268 tn
.GetNextToken(); // x-res
269 tn
.GetNextToken(); // y-res
271 tmp
= tn
.GetNextToken().MakeUpper(); // spacing
274 M_FONTDATA
->m_family
= wxMODERN
;
275 else if (M_FONTDATA
->m_faceName
== wxT("TIMES"))
276 M_FONTDATA
->m_family
= wxROMAN
;
277 else if (M_FONTDATA
->m_faceName
== wxT("HELVETICA"))
278 M_FONTDATA
->m_family
= wxSWISS
;
279 else if (M_FONTDATA
->m_faceName
== wxT("LUCIDATYPEWRITER"))
280 M_FONTDATA
->m_family
= wxTELETYPE
;
281 else if (M_FONTDATA
->m_faceName
== wxT("LUCIDA"))
282 M_FONTDATA
->m_family
= wxDECORATIVE
;
283 else if (M_FONTDATA
->m_faceName
== wxT("UTOPIA"))
284 M_FONTDATA
->m_family
= wxSCRIPT
;
286 tn
.GetNextToken(); // avg width
288 // deal with font encoding
289 M_FONTDATA
->m_encoding
= enc
;
290 if ( M_FONTDATA
->m_encoding
== wxFONTENCODING_SYSTEM
)
292 wxString registry
= tn
.GetNextToken().MakeUpper(),
293 encoding
= tn
.GetNextToken().MakeUpper();
295 if ( registry
== _T("ISO8859") )
298 if ( wxSscanf(encoding
, wxT("%d"), &cp
) == 1 )
300 M_FONTDATA
->m_encoding
=
301 (wxFontEncoding
)(wxFONTENCODING_ISO8859_1
+ cp
- 1);
304 else if ( registry
== _T("MICROSOFT") )
307 if ( wxSscanf(encoding
, wxT("cp125%d"), &cp
) == 1 )
309 M_FONTDATA
->m_encoding
=
310 (wxFontEncoding
)(wxFONTENCODING_CP1250
+ cp
);
313 else if ( registry
== _T("KOI8") )
315 M_FONTDATA
->m_encoding
= wxFONTENCODING_KOI8
;
317 //else: unknown encoding - may be give a warning here?
328 // ----------------------------------------------------------------------------
329 // change the font attributes
330 // ----------------------------------------------------------------------------
332 void wxFont::Unshare()
334 // Don't change shared data
337 m_refData
= new wxFontRefData();
341 wxFontRefData
* ref
= new wxFontRefData(*(wxFontRefData
*)m_refData
);
347 void wxFont::SetPointSize(int pointSize
)
351 M_FONTDATA
->m_pointSize
= pointSize
;
352 M_FONTDATA
->m_nativeFontInfo
.xFontName
.Clear(); // invalid now
357 void wxFont::SetFamily(int family
)
361 M_FONTDATA
->m_family
= family
;
362 M_FONTDATA
->m_nativeFontInfo
.xFontName
.Clear(); // invalid now
367 void wxFont::SetStyle(int style
)
371 M_FONTDATA
->m_style
= style
;
372 M_FONTDATA
->m_nativeFontInfo
.xFontName
.Clear(); // invalid now
377 void wxFont::SetWeight(int weight
)
381 M_FONTDATA
->m_weight
= weight
;
382 M_FONTDATA
->m_nativeFontInfo
.xFontName
.Clear(); // invalid now
387 void wxFont::SetFaceName(const wxString
& faceName
)
391 M_FONTDATA
->m_faceName
= faceName
;
392 M_FONTDATA
->m_nativeFontInfo
.xFontName
.Clear(); // invalid now
397 void wxFont::SetUnderlined(bool underlined
)
401 M_FONTDATA
->m_underlined
= underlined
;
406 void wxFont::SetEncoding(wxFontEncoding encoding
)
410 M_FONTDATA
->m_encoding
= encoding
;
411 M_FONTDATA
->m_nativeFontInfo
.xFontName
.Clear(); // invalid now
416 void wxFont::SetNativeFontInfo(const wxNativeFontInfo
& info
)
420 M_FONTDATA
->m_nativeFontInfo
= info
;
423 // ----------------------------------------------------------------------------
424 // query font attributes
425 // ----------------------------------------------------------------------------
427 int wxFont::GetPointSize() const
429 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
431 return M_FONTDATA
->m_pointSize
;
434 wxString
wxFont::GetFaceName() const
436 wxCHECK_MSG( Ok(), wxT(""), wxT("invalid font") );
438 return M_FONTDATA
->m_faceName
;
441 int wxFont::GetFamily() const
443 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
445 return M_FONTDATA
->m_family
;
448 int wxFont::GetStyle() const
450 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
452 return M_FONTDATA
->m_style
;
455 int wxFont::GetWeight() const
457 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
459 return M_FONTDATA
->m_weight
;
462 bool wxFont::GetUnderlined() const
464 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid font") );
466 return M_FONTDATA
->m_underlined
;
469 wxFontEncoding
wxFont::GetEncoding() const
471 wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT
, wxT("invalid font") );
473 return M_FONTDATA
->m_encoding
;
476 wxNativeFontInfo
*wxFont::GetNativeFontInfo() const
478 wxCHECK_MSG( Ok(), (wxNativeFontInfo
*)NULL
, wxT("invalid font") );
480 if(M_FONTDATA
->m_nativeFontInfo
.xFontName
.IsEmpty())
483 return new wxNativeFontInfo(M_FONTDATA
->m_nativeFontInfo
);
486 // ----------------------------------------------------------------------------
487 // real implementation
488 // ----------------------------------------------------------------------------
490 // Find an existing, or create a new, XFontStruct
491 // based on this wxFont and the given scale. Append the
492 // font to list in the private data for future reference.
493 wxXFont
* wxFont::GetInternalFont(double scale
, WXDisplay
* display
) const
496 return (wxXFont
*)NULL
;
498 long intScale
= long(scale
* 100.0 + 0.5); // key for wxXFont
499 int pointSize
= (M_FONTDATA
->m_pointSize
* 10 * intScale
) / 100;
501 // search existing fonts first
502 wxNode
* node
= M_FONTDATA
->m_fonts
.First();
505 wxXFont
* f
= (wxXFont
*) node
->Data();
506 if ((!display
|| (f
->m_display
== display
)) && (f
->m_scale
== intScale
))
511 // 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
);
523 wxFAIL_MSG( wxT("Could not allocate even a default font -- something is wrong.") );
525 return (wxXFont
*) NULL
;
528 wxXFont
* f
= new wxXFont
;
529 f
->m_fontStruct
= (WXFontStructPtr
)font
;
530 f
->m_display
= ( display
? display
: wxGetDisplay() );
531 f
->m_scale
= intScale
;
532 f
->m_fontList
= XmFontListCreate ((XFontStruct
*) font
, XmSTRING_DEFAULT_CHARSET
);
533 M_FONTDATA
->m_fonts
.Append(f
);
538 WXFontStructPtr
wxFont::GetFontStruct(double scale
, WXDisplay
* display
) const
540 wxXFont
* f
= GetInternalFont(scale
, display
);
542 return (f
? f
->m_fontStruct
: (WXFontStructPtr
) 0);
545 WXFontList
wxFont::GetFontList(double scale
, WXDisplay
* display
) const
547 wxXFont
* f
= GetInternalFont(scale
, display
);
549 return (f
? f
->m_fontList
: (WXFontList
) 0);