1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/unix/fontutil.cpp 
   3 // Purpose:     Font helper functions for X11 (GDK/X) 
   4 // Author:      Vadim Zeitlin 
   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) (wxConvUTF8.cWX2MB((s))) 
  57     #define wxPANGO_CONV_BACK(s) (wxConvUTF8.cMB2WX((s))) 
  60 // ---------------------------------------------------------------------------- 
  62 // ---------------------------------------------------------------------------- 
  64 void wxNativeFontInfo::Init() 
  70 wxNativeFontInfo::Init(const wxNativeFontInfo
& info
) 
  73         description 
= pango_font_description_copy(info
.description
); 
  78 void wxNativeFontInfo::Free() 
  81         pango_font_description_free(description
); 
  84 int wxNativeFontInfo::GetPointSize() const 
  86     return pango_font_description_get_size( description 
) / PANGO_SCALE
; 
  89 wxFontStyle 
wxNativeFontInfo::GetStyle() const 
  91     wxFontStyle m_style 
= wxFONTSTYLE_NORMAL
; 
  93     switch (pango_font_description_get_style( description 
)) 
  95         case PANGO_STYLE_NORMAL
: 
  96             m_style 
= wxFONTSTYLE_NORMAL
; 
  98         case PANGO_STYLE_ITALIC
: 
  99             m_style 
= wxFONTSTYLE_ITALIC
; 
 101         case PANGO_STYLE_OBLIQUE
: 
 102             m_style 
= wxFONTSTYLE_SLANT
; 
 109 wxFontWeight 
wxNativeFontInfo::GetWeight() const 
 112     // We seem to currently initialize only by string. 
 113     // In that case PANGO_FONT_MASK_WEIGHT is always set. 
 114     if (!(pango_font_description_get_set_fields(description
) & PANGO_FONT_MASK_WEIGHT
)) 
 115         return wxFONTWEIGHT_NORMAL
; 
 118     PangoWeight pango_weight 
= pango_font_description_get_weight( description 
); 
 120     // Until the API can be changed the following ranges of weight values are used: 
 121     // wxFONTWEIGHT_LIGHT:  100 .. 349 - range of 250 
 122     // wxFONTWEIGHT_NORMAL: 350 .. 599 - range of 250 
 123     // wxFONTWEIGHT_BOLD:   600 .. 900 - range of 301 (600 is "semibold" already) 
 125     if (pango_weight 
>= 600) 
 126         return wxFONTWEIGHT_BOLD
; 
 128     if (pango_weight 
< 350) 
 129         return wxFONTWEIGHT_LIGHT
; 
 131     return wxFONTWEIGHT_NORMAL
; 
 134 bool wxNativeFontInfo::GetUnderlined() const 
 139 wxString 
wxNativeFontInfo::GetFaceName() const 
 141     return wxPANGO_CONV_BACK(pango_font_description_get_family(description
)); 
 144 wxFontFamily 
wxNativeFontInfo::GetFamily() const 
 146     wxFontFamily ret 
= wxFONTFAMILY_DEFAULT
; 
 147     // note: not passing -1 as the 2nd parameter to g_ascii_strdown to work 
 148     // around a bug in the 64-bit glib shipped with solaris 10, -1 causes it 
 149     // to try to allocate 2^32 bytes. 
 150     const char *family_name 
= pango_font_description_get_family( description 
); 
 154     wxGtkString 
family_text(g_ascii_strdown(family_name
, strlen(family_name
))); 
 156     // Check for some common fonts, to salvage what we can from the current win32 centric wxFont API: 
 157     if (strncmp( family_text
, "monospace", 9 ) == 0) 
 158         ret 
= wxFONTFAMILY_TELETYPE
; // begins with "Monospace" 
 159     else if (strncmp( family_text
, "courier", 7 ) == 0) 
 160         ret 
= wxFONTFAMILY_TELETYPE
; // begins with "Courier" 
 161 #if defined(__WXGTK20__) || defined(HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE) 
 164     if (!gtk_check_version(2,4,0)) 
 167         PangoFontFamily 
**families
; 
 168         PangoFontFamily  
*family 
= NULL
; 
 170         pango_context_list_families( 
 172                 gtk_widget_get_pango_context( wxGetRootWindow() ), 
 174                 wxTheApp
->GetPangoContext(), 
 176                 &families
, &n_families
); 
 178         for (int i 
= 0;i 
< n_families
;++i
) 
 180             if (g_ascii_strcasecmp(pango_font_family_get_name( families
[i
] ), pango_font_description_get_family( description 
)) == 0 ) 
 182                 family 
= families
[i
]; 
 189         // Some gtk+ systems might query for a non-existing font from wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) 
 190         // on initialization, don't assert until wxSystemSettings::GetFont is checked for this - MR 
 191         // wxASSERT_MSG( family, wxT("wxNativeFontInfo::GetFamily() - No appropriate PangoFontFamily found for ::description") ); 
 193         //BCI: Cache the wxFontFamily inside the class. Validate cache with 
 194         //BCI: g_ascii_strcasecmp(pango_font_description_get_family(description), pango_font_family_get_name(family)) == 0 
 196         if (family 
!= NULL 
&& pango_font_family_is_monospace( family 
)) 
 197             ret 
