1
/////////////////////////////////////////////////////////////////////////////
2
// Name: src/unix/fontutil.cpp
3
// Purpose: Font helper functions for wxX11, wxGTK, wxMotif
4
// Author: Vadim Zeitlin
7
// RCS-ID: $Id: fontutil.cpp 71382 2012-05-09 14:24:03Z VZ $
8
// Copyright: (c) Vadim Zeitlin
9
// Licence: wxWindows licence
10
/////////////////////////////////////////////////////////////////////////////
12
// ============================================================================
14
// ============================================================================
16
// ----------------------------------------------------------------------------
18
// ----------------------------------------------------------------------------
20
// For compilers that support precompilation, includes "wx.h".
21
#include "wx/wxprec.h"
27
#include "wx/fontutil.h"
31
#include "wx/font.h" // wxFont enums
32
#include "wx/encinfo.h"
34
#include "wx/utils.h" // for wxGetDisplay()
35
#include "wx/module.h"
38
#include "wx/fontmap.h"
39
#include "wx/tokenzr.h"
40
#include "wx/fontenum.h"
44
#include "pango/pango.h"
47
#include "wx/gtk/private.h"
48
extern GtkWidget *wxGetRootWindow();
50
#define wxPANGO_CONV wxGTK_CONV_SYS
51
#define wxPANGO_CONV_BACK wxGTK_CONV_BACK_SYS
53
#include "wx/x11/private.h"
54
#include "wx/gtk/private/string.h"
56
#define wxPANGO_CONV(s) s.utf8_str()
57
#define wxPANGO_CONV_BACK(s) wxString::FromUTF8Unchecked(s)
60
// ----------------------------------------------------------------------------
62
// ----------------------------------------------------------------------------
64
void wxNativeFontInfo::Init()
69
void wxNativeFontInfo::Init(const wxNativeFontInfo& info)
72
description = pango_font_description_copy(info.description);
77
void wxNativeFontInfo::Free()
80
pango_font_description_free(description);
83
int wxNativeFontInfo::GetPointSize() const
85
return pango_font_description_get_size( description ) / PANGO_SCALE;
88
wxFontStyle wxNativeFontInfo::GetStyle() const
90
wxFontStyle m_style = wxFONTSTYLE_NORMAL;
92
switch (pango_font_description_get_style( description ))
94
case PANGO_STYLE_NORMAL:
95
m_style = wxFONTSTYLE_NORMAL;
97
case PANGO_STYLE_ITALIC:
98
m_style = wxFONTSTYLE_ITALIC;
100
case PANGO_STYLE_OBLIQUE:
101
m_style = wxFONTSTYLE_SLANT;
108
wxFontWeight wxNativeFontInfo::GetWeight() const
110
// We seem to currently initialize only by string.
111
// In that case PANGO_FONT_MASK_WEIGHT is always set.
112
// if (!(pango_font_description_get_set_fields(description) & PANGO_FONT_MASK_WEIGHT))
113
// return wxFONTWEIGHT_NORMAL;
115
PangoWeight pango_weight = pango_font_description_get_weight( description );
117
// Until the API can be changed the following ranges of weight values are used:
118
// wxFONTWEIGHT_LIGHT: 100 .. 349 - range of 250
119
// wxFONTWEIGHT_NORMAL: 350 .. 599 - range of 250
120
// wxFONTWEIGHT_BOLD: 600 .. 900 - range of 301 (600 is "semibold" already)
122
if (pango_weight >= 600)
123
return wxFONTWEIGHT_BOLD;
125
if (pango_weight < 350)
126
return wxFONTWEIGHT_LIGHT;
128
return wxFONTWEIGHT_NORMAL;
131
bool wxNativeFontInfo::GetUnderlined() const
136
bool wxNativeFontInfo::GetStrikethrough() const
141
wxString wxNativeFontInfo::GetFaceName() const
143
// the Pango "family" is the wx "face name"
144
return wxPANGO_CONV_BACK(pango_font_description_get_family(description));
147
wxFontFamily wxNativeFontInfo::GetFamily() const
149
wxFontFamily ret = wxFONTFAMILY_UNKNOWN;
151
const char *family_name = pango_font_description_get_family( description );
153
// note: not passing -1 as the 2nd parameter to g_ascii_strdown to work
154
// around a bug in the 64-bit glib shipped with solaris 10, -1 causes it
155
// to try to allocate 2^32 bytes.
158
wxGtkString family_text(g_ascii_strdown(family_name, strlen(family_name)));
160
// Check for some common fonts, to salvage what we can from the current
161
// win32 centric wxFont API:
162
if (wxStrnicmp( family_text, "monospace", 9 ) == 0)
163
ret = wxFONTFAMILY_TELETYPE; // begins with "Monospace"
164
else if (wxStrnicmp( family_text, "courier", 7 ) == 0)
165
ret = wxFONTFAMILY_TELETYPE; // begins with "Courier"
166
#if defined(__WXGTK20__) || defined(HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE)
169
PangoFontFamily **families;
170
PangoFontFamily *family = NULL;
172
pango_context_list_families(
174
gtk_widget_get_pango_context( wxGetRootWindow() ),
176
wxTheApp->GetPangoContext(),
178
&families, &n_families);
180
for (int i = 0; i < n_families; ++i)
182
if (g_ascii_strcasecmp(pango_font_family_get_name( families[i] ),
183
pango_font_description_get_family( description )) == 0 )
185
family = families[i];
192
// Some gtk+ systems might query for a non-existing font from
193
// wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) on initialization,
194
// don't assert until wxSystemSettings::GetFont is checked for this - MR
195
// wxASSERT_MSG( family, "No appropriate PangoFontFamily found for ::description" );
197
if (family != NULL && pango_font_family_is_monospace( family ))
198
ret = wxFONTFAMILY_TELETYPE; // is deemed a monospace font by pango
200
#endif // GTK+ 2 || HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE
202
if (ret == wxFONTFAMILY_UNKNOWN)
204
if (strstr( family_text, "sans" ) != NULL || strstr( family_text, "Sans" ) != NULL)
205
// checked before serif, so that "* Sans Serif" fonts are detected correctly
206
ret = wxFONTFAMILY_SWISS; // contains "Sans"
207
else if (strstr( family_text, "serif" ) != NULL || strstr( family_text, "Serif" ) != NULL)
208
ret = wxFONTFAMILY_ROMAN; // contains "Serif"
209
else if (wxStrnicmp( family_text, "times", 5 ) == 0)
210
ret = wxFONTFAMILY_ROMAN; // begins with "Times"
211
else if (wxStrnicmp( family_text, "old", 3 ) == 0)
212
ret = wxFONTFAMILY_DECORATIVE; // begins with "Old" - "Old English", "Old Town"
218
wxFontEncoding wxNativeFontInfo::GetEncoding() const
220
return wxFONTENCODING_SYSTEM;
223
void wxNativeFontInfo::SetPointSize(int pointsize)
225
pango_font_description_set_size( description, pointsize * PANGO_SCALE );
228
void wxNativeFontInfo::SetStyle(wxFontStyle style)
232
case wxFONTSTYLE_ITALIC:
233
pango_font_description_set_style( description, PANGO_STYLE_ITALIC );
235
case wxFONTSTYLE_SLANT:
236
pango_font_description_set_style( description, PANGO_STYLE_OBLIQUE );
239
wxFAIL_MSG( "unknown font style" );
241
case wxFONTSTYLE_NORMAL:
242
pango_font_description_set_style( description, PANGO_STYLE_NORMAL );
247
void wxNativeFontInfo::SetWeight(wxFontWeight weight)
251
case wxFONTWEIGHT_BOLD:
252
pango_font_description_set_weight(description, PANGO_WEIGHT_BOLD);
254
case wxFONTWEIGHT_LIGHT:
255
pango_font_description_set_weight(description, PANGO_WEIGHT_LIGHT);
258
wxFAIL_MSG( "unknown font weight" );
260
case wxFONTWEIGHT_NORMAL:
261
pango_font_description_set_weight(description, PANGO_WEIGHT_NORMAL);
265
void wxNativeFontInfo::SetUnderlined(bool WXUNUSED(underlined))
267
// wxWindowDCImpl::DoDrawText will take care of rendering font with
268
// the underline attribute!
269
wxFAIL_MSG( "not implemented" );
272
void wxNativeFontInfo::SetStrikethrough(bool WXUNUSED(strikethrough))
274
wxFAIL_MSG( "not implemented" );
277
bool wxNativeFontInfo::SetFaceName(const wxString& facename)
279
pango_font_description_set_family(description, wxPANGO_CONV(facename));
281
// we return true because Pango doesn't tell us if the call failed or not;
282
// instead on wxGTK wxFont::SetFaceName() will call wxFontBase::SetFaceName()
283
// which does the check
287
void wxNativeFontInfo::SetFamily(wxFontFamily family)
289
wxArrayString facename;
291
// the list of fonts associated with a family was partially
292
// taken from http://www.codestyle.org/css/font-family
296
case wxFONTFAMILY_SCRIPT:
297
// corresponds to the cursive font family in the page linked above
298
facename.Add(wxS("URW Chancery L"));
299
facename.Add(wxS("Comic Sans MS"));
302
case wxFONTFAMILY_DECORATIVE:
303
// corresponds to the fantasy font family in the page linked above
304
facename.Add(wxS("Impact"));
307
case wxFONTFAMILY_ROMAN:
308
// corresponds to the serif font family in the page linked above
309
facename.Add(wxS("Serif"));
310
facename.Add(wxS("DejaVu Serif"));
311
facename.Add(wxS("DejaVu LGC Serif"));
312
facename.Add(wxS("Bitstream Vera Serif"));
313
facename.Add(wxS("Liberation Serif"));
314
facename.Add(wxS("FreeSerif"));
315
facename.Add(wxS("Luxi Serif"));
316
facename.Add(wxS("Times New Roman"));
317
facename.Add(wxS("Century Schoolbook L"));
318
facename.Add(wxS("URW Bookman L"));
319
facename.Add(wxS("URW Palladio L"));
320
facename.Add(wxS("Times"));
323
case wxFONTFAMILY_TELETYPE:
324
case wxFONTFAMILY_MODERN:
325
// corresponds to the monospace font family in the page linked above
326
facename.Add(wxS("Monospace"));
327
facename.Add(wxS("DejaVu Sans Mono"));
328
facename.Add(wxS("DejaVu LGC Sans Mono"));
329
facename.Add(wxS("Bitstream Vera Sans Mono"));
330
facename.Add(wxS("Liberation Mono"));
331
facename.Add(wxS("FreeMono"));
332
facename.Add(wxS("Luxi Mono"));
333
facename.Add(wxS("Courier New"));
334
facename.Add(wxS("Lucida Sans Typewriter"));
335
facename.Add(wxS("Nimbus Mono L"));
336
facename.Add(wxS("Andale Mono"));
337
facename.Add(wxS("Courier"));
340
case wxFONTFAMILY_SWISS:
341
case wxFONTFAMILY_DEFAULT:
343
// corresponds to the sans-serif font family in the page linked above
344
facename.Add(wxS("Sans"));
345
facename.Add(wxS("DejaVu Sans"));
346
facename.Add(wxS("DejaVu LGC Sans"));
347
facename.Add(wxS("Bitstream Vera Sans"));
348
facename.Add(wxS("Liberation Sans"));
349
facename.Add(wxS("FreeSans"));
350
facename.Add(wxS("Luxi Sans"));
351
facename.Add(wxS("Arial"));
352
facename.Add(wxS("Lucida Sans"));
353
facename.Add(wxS("Nimbus Sans L"));
354
facename.Add(wxS("URW Gothic L"));
358
SetFaceName(facename);
361
void wxNativeFontInfo::SetEncoding(wxFontEncoding WXUNUSED(encoding))
363
wxFAIL_MSG( "not implemented: Pango encoding is always UTF8" );
366
bool wxNativeFontInfo::FromString(const wxString& s)
369
pango_font_description_free( description );
371
// there is a bug in at least pango <= 1.13 which makes it (or its backends)
372
// segfault for very big point sizes and for negative point sizes.
373
// To workaround that bug for pango <= 1.13
374
// (see http://bugzilla.gnome.org/show_bug.cgi?id=340229)
375
// we do the check on the size here using same (arbitrary) limits used by
376
// pango > 1.13. Note that the segfault could happen also for pointsize
377
// smaller than this limit !!
379
const size_t pos = str.find_last_of(wxS(" "));
381
if ( pos != wxString::npos && wxString(str, pos + 1).ToDouble(&size) )
386
else if ( size >= 1E6 )
387
sizeStr = wxS("1E6");
389
if ( !sizeStr.empty() )
391
// replace the old size with the adjusted one
392
str = wxString(s, 0, pos) + sizeStr;
396
description = pango_font_description_from_string(wxPANGO_CONV(str));
399
// ensure a valid facename is selected
400
if (!wxFontEnumerator::IsValidFacename(GetFaceName()))
401
SetFaceName(wxNORMAL_FONT->GetFaceName());
402
#endif // wxUSE_FONTENUM
407
wxString wxNativeFontInfo::ToString() const
409
wxGtkString str(pango_font_description_to_string( description ));
411
return wxPANGO_CONV_BACK(str);
414
bool wxNativeFontInfo::FromUserString(const wxString& s)
416
return FromString( s );
419
wxString wxNativeFontInfo::ToUserString() const
428
#pragma message disable nosimpint
431
#include <X11/Xlib.h>
434
#pragma message enable nosimpint
437
#elif defined(__WXGTK__)
438
// we have to declare struct tm to avoid problems with first forward
439
// declaring it in C code (glib.h included from gdk.h does it) and then
440
// defining it when time.h is included from the headers below - this is
441
// known not to work at least with Sun CC 6.01
448
// ----------------------------------------------------------------------------
450
// ----------------------------------------------------------------------------
452
static wxHashTable *g_fontHash = NULL;
454
// ----------------------------------------------------------------------------
456
// ----------------------------------------------------------------------------
458
// define the functions to create and destroy native fonts for this toolkit
460
wxNativeFont wxLoadFont(const wxString& fontSpec)
462
return XLoadQueryFont((Display *)wxGetDisplay(), fontSpec);
465
inline void wxFreeFont(wxNativeFont font)
467
XFreeFont((Display *)wxGetDisplay(), (XFontStruct *)font);
469
#elif defined(__WXGTK__)
470
wxNativeFont wxLoadFont(const wxString& fontSpec)
472
// VZ: we should use gdk_fontset_load() instead of gdk_font_load()
473
// here to be able to display Japanese fonts correctly (at least
474
// this is what people report) but unfortunately doing it results
475
// in tons of warnings when using GTK with "normal" European
476
// languages and so we can't always do it and I don't know enough
477
// to determine when should this be done... (FIXME)
478
return gdk_font_load( wxConvertWX2MB(fontSpec) );
481
inline void wxFreeFont(wxNativeFont font)
483
gdk_font_unref(font);
486
#error "Unknown GUI toolkit"
489
static bool wxTestFontSpec(const wxString& fontspec);
491
static wxNativeFont wxLoadQueryFont(int pointSize,
496
const wxString& facename,
497
const wxString& xregistry,
498
const wxString& xencoding,
499
wxString* xFontName);
501
// ============================================================================
503
// ============================================================================
505
// ----------------------------------------------------------------------------
506
// wxNativeEncodingInfo
507
// ----------------------------------------------------------------------------
509
// convert to/from the string representation: format is
510
// encodingid;registry;encoding[;facename]
511
bool wxNativeEncodingInfo::FromString(const wxString& s)
513
// use ";", not "-" because it may be part of encoding name
514
wxStringTokenizer tokenizer(s, wxT(";"));
516
wxString encid = tokenizer.GetNextToken();
518
if ( !encid.ToLong(&enc) )
520
encoding = (wxFontEncoding)enc;
522
xregistry = tokenizer.GetNextToken();
526
xencoding = tokenizer.GetNextToken();
531
facename = tokenizer.GetNextToken();
536
wxString wxNativeEncodingInfo::ToString() const
539
s << (long)encoding << wxT(';') << xregistry << wxT(';') << xencoding;
540
if ( !facename.empty() )
542
s << wxT(';') << facename;
548
// ----------------------------------------------------------------------------
550
// ----------------------------------------------------------------------------
552
void wxNativeFontInfo::Init()
557
bool wxNativeFontInfo::FromString(const wxString& s)
559
wxStringTokenizer tokenizer(s, wxT(";"));
562
wxString token = tokenizer.GetNextToken();
563
if ( token != wxT('0') )
566
xFontName = tokenizer.GetNextToken();
568
// this should be the end
569
if ( tokenizer.HasMoreTokens() )
572
return FromXFontName(xFontName);
575
wxString wxNativeFontInfo::ToString() const
578
return wxString::Format(wxT("%d;%s"), 0, GetXFontName().c_str());
581
bool wxNativeFontInfo::FromUserString(const wxString& s)
583
return FromXFontName(s);
586
wxString wxNativeFontInfo::ToUserString() const
588
return GetXFontName();
591
bool wxNativeFontInfo::HasElements() const
593
// we suppose that the foundry is never empty, so if it is it means that we
594
// had never parsed the XLFD
595
return !fontElements[0].empty();
598
wxString wxNativeFontInfo::GetXFontComponent(wxXLFDField field) const
600
wxCHECK_MSG( field < wxXLFD_MAX, wxEmptyString, wxT("invalid XLFD field") );
602
if ( !HasElements() )
604
if ( !const_cast<wxNativeFontInfo *>(this)->FromXFontName(xFontName) )
605
return wxEmptyString;
608
return fontElements[field];
611
bool wxNativeFontInfo::FromXFontName(const wxString& fontname)
613
// TODO: we should be able to handle the font aliases here, but how?
614
wxStringTokenizer tokenizer(fontname, wxT("-"));
616
// skip the leading, usually empty field (font name registry)
617
if ( !tokenizer.HasMoreTokens() )
620
(void)tokenizer.GetNextToken();
622
for ( size_t n = 0; n < WXSIZEOF(fontElements); n++ )
624
if ( !tokenizer.HasMoreTokens() )
626
// not enough elements in the XLFD - or maybe an alias
630
wxString field = tokenizer.GetNextToken();
631
if ( !field.empty() && field != wxT('*') )
633
// we're really initialized now
637
fontElements[n] = field;
640
// this should be all
641
if ( tokenizer.HasMoreTokens() )
647
wxString wxNativeFontInfo::GetXFontName() const
649
if ( xFontName.empty() )
651
for ( size_t n = 0; n < WXSIZEOF(fontElements); n++ )
653
// replace the non specified elements with '*' except for the
654
// additional style which is usually just omitted
655
wxString elt = fontElements[n];
656
if ( elt.empty() && n != wxXLFD_ADDSTYLE )
661
const_cast<wxNativeFontInfo *>(this)->xFontName << wxT('-') << elt;
669
wxNativeFontInfo::SetXFontComponent(wxXLFDField field, const wxString& value)
671
wxCHECK_RET( field < wxXLFD_MAX, wxT("invalid XLFD field") );
673
// this class should be initialized with a valid font spec first and only
674
// then the fields may be modified!
675
wxASSERT_MSG( !IsDefault(), wxT("can't modify an uninitialized XLFD") );
677
if ( !HasElements() )
679
if ( !const_cast<wxNativeFontInfo *>(this)->FromXFontName(xFontName) )
681
wxFAIL_MSG( wxT("can't set font element for invalid XLFD") );
687
fontElements[field] = value;
689
// invalidate the XFLD, it doesn't correspond to the font elements any more
693
void wxNativeFontInfo::SetXFontName(const wxString& xFontName_)
695
// invalidate the font elements, GetXFontComponent() will reparse the XLFD
696
fontElements[0].clear();
698
xFontName = xFontName_;
703
int wxNativeFontInfo::GetPointSize() const
705
const wxString s = GetXFontComponent(wxXLFD_POINTSIZE);
707
// return -1 to indicate that the size is unknown
709
return s.ToLong(&l) ? l : -1;
712
wxFontStyle wxNativeFontInfo::GetStyle() const
714
const wxString s = GetXFontComponent(wxXLFD_SLANT);
716
if ( s.length() != 1 )
718
// it is really unknown but we don't have any way to return it from
720
return wxFONTSTYLE_NORMAL;
723
switch ( s[0].GetValue() )
726
// again, unknown but consider normal by default
729
return wxFONTSTYLE_NORMAL;
732
return wxFONTSTYLE_ITALIC;
735
return wxFONTSTYLE_SLANT;
739
wxFontWeight wxNativeFontInfo::GetWeight() const
741
const wxString s = GetXFontComponent(wxXLFD_WEIGHT).MakeLower();
742
if ( s.find(wxT("bold")) != wxString::npos || s == wxT("black") )
743
return wxFONTWEIGHT_BOLD;
744
else if ( s == wxT("light") )
745
return wxFONTWEIGHT_LIGHT;
747
return wxFONTWEIGHT_NORMAL;
750
bool wxNativeFontInfo::GetUnderlined() const
752
// X fonts are never underlined
756
wxString wxNativeFontInfo::GetFaceName() const
758
// wxWidgets facename probably more accurately corresponds to X family
759
return GetXFontComponent(wxXLFD_FAMILY);
762
wxFontFamily wxNativeFontInfo::GetFamily() const
764
// and wxWidgets family -- to X foundry, but we have to translate it to
765
// wxFontFamily somehow...
766
wxFAIL_MSG(wxT("not implemented")); // GetXFontComponent(wxXLFD_FOUNDRY);
768
return wxFONTFAMILY_DEFAULT;
771
wxFontEncoding wxNativeFontInfo::GetEncoding() const
773
// we already have the code for this but need to refactor it first
774
wxFAIL_MSG( wxT("not implemented") );
776
return wxFONTENCODING_MAX;
779
void wxNativeFontInfo::SetPointSize(int pointsize)
781
SetXFontComponent(wxXLFD_POINTSIZE, wxString::Format(wxT("%d"), pointsize));
784
void wxNativeFontInfo::SetStyle(wxFontStyle style)
789
case wxFONTSTYLE_ITALIC:
793
case wxFONTSTYLE_SLANT:
797
case wxFONTSTYLE_NORMAL:
801
wxFAIL_MSG( wxT("unknown wxFontStyle in wxNativeFontInfo::SetStyle") );
805
SetXFontComponent(wxXLFD_SLANT, s);
808
void wxNativeFontInfo::SetWeight(wxFontWeight weight)
813
case wxFONTWEIGHT_BOLD:
817
case wxFONTWEIGHT_LIGHT:
821
case wxFONTWEIGHT_NORMAL:
826
wxFAIL_MSG( wxT("unknown wxFontWeight in wxNativeFontInfo::SetWeight") );
830
SetXFontComponent(wxXLFD_WEIGHT, s);
833
void wxNativeFontInfo::SetUnderlined(bool WXUNUSED(underlined))
835
// can't do this under X
838
void wxNativeFontInfo::SetStrikethrough(bool WXUNUSED(strikethrough))
840
// this is not supported by Pango fonts neither
843
bool wxNativeFontInfo::SetFaceName(const wxString& facename)
845
SetXFontComponent(wxXLFD_FAMILY, facename);
849
void wxNativeFontInfo::SetFamily(wxFontFamily WXUNUSED(family))
851
// wxFontFamily -> X foundry, anyone?
852
wxFAIL_MSG( wxT("not implemented") );
854
// SetXFontComponent(wxXLFD_FOUNDRY, ...);
857
void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding)
859
wxNativeEncodingInfo info;
860
if ( wxGetNativeFontEncoding(encoding, &info) )
862
SetXFontComponent(wxXLFD_ENCODING, info.xencoding);
863
SetXFontComponent(wxXLFD_REGISTRY, info.xregistry);
867
// ----------------------------------------------------------------------------
869
// ----------------------------------------------------------------------------
871
bool wxGetNativeFontEncoding(wxFontEncoding encoding,
872
wxNativeEncodingInfo *info)
874
wxCHECK_MSG( info, false, wxT("bad pointer in wxGetNativeFontEncoding") );
876
if ( encoding == wxFONTENCODING_DEFAULT )
878
encoding = wxFont::GetDefaultEncoding();
883
case wxFONTENCODING_ISO8859_1:
884
case wxFONTENCODING_ISO8859_2:
885
case wxFONTENCODING_ISO8859_3:
886
case wxFONTENCODING_ISO8859_4:
887
case wxFONTENCODING_ISO8859_5:
888
case wxFONTENCODING_ISO8859_6:
889
case wxFONTENCODING_ISO8859_7:
890
case wxFONTENCODING_ISO8859_8:
891
case wxFONTENCODING_ISO8859_9:
892
case wxFONTENCODING_ISO8859_10:
893
case wxFONTENCODING_ISO8859_11:
894
case wxFONTENCODING_ISO8859_12:
895
case wxFONTENCODING_ISO8859_13:
896
case wxFONTENCODING_ISO8859_14:
897
case wxFONTENCODING_ISO8859_15:
899
int cp = encoding - wxFONTENCODING_ISO8859_1 + 1;
900
info->xregistry = wxT("iso8859");
901
info->xencoding.Printf(wxT("%d"), cp);
905
case wxFONTENCODING_UTF8:
906
info->xregistry = wxT("iso10646");
907
info->xencoding = wxT("*");
910
case wxFONTENCODING_GB2312:
911
info->xregistry = wxT("GB2312"); // or the otherway round?
912
info->xencoding = wxT("*");
915
case wxFONTENCODING_KOI8:
916
case wxFONTENCODING_KOI8_U:
917
info->xregistry = wxT("koi8");
919
// we don't make distinction between koi8-r, koi8-u and koi8-ru (so far)
920
info->xencoding = wxT("*");
923
case wxFONTENCODING_CP1250:
924
case wxFONTENCODING_CP1251:
925
case wxFONTENCODING_CP1252:
926
case wxFONTENCODING_CP1253:
927
case wxFONTENCODING_CP1254:
928
case wxFONTENCODING_CP1255:
929
case wxFONTENCODING_CP1256:
930
case wxFONTENCODING_CP1257:
932
int cp = encoding - wxFONTENCODING_CP1250 + 1250;
933
info->xregistry = wxT("microsoft");
934
info->xencoding.Printf(wxT("cp%d"), cp);
938
case wxFONTENCODING_EUC_JP:
939
case wxFONTENCODING_SHIFT_JIS:
940
info->xregistry = "jis*";
941
info->xencoding = "*";
944
case wxFONTENCODING_SYSTEM:
946
info->xencoding = wxT("*");
950
// don't know how to translate this encoding into X fontspec
954
info->encoding = encoding;
959
bool wxTestFontEncoding(const wxNativeEncodingInfo& info)
962
fontspec.Printf(wxT("-*-%s-*-*-*-*-*-*-*-*-*-*-%s-%s"),
963
!info.facename ? wxT("*") : info.facename.c_str(),
964
info.xregistry.c_str(),
965
info.xencoding.c_str());
967
return wxTestFontSpec(fontspec);
970
// ----------------------------------------------------------------------------
971
// X-specific functions
972
// ----------------------------------------------------------------------------
974
wxNativeFont wxLoadQueryNearestFont(int pointSize,
979
const wxString &facename,
980
wxFontEncoding encoding,
983
if ( encoding == wxFONTENCODING_DEFAULT )
985
encoding = wxFont::GetDefaultEncoding();
988
// first determine the encoding - if the font doesn't exist at all in this
989
// encoding, it's useless to do all other approximations (i.e. size,
990
// family &c don't matter much)
991
wxNativeEncodingInfo info;
992
if ( encoding == wxFONTENCODING_SYSTEM )
994
// This will always work so we don't test to save time
995
wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
999
if ( !wxGetNativeFontEncoding(encoding, &info) ||
1000
!wxTestFontEncoding(info) )
1003
if ( !wxFontMapper::Get()->GetAltForEncoding(encoding, &info) )
1004
#endif // wxUSE_FONTMAP
1006
// unspported encoding - replace it with the default
1008
// NB: we can't just return 0 from here because wxGTK code doesn't
1009
// check for it (i.e. it supposes that we'll always succeed),
1010
// so it would provoke a crash
1011
wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
1016
// OK, we have the correct xregistry/xencoding in info structure
1017
wxNativeFont font = 0;
1019
// if we already have the X font name, try to use it
1020
if( xFontName && !xFontName->empty() )
1023
// Make sure point size is correct for scale factor.
1025
wxStringTokenizer tokenizer(*xFontName, wxT("-"), wxTOKEN_RET_DELIMS);
1026
wxString newFontName;
1028
for(int i = 0; i < 8; i++)
1029
newFontName += tokenizer.NextToken();
1031
(void) tokenizer.NextToken();
1033
newFontName += wxString::Format(wxT("%d-"), pointSize);
1035
while(tokenizer.HasMoreTokens())
1036
newFontName += tokenizer.GetNextToken();
1038
font = wxLoadFont(newFontName);
1041
*xFontName = newFontName;
1046
// search up and down by stepsize 10
1047
int max_size = pointSize + 20 * (1 + (pointSize/180));
1048
int min_size = pointSize - 20 * (1 + (pointSize/180));
1050
int i, round; // counters
1052
// first round: search for equal, then for smaller and for larger size
1053
// with the given weight and style
1054
int testweight = weight;
1055
int teststyle = style;
1057
for ( round = 0; round < 3; round++ )
1059
// second round: use normal weight
1062
if ( testweight != wxNORMAL )
1064
testweight = wxNORMAL;
1068
++round; // fall through to third round
1072
// third round: ... and use normal style
1075
if ( teststyle != wxNORMAL )
1077
teststyle = wxNORMAL;
1084
// Search for equal or smaller size (approx.)
1085
for ( i = pointSize; !font && i >= 10 && i >= min_size; i -= 10 )
1087
font = wxLoadQueryFont(i, family, teststyle, testweight, underlined,
1088
facename, info.xregistry, info.xencoding,
1092
// Search for larger size (approx.)
1093
for ( i = pointSize + 10; !font && i <= max_size; i += 10 )
1095
font = wxLoadQueryFont(i, family, teststyle, testweight, underlined,
1096
facename, info.xregistry, info.xencoding,
1101
// Try default family
1102
if ( !font && family != wxDEFAULT )
1104
font = wxLoadQueryFont(pointSize, wxDEFAULT, style, weight,
1105
underlined, facename,
1106
info.xregistry, info.xencoding,
1110
// ignore size, family, style and weight but try to find font with the
1111
// given facename and encoding
1114
font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
1115
underlined, facename,
1116
info.xregistry, info.xencoding,
1119
// ignore family as well
1122
font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
1123
underlined, wxEmptyString,
1124
info.xregistry, info.xencoding,
1127
// if it still failed, try to get the font of any size but
1128
// with the requested encoding: this can happen if the
1129
// encoding is only available in one size which happens to be
1130
// different from 120
1133
font = wxLoadQueryFont(-1, wxDEFAULT, wxNORMAL, wxNORMAL,
1134
false, wxEmptyString,
1135
info.xregistry, info.xencoding,
1138
// this should never happen as we had tested for it in the
1139
// very beginning, but if it does, do return something non
1140
// NULL or we'd crash in wxFont code
1143
wxFAIL_MSG( wxT("this encoding should be available!") );
1145
font = wxLoadQueryFont(-1,
1146
wxDEFAULT, wxNORMAL, wxNORMAL,
1147
false, wxEmptyString,
1159
// ----------------------------------------------------------------------------
1160
// private functions
1161
// ----------------------------------------------------------------------------
1163
// returns true if there are any fonts matching this font spec
1164
static bool wxTestFontSpec(const wxString& fontspec)
1166
// some X servers will fail to load this font because there are too many
1167
// matches so we must test explicitly for this
1168
if ( fontspec == wxT("-*-*-*-*-*-*-*-*-*-*-*-*-*-*") )
1173
wxNativeFont test = (wxNativeFont) g_fontHash->Get( fontspec );
1179
test = wxLoadFont(fontspec);
1180
g_fontHash->Put( fontspec, (wxObject*) test );
1194
static wxNativeFont wxLoadQueryFont(int pointSize,
1198
bool WXUNUSED(underlined),
1199
const wxString& facename,
1200
const wxString& xregistry,
1201
const wxString& xencoding,
1202
wxString* xFontName)
1207
case wxDECORATIVE: xfamily = wxT("lucida"); break;
1208
case wxROMAN: xfamily = wxT("times"); break;
1209
case wxMODERN: xfamily = wxT("courier"); break;
1210
case wxSWISS: xfamily = wxT("helvetica"); break;
1211
case wxTELETYPE: xfamily = wxT("lucidatypewriter"); break;
1212
case wxSCRIPT: xfamily = wxT("utopia"); break;
1213
default: xfamily = wxT("*");
1221
xweight = MWLF_WEIGHT_BOLD;
1226
xweight = MWLF_WEIGHT_LIGHT;
1231
xweight = MWLF_WEIGHT_NORMAL;
1237
xweight = MWLF_WEIGHT_DEFAULT;
1241
GR_SCREEN_INFO screenInfo;
1242
GrGetScreenInfo(& screenInfo);
1244
int yPixelsPerCM = screenInfo.ydpcm;
1246
// A point is 1/72 of an inch.
1247
// An inch is 2.541 cm.
1248
// So pixelHeight = (pointSize / 72) (inches) * 2.541 (for cm) * yPixelsPerCM (for pixels)
1249
// In fact pointSize is 10 * the normal point size so
1252
int pixelHeight = (int) ( (((float)pointSize) / 720.0) * 2.541 * (float) yPixelsPerCM) ;
1254
// An alternative: assume that the screen is 72 dpi.
1255
//int pixelHeight = (int) (((float)pointSize / 720.0) * 72.0) ;
1256
//int pixelHeight = (int) ((float)pointSize / 10.0) ;
1259
logFont.lfHeight = pixelHeight;
1260
logFont.lfWidth = 0;
1261
logFont.lfEscapement = 0;
1262
logFont.lfOrientation = 0;
1263
logFont.lfWeight = xweight;
1264
logFont.lfItalic = (style == wxNORMAL ? 0 : 1) ;
1265
logFont.lfUnderline = 0;
1266
logFont.lfStrikeOut = 0;
1267
logFont.lfCharSet = MWLF_CHARSET_DEFAULT; // TODO: select appropriate one
1268
logFont.lfOutPrecision = MWLF_TYPE_DEFAULT;
1269
logFont.lfClipPrecision = 0; // Not used
1270
logFont.lfRoman = (family == wxROMAN ? 1 : 0) ;
1271
logFont.lfSerif = (family == wxSWISS ? 0 : 1) ;
1272
logFont.lfSansSerif = !logFont.lfSerif ;
1273
logFont.lfModern = (family == wxMODERN ? 1 : 0) ;
1274
logFont.lfProportional = (family == wxTELETYPE ? 0 : 1) ;
1275
logFont.lfOblique = 0;
1276
logFont.lfSmallCaps = 0;
1277
logFont.lfPitch = 0; // 0 = default
1278
strcpy(logFont.lfFaceName, facename.c_str());
1280
XFontStruct* fontInfo = (XFontStruct*) malloc(sizeof(XFontStruct));
1281
fontInfo->fid = GrCreateFont((GR_CHAR*) facename.c_str(), pixelHeight, & logFont);
1282
GrGetFontInfo(fontInfo->fid, & fontInfo->info);
1283
return (wxNativeFont) fontInfo;
1287
if (!facename.empty())
1289
fontSpec.Printf(wxT("-*-%s-*-*-normal-*-*-*-*-*-*-*-*-*"),
1292
if ( wxTestFontSpec(fontSpec) )
1296
//else: no such family, use default one instead
1303
fontSpec.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
1305
if ( wxTestFontSpec(fontSpec) )
1310
// fall through - try wxITALIC now
1313
fontSpec.Printf(wxT("-*-%s-*-i-*-*-*-*-*-*-*-*-*-*"),
1315
if ( wxTestFontSpec(fontSpec) )
1319
else if ( style == wxITALIC ) // and not wxSLANT
1322
fontSpec.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
1324
if ( wxTestFontSpec(fontSpec) )
1330
// no italic, no slant - leave default
1337
wxFAIL_MSG(wxT("unknown font style"));
1338
// fall back to normal
1350
fontSpec.Printf(wxT("-*-%s-bold-*-*-*-*-*-*-*-*-*-*-*"),
1352
if ( wxTestFontSpec(fontSpec) )
1354
xweight = wxT("bold");
1357
fontSpec.Printf(wxT("-*-%s-heavy-*-*-*-*-*-*-*-*-*-*-*"),
1359
if ( wxTestFontSpec(fontSpec) )
1361
xweight = wxT("heavy");
1364
fontSpec.Printf(wxT("-*-%s-extrabold-*-*-*-*-*-*-*-*-*-*-*"),
1366
if ( wxTestFontSpec(fontSpec) )
1368
xweight = wxT("extrabold");
1371
fontSpec.Printf(wxT("-*-%s-demibold-*-*-*-*-*-*-*-*-*-*-*"),
1373
if ( wxTestFontSpec(fontSpec) )
1375
xweight = wxT("demibold");
1378
fontSpec.Printf(wxT("-*-%s-black-*-*-*-*-*-*-*-*-*-*-*"),
1380
if ( wxTestFontSpec(fontSpec) )
1382
xweight = wxT("black");
1385
fontSpec.Printf(wxT("-*-%s-ultrablack-*-*-*-*-*-*-*-*-*-*-*"),
1387
if ( wxTestFontSpec(fontSpec) )
1389
xweight = wxT("ultrablack");
1396
fontSpec.Printf(wxT("-*-%s-light-*-*-*-*-*-*-*-*-*-*-*"),
1398
if ( wxTestFontSpec(fontSpec) )
1400
xweight = wxT("light");
1403
fontSpec.Printf(wxT("-*-%s-thin-*-*-*-*-*-*-*-*-*-*-*"),
1405
if ( wxTestFontSpec(fontSpec) )
1407
xweight = wxT("thin");
1414
fontSpec.Printf(wxT("-*-%s-medium-*-*-*-*-*-*-*-*-*-*-*"),
1416
if ( wxTestFontSpec(fontSpec) )
1418
xweight = wxT("medium");
1421
fontSpec.Printf(wxT("-*-%s-normal-*-*-*-*-*-*-*-*-*-*-*"),
1423
if ( wxTestFontSpec(fontSpec) )
1425
xweight = wxT("normal");
1428
fontSpec.Printf(wxT("-*-%s-regular-*-*-*-*-*-*-*-*-*-*-*"),
1430
if ( wxTestFontSpec(fontSpec) )
1432
xweight = wxT("regular");
1438
default: xweight = wxT("*"); break;
1441
// if pointSize is -1, don't specify any
1443
if ( pointSize == -1 )
1445
sizeSpec = wxT('*');
1449
sizeSpec.Printf(wxT("%d"), pointSize);
1452
// construct the X font spec from our data
1453
fontSpec.Printf(wxT("-*-%s-%s-%s-normal-*-*-%s-*-*-*-*-%s-%s"),
1454
xfamily.c_str(), xweight.c_str(), xstyle.c_str(),
1455
sizeSpec.c_str(), xregistry.c_str(), xencoding.c_str());
1458
*xFontName = fontSpec;
1460
return wxLoadFont(fontSpec);
1465
// ----------------------------------------------------------------------------
1467
// ----------------------------------------------------------------------------
1469
class wxFontModule : public wxModule
1476
DECLARE_DYNAMIC_CLASS(wxFontModule)
1479
IMPLEMENT_DYNAMIC_CLASS(wxFontModule, wxModule)
1481
bool wxFontModule::OnInit()
1483
g_fontHash = new wxHashTable( wxKEY_STRING );
1488
void wxFontModule::OnExit()
1490
wxDELETE(g_fontHash);
1493
#endif // GTK 2.0/1.x