= wxFONTFAMILY_TELETYPE
; // is deemed a monospace font by pango 
 199 #endif // GTK+ 2 || HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE 
 201     if (ret 
== wxFONTFAMILY_DEFAULT
) 
 203         if (strstr( family_text
, "sans" ) != NULL
) // checked before serif, so that "* Sans Serif" fonts are detected correctly 
 204             ret 
= wxFONTFAMILY_SWISS
; // contains "Sans" 
 205         else if (strstr( family_text
, "serif" ) != NULL
) 
 206             ret 
= wxFONTFAMILY_ROMAN
; // contains "Serif" 
 207         else if (strncmp( family_text
, "times", 5 ) == 0) 
 208             ret 
= wxFONTFAMILY_ROMAN
; // begins with "Times" 
 209         else if (strncmp( family_text
, "old", 3 ) == 0) 
 210             ret 
= wxFONTFAMILY_DECORATIVE
; // Begins with "Old" - "Old English", "Old Town" 
 216 wxFontEncoding 
wxNativeFontInfo::GetEncoding() const 
 218     return wxFONTENCODING_SYSTEM
; 
 222 void wxNativeFontInfo::SetPointSize(int pointsize
) 
 224     pango_font_description_set_size( description
, pointsize 
* PANGO_SCALE 
); 
 227 void wxNativeFontInfo::SetStyle(wxFontStyle style
) 
 231         case wxFONTSTYLE_ITALIC
: 
 232             pango_font_description_set_style( description
, PANGO_STYLE_ITALIC 
); 
 234         case wxFONTSTYLE_SLANT
: 
 235             pango_font_description_set_style( description
, PANGO_STYLE_OBLIQUE 
); 
 238             wxFAIL_MSG( _T("unknown font style") ); 
 240         case wxFONTSTYLE_NORMAL
: 
 241             pango_font_description_set_style( description
, PANGO_STYLE_NORMAL 
); 
 246 void wxNativeFontInfo::SetWeight(wxFontWeight weight
) 
 250         case wxFONTWEIGHT_BOLD
: 
 251             pango_font_description_set_weight(description
, PANGO_WEIGHT_BOLD
); 
 253         case wxFONTWEIGHT_LIGHT
: 
 254             pango_font_description_set_weight(description
, PANGO_WEIGHT_LIGHT
); 
 257             wxFAIL_MSG( _T("unknown font weight") ); 
 259         case wxFONTWEIGHT_NORMAL
: 
 260             pango_font_description_set_weight(description
, PANGO_WEIGHT_NORMAL
); 
 264 void wxNativeFontInfo::SetUnderlined(bool WXUNUSED(underlined
)) 
 266     wxFAIL_MSG( _T("not implemented") ); 
 269 bool wxNativeFontInfo::SetFaceName(const wxString
& facename
) 
 271     pango_font_description_set_family(description
, wxPANGO_CONV(facename
)); 
 275 void wxNativeFontInfo::SetFamily(wxFontFamily 
WXUNUSED(family
)) 
 277     wxFAIL_MSG( _T("not implemented") ); 
 280 void wxNativeFontInfo::SetEncoding(wxFontEncoding 
WXUNUSED(encoding
)) 
 282     wxFAIL_MSG( _T("not implemented") ); 
 287 bool wxNativeFontInfo::FromString(const wxString
& s
) 
 290         pango_font_description_free( description 
); 
 292     // there is a bug in at least pango <= 1.13 which makes it (or its backends) 
 293     // segfault for very big point sizes and for negative point sizes. 
 294     // To workaround that bug for pango <= 1.13 
 295     // (see http://bugzilla.gnome.org/show_bug.cgi?id=340229) 
 296     // we do the check on the size here using same (arbitrary) limits used by 
 297     // pango > 1.13. Note that the segfault could happen also for pointsize 
 298     // smaller than this limit !! 
 300     const size_t pos 
= str
.find_last_of(_T(" ")); 
 302     if ( pos 
!= wxString::npos 
&& wxString(str
, pos 
+ 1).ToDouble(&size
) ) 
 307         else if ( size 
>= 1E6 
) 
 310         if ( !sizeStr
.empty() ) 
 312             // replace the old size with the adjusted one 
 313             str 
= wxString(s
, 0, pos
) + sizeStr
; 
 317     description 
= pango_font_description_from_string(wxPANGO_CONV(str
)); 
 320     // ensure a valid facename is selected 
 321     if (!wxFontEnumerator::IsValidFacename(GetFaceName())) 
 322         SetFaceName(wxNORMAL_FONT
->GetFaceName()); 
 323 #endif // wxUSE_FONTENUM 
 328 wxString 
wxNativeFontInfo::ToString() const 
 330     wxGtkString 
str(pango_font_description_to_string( description 
)); 
 332     return wxPANGO_CONV_BACK(str
); 
 335 bool wxNativeFontInfo::FromUserString(const wxString
& s
) 
 337     return FromString( s 
); 
 340 wxString 
wxNativeFontInfo::ToUserString() const 
 349         #pragma message disable nosimpint 
 352     #include <X11/Xlib.h> 
 355         #pragma message enable nosimpint 
 358 #elif defined(__WXGTK__) 
 359     // we have to declare struct tm to avoid problems with first forward 
 360     // declaring it in C code (glib.h included from gdk.h does it) and then 
 361     // defining it when time.h is included from the headers below - this is 
 362     // known not to work at least with Sun CC 6.01 
 369 // ---------------------------------------------------------------------------- 
 371 // ---------------------------------------------------------------------------- 
 373 static wxHashTable 
*g_fontHash 
= (wxHashTable
*) NULL
; 
 375 // ---------------------------------------------------------------------------- 
 377 // ---------------------------------------------------------------------------- 
 379 // define the functions to create and destroy native fonts for this toolkit 
 381     wxNativeFont 
wxLoadFont(const wxString
& fontSpec
) 
 383         return XLoadQueryFont((Display 
*)wxGetDisplay(), fontSpec
); 
 386     inline void wxFreeFont(wxNativeFont font
) 
 388         XFreeFont((Display 
*)wxGetDisplay(), (XFontStruct 
*)font
); 
 390 #elif defined(__WXGTK__) 
 391     wxNativeFont 
wxLoadFont(const wxString
& fontSpec
) 
 393         // VZ: we should use gdk_fontset_load() instead of gdk_font_load() 
 394         //     here to be able to display Japanese fonts correctly (at least 
 395         //     this is what people report) but unfortunately doing it results 
 396         //     in tons of warnings when using GTK with "normal" European 
 397         //     languages and so we can't always do it and I don't know enough 
 398         //     to determine when should this be done... (FIXME) 
 399         return gdk_font_load( wxConvertWX2MB(fontSpec
) ); 
 402     inline void wxFreeFont(wxNativeFont font
) 
 404         gdk_font_unref(font
); 
 407     #error "Unknown GUI toolkit" 
 410 static bool wxTestFontSpec(const wxString
& fontspec
); 
 412 static wxNativeFont 
wxLoadQueryFont(int pointSize
, 
 417                                     const wxString
& facename
, 
 418                                     const wxString
& xregistry
, 
 419                                     const wxString
& xencoding
, 
 420                                     wxString
* xFontName
); 
 422 // ============================================================================ 
 424 // ============================================================================ 
 426 // ---------------------------------------------------------------------------- 
 427 // wxNativeEncodingInfo 
 428 // ---------------------------------------------------------------------------- 
 430 // convert to/from the string representation: format is 
 431 //      encodingid;registry;encoding[;facename] 
 432 bool wxNativeEncodingInfo::FromString(const wxString
& s
) 
 434     // use ";", not "-" because it may be part of encoding name 
 435     wxStringTokenizer 
tokenizer(s
, _T(";")); 
 437     wxString encid 
= tokenizer
.GetNextToken(); 
 439     if ( !encid
.ToLong(&enc
) ) 
 441     encoding 
= (wxFontEncoding
)enc
; 
 443     xregistry 
= tokenizer
.GetNextToken(); 
 447     xencoding 
= tokenizer
.GetNextToken(); 
 452     facename 
= tokenizer
.GetNextToken(); 
 457 wxString 
wxNativeEncodingInfo::ToString() const 
 460     s 
<< (long)encoding 
<< _T(';') << xregistry 
<< _T(';') << xencoding
; 
 461     if ( !facename
.empty() ) 
 463         s 
<< _T(';') << facename
; 
 469 // ---------------------------------------------------------------------------- 
 471 // ---------------------------------------------------------------------------- 
 473 void wxNativeFontInfo::Init() 
 478 bool wxNativeFontInfo::FromString(const wxString
& s
) 
 480     wxStringTokenizer 
tokenizer(s
, _T(";")); 
 483     wxString token 
= tokenizer
.GetNextToken(); 
 484     if ( token 
!= _T('0') ) 
 487     xFontName 
= tokenizer
.GetNextToken(); 
 489     // this should be the end 
 490     if ( tokenizer
.HasMoreTokens() ) 
 493     return FromXFontName(xFontName
); 
 496 wxString 
wxNativeFontInfo::ToString() const 
 499     return wxString::Format(_T("%d;%s"), 0, GetXFontName().c_str()); 
 502 bool wxNativeFontInfo::FromUserString(const wxString
& s
) 
 504     return FromXFontName(s
); 
 507 wxString 
wxNativeFontInfo::ToUserString() const 
 509     return GetXFontName(); 
 512 bool wxNativeFontInfo::HasElements() const 
 514     // we suppose that the foundry is never empty, so if it is it means that we 
 515     // had never parsed the XLFD 
 516     return !fontElements
[0].empty(); 
 519 wxString 
wxNativeFontInfo::GetXFontComponent(wxXLFDField field
) const 
 521     wxCHECK_MSG( field 
< wxXLFD_MAX
, wxEmptyString
, _T("invalid XLFD field") ); 
 523     if ( !HasElements() ) 
 526         if ( !((wxNativeFontInfo 
*)this)->FromXFontName(xFontName
) ) 
 527             return wxEmptyString
; 
 530     return fontElements
[field
]; 
 533 bool wxNativeFontInfo::FromXFontName(const wxString
& fontname
) 
 535     // TODO: we should be able to handle the font aliases here, but how? 
 536     wxStringTokenizer 
tokenizer(fontname
, _T("-")); 
 538     // skip the leading, usually empty field (font name registry) 
 539     if ( !tokenizer
.HasMoreTokens() ) 
 542     (void)tokenizer
.GetNextToken(); 
 544     for ( size_t n 
= 0; n 
< WXSIZEOF(fontElements
); n
++ ) 
 546         if ( !tokenizer
.HasMoreTokens() ) 
 548             // not enough elements in the XLFD - or maybe an alias 
 552         wxString field 
= tokenizer
.GetNextToken(); 
 553         if ( !field
.empty() && field 
!= _T('*') ) 
 555             // we're really initialized now 
 559         fontElements
[n
] = field
; 
 562     // this should be all 
 563     if ( tokenizer
.HasMoreTokens() ) 
 569 wxString 
wxNativeFontInfo::GetXFontName() const 
 571     if ( xFontName
.empty() ) 
 573         for ( size_t n 
= 0; n 
< WXSIZEOF(fontElements
); n
++ ) 
 575             // replace the non specified elements with '*' except for the 
 576             // additional style which is usually just omitted 
 577             wxString elt 
= fontElements
[n
]; 
 578             if ( elt
.empty() && n 
!= wxXLFD_ADDSTYLE 
) 
 584             ((wxNativeFontInfo 
*)this)->xFontName 
<< _T('-') << elt
; 
 592 wxNativeFontInfo::SetXFontComponent(wxXLFDField field
, const wxString
& value
) 
 594     wxCHECK_RET( field 
< wxXLFD_MAX
, _T("invalid XLFD field") ); 
 596     // this class should be initialized with a valid font spec first and only 
 597     // then the fields may be modified! 
 598     wxASSERT_MSG( !IsDefault(), _T("can't modify an uninitialized XLFD") ); 
 600     if ( !HasElements() ) 
 603         if ( !((wxNativeFontInfo 
*)this)->FromXFontName(xFontName
) ) 
 605             wxFAIL_MSG( _T("can't set font element for invalid XLFD") ); 
 611     fontElements
[field
] = value
; 
 613     // invalidate the XFLD, it doesn't correspond to the font elements any more 
 617 void wxNativeFontInfo::SetXFontName(const wxString
& xFontName_
) 
 619     // invalidate the font elements, GetXFontComponent() will reparse the XLFD 
 620     fontElements
[0].clear(); 
 622     xFontName 
= xFontName_
; 
 627 int wxNativeFontInfo::GetPointSize() const 
 629     const wxString s 
= GetXFontComponent(wxXLFD_POINTSIZE
); 
 631     // return -1 to indicate that the size is unknown 
 633     return s
.ToLong(&l
) ? l 
: -1; 
 636 wxFontStyle 
wxNativeFontInfo::GetStyle() const 
 638     const wxString s 
= GetXFontComponent(wxXLFD_SLANT
); 
 640     if ( s
.length() != 1 ) 
 642         // it is really unknown but we don't have any way to return it from 
 644         return wxFONTSTYLE_NORMAL
; 
 647     switch ( s
[0].GetValue() ) 
 650             // again, unknown but consider normal by default 
 653             return wxFONTSTYLE_NORMAL
; 
 656             return wxFONTSTYLE_ITALIC
; 
 659             return wxFONTSTYLE_SLANT
; 
 663 wxFontWeight 
wxNativeFontInfo::GetWeight() const 
 665     const wxString s 
= GetXFontComponent(wxXLFD_WEIGHT
).MakeLower(); 
 666     if ( s
.find(_T("bold")) != wxString::npos 
|| s 
== _T("black") ) 
 667         return wxFONTWEIGHT_BOLD
; 
 668     else if ( s 
== _T("light") ) 
 669         return wxFONTWEIGHT_LIGHT
; 
 671     return wxFONTWEIGHT_NORMAL
; 
 674 bool wxNativeFontInfo::GetUnderlined() const 
 676     // X fonts are never underlined 
 680 wxString 
wxNativeFontInfo::GetFaceName() const 
 682     // wxWidgets facename probably more accurately corresponds to X family 
 683     return GetXFontComponent(wxXLFD_FAMILY
); 
 686 wxFontFamily 
wxNativeFontInfo::GetFamily() const 
 688     // and wxWidgets family -- to X foundry, but we have to translate it to 
 689     // wxFontFamily somehow... 
 690     wxFAIL_MSG(_T("not implemented")); // GetXFontComponent(wxXLFD_FOUNDRY); 
 692     return wxFONTFAMILY_DEFAULT
; 
 695 wxFontEncoding 
wxNativeFontInfo::GetEncoding() const 
 697     // we already have the code for this but need to refactor it first 
 698     wxFAIL_MSG( _T("not implemented") ); 
 700     return wxFONTENCODING_MAX
; 
 703 void wxNativeFontInfo::SetPointSize(int pointsize
) 
 705     SetXFontComponent(wxXLFD_POINTSIZE
, wxString::Format(_T("%d"), pointsize
)); 
 708 void wxNativeFontInfo::SetStyle(wxFontStyle style
) 
 713         case wxFONTSTYLE_ITALIC
: 
 717         case wxFONTSTYLE_SLANT
: 
 721         case wxFONTSTYLE_NORMAL
: 
 725             wxFAIL_MSG( _T("unknown wxFontStyle in wxNativeFontInfo::SetStyle") ); 
 729     SetXFontComponent(wxXLFD_SLANT
, s
); 
 732 void wxNativeFontInfo::SetWeight(wxFontWeight weight
) 
 737         case wxFONTWEIGHT_BOLD
: 
 741         case wxFONTWEIGHT_LIGHT
: 
 745         case wxFONTWEIGHT_NORMAL
: 
 750             wxFAIL_MSG( _T("unknown wxFontWeight in wxNativeFontInfo::SetWeight") ); 
 754     SetXFontComponent(wxXLFD_WEIGHT
, s
); 
 757 void wxNativeFontInfo::SetUnderlined(bool WXUNUSED(underlined
)) 
 759     // can't do this under X 
 762 bool wxNativeFontInfo::SetFaceName(const wxString
& facename
) 
 764     SetXFontComponent(wxXLFD_FAMILY
, facename
); 
 768 void wxNativeFontInfo::SetFamily(wxFontFamily 
WXUNUSED(family
)) 
 770     // wxFontFamily -> X foundry, anyone? 
 771     wxFAIL_MSG( _T("not implemented") ); 
 773     // SetXFontComponent(wxXLFD_FOUNDRY, ...); 
 776 void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding
) 
 778     wxNativeEncodingInfo info
; 
 779     if ( wxGetNativeFontEncoding(encoding
, &info
) ) 
 781         SetXFontComponent(wxXLFD_ENCODING
, info
.xencoding
); 
 782         SetXFontComponent(wxXLFD_REGISTRY
, info
.xregistry
); 
 786 // ---------------------------------------------------------------------------- 
 788 // ---------------------------------------------------------------------------- 
 790 bool wxGetNativeFontEncoding(wxFontEncoding encoding
, 
 791                              wxNativeEncodingInfo 
*info
) 
 793     wxCHECK_MSG( info
, false, _T("bad pointer in wxGetNativeFontEncoding") ); 
 795     if ( encoding 
== wxFONTENCODING_DEFAULT 
) 
 797         encoding 
= wxFont::GetDefaultEncoding(); 
 802         case wxFONTENCODING_ISO8859_1
: 
 803         case wxFONTENCODING_ISO8859_2
: 
 804         case wxFONTENCODING_ISO8859_3
: 
 805         case wxFONTENCODING_ISO8859_4
: 
 806         case wxFONTENCODING_ISO8859_5
: 
 807         case wxFONTENCODING_ISO8859_6
: 
 808         case wxFONTENCODING_ISO8859_7
: 
 809         case wxFONTENCODING_ISO8859_8
: 
 810         case wxFONTENCODING_ISO8859_9
: 
 811         case wxFONTENCODING_ISO8859_10
: 
 812         case wxFONTENCODING_ISO8859_11
: 
 813         case wxFONTENCODING_ISO8859_12
: 
 814         case wxFONTENCODING_ISO8859_13
: 
 815         case wxFONTENCODING_ISO8859_14
: 
 816         case wxFONTENCODING_ISO8859_15
: 
 818                 int cp 
= encoding 
- wxFONTENCODING_ISO8859_1 
+ 1; 
 819                 info
->xregistry 
= wxT("iso8859"); 
 820                 info
->xencoding
.Printf(wxT("%d"), cp
); 
 824         case wxFONTENCODING_UTF8
: 
 825             info
->xregistry 
= wxT("iso10646"); 
 826             info
->xencoding 
= wxT("*"); 
 829         case wxFONTENCODING_GB2312
: 
 830             info
->xregistry 
= wxT("GB2312");   // or the otherway round? 
 831             info
->xencoding 
= wxT("*"); 
 834         case wxFONTENCODING_KOI8
: 
 835         case wxFONTENCODING_KOI8_U
: 
 836             info
->xregistry 
= wxT("koi8"); 
 838             // we don't make distinction between koi8-r, koi8-u and koi8-ru (so far) 
 839             info
->xencoding 
= wxT("*"); 
 842         case wxFONTENCODING_CP1250
: 
 843         case wxFONTENCODING_CP1251
: 
 844         case wxFONTENCODING_CP1252
: 
 845         case wxFONTENCODING_CP1253
: 
 846         case wxFONTENCODING_CP1254
: 
 847         case wxFONTENCODING_CP1255
: 
 848         case wxFONTENCODING_CP1256
: 
 849         case wxFONTENCODING_CP1257
: 
 851                 int cp 
= encoding 
- wxFONTENCODING_CP1250 
+ 1250; 
 852                 info
->xregistry 
= wxT("microsoft"); 
 853                 info
->xencoding
.Printf(wxT("cp%d"), cp
); 
 857         case wxFONTENCODING_EUC_JP
: 
 858         case wxFONTENCODING_SHIFT_JIS
: 
 859             info
->xregistry 
= "jis*"; 
 860             info
->xencoding 
= "*"; 
 863         case wxFONTENCODING_SYSTEM
: 
 865             info
->xencoding 
= wxT("*"); 
 869             // don't know how to translate this encoding into X fontspec 
 873     info
->encoding 
= encoding
; 
 878 bool wxTestFontEncoding(const wxNativeEncodingInfo
& info
) 
 881     fontspec
.Printf(_T("-*-%s-*-*-*-*-*-*-*-*-*-*-%s-%s"), 
 882                     !info
.facename 
? _T("*") : info
.facename
.c_str(), 
 883                     info
.xregistry
.c_str(), 
 884                     info
.xencoding
.c_str()); 
 886     return wxTestFontSpec(fontspec
); 
 889 // ---------------------------------------------------------------------------- 
 890 // X-specific functions 
 891 // ---------------------------------------------------------------------------- 
 893 wxNativeFont 
wxLoadQueryNearestFont(int pointSize
, 
 898                                     const wxString 
&facename
, 
 899                                     wxFontEncoding encoding
, 
 902     if ( encoding 
== wxFONTENCODING_DEFAULT 
) 
 904         encoding 
= wxFont::GetDefaultEncoding(); 
 907     // first determine the encoding - if the font doesn't exist at all in this 
 908     // encoding, it's useless to do all other approximations (i.e. size, 
 909     // family &c don't matter much) 
 910     wxNativeEncodingInfo info
; 
 911     if ( encoding 
== wxFONTENCODING_SYSTEM 
) 
 913         // This will always work so we don't test to save time 
 914         wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM
, &info
); 
 918         if ( !wxGetNativeFontEncoding(encoding
, &info
) || 
 919              !wxTestFontEncoding(info
) ) 
 922             if ( !wxFontMapper::Get()->GetAltForEncoding(encoding
, &info
) ) 
 923 #endif // wxUSE_FONTMAP 
 925                 // unspported encoding - replace it with the default 
 927                 // NB: we can't just return 0 from here because wxGTK code doesn't 
 928                 //     check for it (i.e. it supposes that we'll always succeed), 
 929                 //     so it would provoke a crash 
 930                 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM
, &info
); 
 935     // OK, we have the correct xregistry/xencoding in info structure 
 936     wxNativeFont font 
= 0; 
 938     // if we already have the X font name, try to use it 
 939     if( xFontName 
&& !xFontName
->empty() ) 
 942         //  Make sure point size is correct for scale factor. 
 944         wxStringTokenizer 
tokenizer(*xFontName
, _T("-"), wxTOKEN_RET_DELIMS
); 
 945         wxString newFontName
; 
 947         for(int i 
= 0; i 
< 8; i
++) 
 948           newFontName 
+= tokenizer
.NextToken(); 
 950         (void) tokenizer
.NextToken(); 
 952         newFontName 
+= wxString::Format(wxT("%d-"), pointSize
); 
 954         while(tokenizer
.HasMoreTokens()) 
 955           newFontName 
+= tokenizer
.GetNextToken(); 
 957         font 
= wxLoadFont(newFontName
); 
 960           *xFontName 
= newFontName
; 
 965         // search up and down by stepsize 10 
 966         int max_size 
= pointSize 
+ 20 * (1 + (pointSize
/180)); 
 967         int min_size 
= pointSize 
- 20 * (1 + (pointSize
/180)); 
 969         int i
, round
; // counters 
 971         // first round: search for equal, then for smaller and for larger size with the given weight and style 
 972         int testweight 
= weight
; 
 973         int teststyle 
= style
; 
 975         for ( round 
= 0; round 
< 3; round
++ ) 
 977             // second round: use normal weight 
 980                 if ( testweight 
!= wxNORMAL 
) 
 982                     testweight 
= wxNORMAL
; 
 986                     ++round
; // fall through to third round 
 990             // third round: ... and use normal style 
 993                 if ( teststyle 
!= wxNORMAL 
) 
 995                     teststyle 
= wxNORMAL
; 
1002             // Search for equal or smaller size (approx.) 
1003             for ( i 
= pointSize
; !font 
&& i 
>= 10 && i 
>= min_size
; i 
-= 10 ) 
1005                 font 
= wxLoadQueryFont(i
, family
, teststyle
, testweight
, underlined
, 
1006                                    facename
, info
.xregistry
, info
.xencoding
, 
1010             // Search for larger size (approx.) 
1011             for ( i 
= pointSize 
+ 10; !font 
&& i 
<= max_size
; i 
+= 10 ) 
1013                 font 
= wxLoadQueryFont(i
, family
, teststyle
, testweight
, underlined
, 
1014                                    facename
, info
.xregistry
, info
.xencoding
, 
1019         // Try default family 
1020         if ( !font 
&& family 
!= wxDEFAULT 
) 
1022             font 
= wxLoadQueryFont(pointSize
, wxDEFAULT
, style
, weight
, 
1023                                    underlined
, facename
, 
1024                                    info
.xregistry
, info
.xencoding
, 
1028         // ignore size, family, style and weight but try to find font with the 
1029         // given facename and encoding 
1032             font 
= wxLoadQueryFont(120, wxDEFAULT
, wxNORMAL
, wxNORMAL
, 
1033                                    underlined
, facename
, 
1034                                    info
.xregistry
, info
.xencoding
, 
1037             // ignore family as well 
1040                 font 
= wxLoadQueryFont(120, wxDEFAULT
, wxNORMAL
, wxNORMAL
, 
1041                                        underlined
, wxEmptyString
, 
1042                                        info
.xregistry
, info
.xencoding
, 
1045                 // if it still failed, try to get the font of any size but 
1046                 // with the requested encoding: this can happen if the 
1047                 // encoding is only available in one size which happens to be 
1048                 // different from 120 
1051                     font 
= wxLoadQueryFont(-1, wxDEFAULT
, wxNORMAL
, wxNORMAL
, 
1052                                            false, wxEmptyString
, 
1053                                            info
.xregistry
, info
.xencoding
, 
1056                     // this should never happen as we had tested for it in the 
1057                     // very beginning, but if it does, do return something non 
1058                     // NULL or we'd crash in wxFont code 
1061                         wxFAIL_MSG( _T("this encoding should be available!") ); 
1063                         font 
= wxLoadQueryFont(-1, 
1064                                                wxDEFAULT
, wxNORMAL
, wxNORMAL
, 
1065                                                false, wxEmptyString
, 
1077 // ---------------------------------------------------------------------------- 
1078 // private functions 
1079 // ---------------------------------------------------------------------------- 
1081 // returns true if there are any fonts matching this font spec 
1082 static bool wxTestFontSpec(const wxString
& fontspec
) 
1084     // some X servers will fail to load this font because there are too many 
1085     // matches so we must test explicitly for this 
1086     if ( fontspec 
== _T("-*-*-*-*-*-*-*-*-*-*-*-*-*-*") ) 
1091     wxNativeFont test 
= (wxNativeFont
) g_fontHash
->Get( fontspec 
); 
1097     test 
= wxLoadFont(fontspec
); 
1098     g_fontHash
->Put( fontspec
, (wxObject
*) test 
); 
1112 static wxNativeFont 
wxLoadQueryFont(int pointSize
, 
1116                                     bool WXUNUSED(underlined
), 
1117                                     const wxString
& facename
, 
1118                                     const wxString
& xregistry
, 
1119                                     const wxString
& xencoding
, 
1120                                     wxString
* xFontName
) 
1125         case wxDECORATIVE
: xfamily 
= wxT("lucida"); break; 
1126         case wxROMAN
:      xfamily 
= wxT("times");  break; 
1127         case wxMODERN
:     xfamily 
= wxT("courier"); break; 
1128         case wxSWISS
:      xfamily 
= wxT("helvetica"); break; 
1129         case wxTELETYPE
:   xfamily 
= wxT("lucidatypewriter"); break; 
1130         case wxSCRIPT
:     xfamily 
= wxT("utopia"); break; 
1131         default:           xfamily 
= wxT("*"); 
1139                  xweight 
= MWLF_WEIGHT_BOLD
; 
1144                  xweight 
= MWLF_WEIGHT_LIGHT
; 
1149                  xweight 
= MWLF_WEIGHT_NORMAL
; 
1155                  xweight 
= MWLF_WEIGHT_DEFAULT
; 
1159     GR_SCREEN_INFO screenInfo
; 
1160     GrGetScreenInfo(& screenInfo
); 
1162     int yPixelsPerCM 
= screenInfo
.ydpcm
; 
1164     // A point is 1/72 of an inch. 
1165     // An inch is 2.541 cm. 
1166     // So pixelHeight = (pointSize / 72) (inches) * 2.541 (for cm) * yPixelsPerCM (for pixels) 
1167     // In fact pointSize is 10 * the normal point size so 
1170     int pixelHeight 
= (int) ( (((float)pointSize
) / 720.0) * 2.541 * (float) yPixelsPerCM
) ; 
1172     // An alternative: assume that the screen is 72 dpi. 
1173     //int pixelHeight = (int) (((float)pointSize / 720.0) * 72.0) ; 
1174     //int pixelHeight = (int) ((float)pointSize / 10.0) ; 
1177     logFont
.lfHeight 
= pixelHeight
; 
1178     logFont
.lfWidth 
= 0; 
1179     logFont
.lfEscapement 
= 0; 
1180     logFont
.lfOrientation 
= 0; 
1181     logFont
.lfWeight 
= xweight
; 
1182     logFont
.lfItalic 
= (style 
== wxNORMAL 
? 0 : 1) ; 
1183     logFont
.lfUnderline 
= 0; 
1184     logFont
.lfStrikeOut 
= 0; 
1185     logFont
.lfCharSet 
= MWLF_CHARSET_DEFAULT
; // TODO: select appropriate one 
1186     logFont
.lfOutPrecision 
= MWLF_TYPE_DEFAULT
; 
1187     logFont
.lfClipPrecision 
= 0; // Not used 
1188     logFont
.lfRoman 
= (family 
== wxROMAN 
? 1 : 0) ; 
1189     logFont
.lfSerif 
= (family 
== wxSWISS 
? 0 : 1) ; 
1190     logFont
.lfSansSerif 
= !logFont
.lfSerif 
; 
1191     logFont
.lfModern 
= (family 
== wxMODERN 
? 1 : 0) ; 
1192     logFont
.lfProportional 
= (family 
== wxTELETYPE 
? 0 : 1) ; 
1193     logFont
.lfOblique 
= 0; 
1194     logFont
.lfSmallCaps 
= 0; 
1195     logFont
.lfPitch 
= 0; // 0 = default 
1196     strcpy(logFont
.lfFaceName
, facename
.c_str()); 
1198     XFontStruct
* fontInfo 
= (XFontStruct
*) malloc(sizeof(XFontStruct
)); 
1199     fontInfo
->fid 
= GrCreateFont((GR_CHAR
*) facename
.c_str(), pixelHeight
, & logFont
); 
1200     GrGetFontInfo(fontInfo
->fid
, & fontInfo
->info
); 
1201     return (wxNativeFont
) fontInfo
; 
1205     if (!facename
.empty()) 
1207         fontSpec
.Printf(wxT("-*-%s-*-*-normal-*-*-*-*-*-*-*-*-*"), 
1210         if ( wxTestFontSpec(fontSpec
) ) 
1214         //else: no such family, use default one instead 
1221             fontSpec
.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"), 
1223             if ( wxTestFontSpec(fontSpec
) ) 
1228             // fall through - try wxITALIC now 
1231             fontSpec
.Printf(wxT("-*-%s-*-i-*-*-*-*-*-*-*-*-*-*"), 
1233             if ( wxTestFontSpec(fontSpec
) ) 
1237             else if ( style 
== wxITALIC 
) // and not wxSLANT 
1240                 fontSpec
.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"), 
1242                 if ( wxTestFontSpec(fontSpec
) ) 
1248                     // no italic, no slant - leave default 
1255             wxFAIL_MSG(_T("unknown font style")); 
1256             // fall back to normal 
1268                   fontSpec
.Printf(wxT("-*-%s-bold-*-*-*-*-*-*-*-*-*-*-*"), 
1270                   if ( wxTestFontSpec(fontSpec
) ) 
1272                        xweight 
= wxT("bold"); 
1275                   fontSpec
.Printf(wxT("-*-%s-heavy-*-*-*-*-*-*-*-*-*-*-*"), 
1277                   if ( wxTestFontSpec(fontSpec
) ) 
1279                        xweight 
= wxT("heavy"); 
1282                   fontSpec
.Printf(wxT("-*-%s-extrabold-*-*-*-*-*-*-*-*-*-*-*"), 
1284                   if ( wxTestFontSpec(fontSpec
) ) 
1286                       xweight 
= wxT("extrabold"); 
1289                   fontSpec
.Printf(wxT("-*-%s-demibold-*-*-*-*-*-*-*-*-*-*-*"), 
1291                   if ( wxTestFontSpec(fontSpec
) ) 
1293                       xweight 
= wxT("demibold"); 
1296                   fontSpec
.Printf(wxT("-*-%s-black-*-*-*-*-*-*-*-*-*-*-*"), 
1298                   if ( wxTestFontSpec(fontSpec
) ) 
1300                       xweight 
= wxT("black"); 
1303                   fontSpec
.Printf(wxT("-*-%s-ultrablack-*-*-*-*-*-*-*-*-*-*-*"), 
1305                   if ( wxTestFontSpec(fontSpec
) ) 
1307                       xweight 
= wxT("ultrablack"); 
1314                   fontSpec
.Printf(wxT("-*-%s-light-*-*-*-*-*-*-*-*-*-*-*"), 
1316                   if ( wxTestFontSpec(fontSpec
) ) 
1318                        xweight 
= wxT("light"); 
1321                   fontSpec
.Printf(wxT("-*-%s-thin-*-*-*-*-*-*-*-*-*-*-*"), 
1323                   if ( wxTestFontSpec(fontSpec
) ) 
1325                        xweight 
= wxT("thin"); 
1332                   fontSpec
.Printf(wxT("-*-%s-medium-*-*-*-*-*-*-*-*-*-*-*"), 
1334                   if ( wxTestFontSpec(fontSpec
) ) 
1336                        xweight 
= wxT("medium"); 
1339                   fontSpec
.Printf(wxT("-*-%s-normal-*-*-*-*-*-*-*-*-*-*-*"), 
1341                   if ( wxTestFontSpec(fontSpec
) ) 
1343                        xweight 
= wxT("normal"); 
1346                   fontSpec
.Printf(wxT("-*-%s-regular-*-*-*-*-*-*-*-*-*-*-*"), 
1348                   if ( wxTestFontSpec(fontSpec
) ) 
1350                       xweight 
= wxT("regular"); 
1356         default:           xweight 
= wxT("*"); break; 
1359     // if pointSize is -1, don't specify any 
1361     if ( pointSize 
== -1 ) 
1367         sizeSpec
.Printf(_T("%d"), pointSize
); 
1370     // construct the X font spec from our data 
1371     fontSpec
.Printf(wxT("-*-%s-%s-%s-normal-*-*-%s-*-*-*-*-%s-%s"), 
1372                     xfamily
.c_str(), xweight
.c_str(), xstyle
.c_str(), 
1373                     sizeSpec
.c_str(), xregistry
.c_str(), xencoding
.c_str()); 
1376         *xFontName 
= fontSpec
; 
1378     return wxLoadFont(fontSpec
); 
1383 // ---------------------------------------------------------------------------- 
1385 // ---------------------------------------------------------------------------- 
1387 class wxFontModule 
: public wxModule
 
1394     DECLARE_DYNAMIC_CLASS(wxFontModule
) 
1397 IMPLEMENT_DYNAMIC_CLASS(wxFontModule
, wxModule
) 
1399 bool wxFontModule::OnInit() 
1401     g_fontHash 
= new wxHashTable( wxKEY_STRING 
); 
1406 void wxFontModule::OnExit() 
1410     g_fontHash 
= (wxHashTable 
*)NULL
; 
1413 #endif // GTK 2.0/1.x