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 
  52     #include "wx/x11/private.h" 
  53     #include "wx/gtk/private/string.h" 
  55     #define wxPANGO_CONV(s) (wxConvUTF8.cWX2MB((s))) 
  58 // ---------------------------------------------------------------------------- 
  60 // ---------------------------------------------------------------------------- 
  62 void wxNativeFontInfo::Init() 
  68 wxNativeFontInfo::Init(const wxNativeFontInfo
& info
) 
  71         description 
= pango_font_description_copy(info
.description
); 
  76 void wxNativeFontInfo::Free() 
  79         pango_font_description_free(description
); 
  82 int wxNativeFontInfo::GetPointSize() const 
  84     return pango_font_description_get_size( description 
) / PANGO_SCALE
; 
  87 wxFontStyle 
wxNativeFontInfo::GetStyle() const 
  89     wxFontStyle m_style 
= wxFONTSTYLE_NORMAL
; 
  91     switch (pango_font_description_get_style( description 
)) 
  93         case PANGO_STYLE_NORMAL
: 
  94             m_style 
= wxFONTSTYLE_NORMAL
; 
  96         case PANGO_STYLE_ITALIC
: 
  97             m_style 
= wxFONTSTYLE_ITALIC
; 
  99         case PANGO_STYLE_OBLIQUE
: 
 100             m_style 
= wxFONTSTYLE_SLANT
; 
 107 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
; 
 116     PangoWeight pango_weight 
= pango_font_description_get_weight( description 
); 
 118     // Until the API can be changed the following ranges of weight values are used: 
 119     // wxFONTWEIGHT_LIGHT:  100 .. 349 - range of 250 
 120     // wxFONTWEIGHT_NORMAL: 350 .. 599 - range of 250 
 121     // wxFONTWEIGHT_BOLD:   600 .. 900 - range of 301 (600 is "semibold" already) 
 123     if (pango_weight 
>= 600) 
 124         return wxFONTWEIGHT_BOLD
; 
 126     if (pango_weight 
< 350) 
 127         return wxFONTWEIGHT_LIGHT
; 
 129     return wxFONTWEIGHT_NORMAL
; 
 132 bool wxNativeFontInfo::GetUnderlined() const 
 137 wxString 
wxNativeFontInfo::GetFaceName() const 
 139     wxString tmp 
= wxGTK_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(__WXGTK24__) || 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 // gtk24 || 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
)); 
 319     // ensure a valid facename is selected 
 320     if (!wxFontEnumerator::IsValidFacename(GetFaceName())) 
 321         SetFaceName(wxNORMAL_FONT
->GetFaceName()); 
 326 wxString 
wxNativeFontInfo::ToString() const 
 328     wxGtkString 
str(pango_font_description_to_string( description 
)); 
 330     return wxGTK_CONV_BACK(str
); 
 333 bool wxNativeFontInfo::FromUserString(const wxString
& s
) 
 335     return FromString( s 
); 
 338 wxString 
wxNativeFontInfo::ToUserString() const 
 343 // ---------------------------------------------------------------------------- 
 344 // wxNativeEncodingInfo 
 345 // ---------------------------------------------------------------------------- 
 347 bool wxNativeEncodingInfo::FromString(const wxString
& WXUNUSED(s
)) 
 352 wxString 
wxNativeEncodingInfo::ToString() const 
 354     return wxEmptyString
; 
 357 bool wxTestFontEncoding(const wxNativeEncodingInfo
& WXUNUSED(info
)) 
 362 bool wxGetNativeFontEncoding(wxFontEncoding encoding
, 
 363                              wxNativeEncodingInfo 
*info
) 
 365     // all encodings are available in GTK+ 2 because we translate text in any 
 366     // encoding to UTF-8 internally anyhow 
 367     info
->facename
.clear(); 
 368     info
->encoding 
= encoding
; 
 377         #pragma message disable nosimpint 
 380     #include <X11/Xlib.h> 
 383         #pragma message enable nosimpint 
 386 #elif defined(__WXGTK__) 
 387     // we have to declare struct tm to avoid problems with first forward 
 388     // declaring it in C code (glib.h included from gdk.h does it) and then 
 389     // defining it when time.h is included from the headers below - this is 
 390     // known not to work at least with Sun CC 6.01 
 397 // ---------------------------------------------------------------------------- 
 399 // ---------------------------------------------------------------------------- 
 401 static wxHashTable 
*g_fontHash 
= (wxHashTable
*) NULL
; 
 403 // ---------------------------------------------------------------------------- 
 405 // ---------------------------------------------------------------------------- 
 407 // define the functions to create and destroy native fonts for this toolkit 
 409     wxNativeFont 
wxLoadFont(const wxString
& fontSpec
) 
 411         return XLoadQueryFont((Display 
*)wxGetDisplay(), fontSpec
); 
 414     inline void wxFreeFont(wxNativeFont font
) 
 416         XFreeFont((Display 
*)wxGetDisplay(), (XFontStruct 
*)font
); 
 418 #elif defined(__WXGTK__) 
 419     wxNativeFont 
wxLoadFont(const wxString
& fontSpec
) 
 421         // VZ: we should use gdk_fontset_load() instead of gdk_font_load() 
 422         //     here to be able to display Japanese fonts correctly (at least 
 423         //     this is what people report) but unfortunately doing it results 
 424         //     in tons of warnings when using GTK with "normal" European 
 425         //     languages and so we can't always do it and I don't know enough 
 426         //     to determine when should this be done... (FIXME) 
 427         return gdk_font_load( wxConvertWX2MB(fontSpec
) ); 
 430     inline void wxFreeFont(wxNativeFont font
) 
 432         gdk_font_unref(font
); 
 435     #error "Unknown GUI toolkit" 
 438 static bool wxTestFontSpec(const wxString
& fontspec
); 
 440 static wxNativeFont 
wxLoadQueryFont(int pointSize
, 
 445                                     const wxString
& facename
, 
 446                                     const wxString
& xregistry
, 
 447                                     const wxString
& xencoding
, 
 448                                     wxString
* xFontName
); 
 450 // ============================================================================ 
 452 // ============================================================================ 
 454 // ---------------------------------------------------------------------------- 
 455 // wxNativeEncodingInfo 
 456 // ---------------------------------------------------------------------------- 
 458 // convert to/from the string representation: format is 
 459 //      encodingid;registry;encoding[;facename] 
 460 bool wxNativeEncodingInfo::FromString(const wxString
& s
) 
 462     // use ";", not "-" because it may be part of encoding name 
 463     wxStringTokenizer 
tokenizer(s
, _T(";")); 
 465     wxString encid 
= tokenizer
.GetNextToken(); 
 467     if ( !encid
.ToLong(&enc
) ) 
 469     encoding 
= (wxFontEncoding
)enc
; 
 471     xregistry 
= tokenizer
.GetNextToken(); 
 475     xencoding 
= tokenizer
.GetNextToken(); 
 480     facename 
= tokenizer
.GetNextToken(); 
 485 wxString 
wxNativeEncodingInfo::ToString() const 
 488     s 
<< (long)encoding 
<< _T(';') << xregistry 
<< _T(';') << xencoding
; 
 489     if ( !facename
.empty() ) 
 491         s 
<< _T(';') << facename
; 
 497 // ---------------------------------------------------------------------------- 
 499 // ---------------------------------------------------------------------------- 
 501 void wxNativeFontInfo::Init() 
 506 bool wxNativeFontInfo::FromString(const wxString
& s
) 
 508     wxStringTokenizer 
tokenizer(s
, _T(";")); 
 511     wxString token 
= tokenizer
.GetNextToken(); 
 512     if ( token 
!= _T('0') ) 
 515     xFontName 
= tokenizer
.GetNextToken(); 
 517     // this should be the end 
 518     if ( tokenizer
.HasMoreTokens() ) 
 521     return FromXFontName(xFontName
); 
 524 wxString 
wxNativeFontInfo::ToString() const 
 527     return wxString::Format(_T("%d;%s"), 0, GetXFontName().c_str()); 
 530 bool wxNativeFontInfo::FromUserString(const wxString
& s
) 
 532     return FromXFontName(s
); 
 535 wxString 
wxNativeFontInfo::ToUserString() const 
 537     return GetXFontName(); 
 540 bool wxNativeFontInfo::HasElements() const 
 542     // we suppose that the foundry is never empty, so if it is it means that we 
 543     // had never parsed the XLFD 
 544     return !fontElements
[0].empty(); 
 547 wxString 
wxNativeFontInfo::GetXFontComponent(wxXLFDField field
) const 
 549     wxCHECK_MSG( field 
< wxXLFD_MAX
, wxEmptyString
, _T("invalid XLFD field") ); 
 551     if ( !HasElements() ) 
 554         if ( !((wxNativeFontInfo 
*)this)->FromXFontName(xFontName
) ) 
 555             return wxEmptyString
; 
 558     return fontElements
[field
]; 
 561 bool wxNativeFontInfo::FromXFontName(const wxString
& fontname
) 
 563     // TODO: we should be able to handle the font aliases here, but how? 
 564     wxStringTokenizer 
tokenizer(fontname
, _T("-")); 
 566     // skip the leading, usually empty field (font name registry) 
 567     if ( !tokenizer
.HasMoreTokens() ) 
 570     (void)tokenizer
.GetNextToken(); 
 572     for ( size_t n 
= 0; n 
< WXSIZEOF(fontElements
); n
++ ) 
 574         if ( !tokenizer
.HasMoreTokens() ) 
 576             // not enough elements in the XLFD - or maybe an alias 
 580         wxString field 
= tokenizer
.GetNextToken(); 
 581         if ( !field
.empty() && field 
!= _T('*') ) 
 583             // we're really initialized now 
 587         fontElements
[n
] = field
; 
 590     // this should be all 
 591     if ( tokenizer
.HasMoreTokens() ) 
 597 wxString 
wxNativeFontInfo::GetXFontName() const 
 599     if ( xFontName
.empty() ) 
 601         for ( size_t n 
= 0; n 
< WXSIZEOF(fontElements
); n
++ ) 
 603             // replace the non specified elements with '*' except for the 
 604             // additional style which is usually just omitted 
 605             wxString elt 
= fontElements
[n
]; 
 606             if ( elt
.empty() && n 
!= wxXLFD_ADDSTYLE 
) 
 612             ((wxNativeFontInfo 
*)this)->xFontName 
<< _T('-') << elt
; 
 620 wxNativeFontInfo::SetXFontComponent(wxXLFDField field
, const wxString
& value
) 
 622     wxCHECK_RET( field 
< wxXLFD_MAX
, _T("invalid XLFD field") ); 
 624     // this class should be initialized with a valid font spec first and only 
 625     // then the fields may be modified! 
 626     wxASSERT_MSG( !IsDefault(), _T("can't modify an uninitialized XLFD") ); 
 628     if ( !HasElements() ) 
 631         if ( !((wxNativeFontInfo 
*)this)->FromXFontName(xFontName
) ) 
 633             wxFAIL_MSG( _T("can't set font element for invalid XLFD") ); 
 639     fontElements
[field
] = value
; 
 641     // invalidate the XFLD, it doesn't correspond to the font elements any more 
 645 void wxNativeFontInfo::SetXFontName(const wxString
& xFontName_
) 
 647     // invalidate the font elements, GetXFontComponent() will reparse the XLFD 
 648     fontElements
[0].clear(); 
 650     xFontName 
= xFontName_
; 
 655 int wxNativeFontInfo::GetPointSize() const 
 657     const wxString s 
= GetXFontComponent(wxXLFD_POINTSIZE
); 
 659     // return -1 to indicate that the size is unknown 
 661     return s
.ToLong(&l
) ? l 
: -1; 
 664 wxFontStyle 
wxNativeFontInfo::GetStyle() const 
 666     const wxString s 
= GetXFontComponent(wxXLFD_SLANT
); 
 668     if ( s
.length() != 1 ) 
 670         // it is really unknown but we don't have any way to return it from 
 672         return wxFONTSTYLE_NORMAL
; 
 678             // again, unknown but consider normal by default 
 681             return wxFONTSTYLE_NORMAL
; 
 684             return wxFONTSTYLE_ITALIC
; 
 687             return wxFONTSTYLE_SLANT
; 
 691 wxFontWeight 
wxNativeFontInfo::GetWeight() const 
 693     const wxString s 
= GetXFontComponent(wxXLFD_WEIGHT
).MakeLower(); 
 694     if ( s
.find(_T("bold")) != wxString::npos 
|| s 
== _T("black") ) 
 695         return wxFONTWEIGHT_BOLD
; 
 696     else if ( s 
== _T("light") ) 
 697         return wxFONTWEIGHT_LIGHT
; 
 699     return wxFONTWEIGHT_NORMAL
; 
 702 bool wxNativeFontInfo::GetUnderlined() const 
 704     // X fonts are never underlined 
 708 wxString 
wxNativeFontInfo::GetFaceName() const 
 710     // wxWidgets facename probably more accurately corresponds to X family 
 711     return GetXFontComponent(wxXLFD_FAMILY
); 
 714 wxFontFamily 
wxNativeFontInfo::GetFamily() const 
 716     // and wxWidgets family -- to X foundry, but we have to translate it to 
 717     // wxFontFamily somehow... 
 718     wxFAIL_MSG(_T("not implemented")); // GetXFontComponent(wxXLFD_FOUNDRY); 
 720     return wxFONTFAMILY_DEFAULT
; 
 723 wxFontEncoding 
wxNativeFontInfo::GetEncoding() const 
 725     // we already have the code for this but need to refactor it first 
 726     wxFAIL_MSG( _T("not implemented") ); 
 728     return wxFONTENCODING_MAX
; 
 731 void wxNativeFontInfo::SetPointSize(int pointsize
) 
 733     SetXFontComponent(wxXLFD_POINTSIZE
, wxString::Format(_T("%d"), pointsize
)); 
 736 void wxNativeFontInfo::SetStyle(wxFontStyle style
) 
 741         case wxFONTSTYLE_ITALIC
: 
 745         case wxFONTSTYLE_SLANT
: 
 749         case wxFONTSTYLE_NORMAL
: 
 753             wxFAIL_MSG( _T("unknown wxFontStyle in wxNativeFontInfo::SetStyle") ); 
 757     SetXFontComponent(wxXLFD_SLANT
, s
); 
 760 void wxNativeFontInfo::SetWeight(wxFontWeight weight
) 
 765         case wxFONTWEIGHT_BOLD
: 
 769         case wxFONTWEIGHT_LIGHT
: 
 773         case wxFONTWEIGHT_NORMAL
: 
 778             wxFAIL_MSG( _T("unknown wxFontWeight in wxNativeFontInfo::SetWeight") ); 
 782     SetXFontComponent(wxXLFD_WEIGHT
, s
); 
 785 void wxNativeFontInfo::SetUnderlined(bool WXUNUSED(underlined
)) 
 787     // can't do this under X 
 790 bool wxNativeFontInfo::SetFaceName(const wxString
& facename
) 
 792     SetXFontComponent(wxXLFD_FAMILY
, facename
); 
 796 void wxNativeFontInfo::SetFamily(wxFontFamily 
WXUNUSED(family
)) 
 798     // wxFontFamily -> X foundry, anyone? 
 799     wxFAIL_MSG( _T("not implemented") ); 
 801     // SetXFontComponent(wxXLFD_FOUNDRY, ...); 
 804 void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding
) 
 806     wxNativeEncodingInfo info
; 
 807     if ( wxGetNativeFontEncoding(encoding
, &info
) ) 
 809         SetXFontComponent(wxXLFD_ENCODING
, info
.xencoding
); 
 810         SetXFontComponent(wxXLFD_REGISTRY
, info
.xregistry
); 
 814 // ---------------------------------------------------------------------------- 
 816 // ---------------------------------------------------------------------------- 
 818 bool wxGetNativeFontEncoding(wxFontEncoding encoding
, 
 819                              wxNativeEncodingInfo 
*info
) 
 821     wxCHECK_MSG( info
, false, _T("bad pointer in wxGetNativeFontEncoding") ); 
 823     if ( encoding 
== wxFONTENCODING_DEFAULT 
) 
 825         encoding 
= wxFont::GetDefaultEncoding(); 
 830         case wxFONTENCODING_ISO8859_1
: 
 831         case wxFONTENCODING_ISO8859_2
: 
 832         case wxFONTENCODING_ISO8859_3
: 
 833         case wxFONTENCODING_ISO8859_4
: 
 834         case wxFONTENCODING_ISO8859_5
: 
 835         case wxFONTENCODING_ISO8859_6
: 
 836         case wxFONTENCODING_ISO8859_7
: 
 837         case wxFONTENCODING_ISO8859_8
: 
 838         case wxFONTENCODING_ISO8859_9
: 
 839         case wxFONTENCODING_ISO8859_10
: 
 840         case wxFONTENCODING_ISO8859_11
: 
 841         case wxFONTENCODING_ISO8859_12
: 
 842         case wxFONTENCODING_ISO8859_13
: 
 843         case wxFONTENCODING_ISO8859_14
: 
 844         case wxFONTENCODING_ISO8859_15
: 
 846                 int cp 
= encoding 
- wxFONTENCODING_ISO8859_1 
+ 1; 
 847                 info
->xregistry 
= wxT("iso8859"); 
 848                 info
->xencoding
.Printf(wxT("%d"), cp
); 
 852         case wxFONTENCODING_UTF8
: 
 853             info
->xregistry 
= wxT("iso10646"); 
 854             info
->xencoding 
= wxT("*"); 
 857         case wxFONTENCODING_GB2312
: 
 858             info
->xregistry 
= wxT("GB2312");   // or the otherway round? 
 859             info
->xencoding 
= wxT("*"); 
 862         case wxFONTENCODING_KOI8
: 
 863         case wxFONTENCODING_KOI8_U
: 
 864             info
->xregistry 
= wxT("koi8"); 
 866             // we don't make distinction between koi8-r, koi8-u and koi8-ru (so far) 
 867             info
->xencoding 
= wxT("*"); 
 870         case wxFONTENCODING_CP1250
: 
 871         case wxFONTENCODING_CP1251
: 
 872         case wxFONTENCODING_CP1252
: 
 873         case wxFONTENCODING_CP1253
: 
 874         case wxFONTENCODING_CP1254
: 
 875         case wxFONTENCODING_CP1255
: 
 876         case wxFONTENCODING_CP1256
: 
 877         case wxFONTENCODING_CP1257
: 
 879                 int cp 
= encoding 
- wxFONTENCODING_CP1250 
+ 1250; 
 880                 info
->xregistry 
= wxT("microsoft"); 
 881                 info
->xencoding
.Printf(wxT("cp%d"), cp
); 
 885         case wxFONTENCODING_EUC_JP
: 
 886         case wxFONTENCODING_SHIFT_JIS
: 
 887             info
->xregistry 
= "jis*"; 
 888             info
->xencoding 
= "*"; 
 891         case wxFONTENCODING_SYSTEM
: 
 893             info
->xencoding 
= wxT("*"); 
 897             // don't know how to translate this encoding into X fontspec 
 901     info
->encoding 
= encoding
; 
 906 bool wxTestFontEncoding(const wxNativeEncodingInfo
& info
) 
 909     fontspec
.Printf(_T("-*-%s-*-*-*-*-*-*-*-*-*-*-%s-%s"), 
 910                     !info
.facename 
? _T("*") : info
.facename
.c_str(), 
 911                     info
.xregistry
.c_str(), 
 912                     info
.xencoding
.c_str()); 
 914     return wxTestFontSpec(fontspec
); 
 917 // ---------------------------------------------------------------------------- 
 918 // X-specific functions 
 919 // ---------------------------------------------------------------------------- 
 921 wxNativeFont 
wxLoadQueryNearestFont(int pointSize
, 
 926                                     const wxString 
&facename
, 
 927                                     wxFontEncoding encoding
, 
 930     if ( encoding 
== wxFONTENCODING_DEFAULT 
) 
 932         encoding 
= wxFont::GetDefaultEncoding(); 
 935     // first determine the encoding - if the font doesn't exist at all in this 
 936     // encoding, it's useless to do all other approximations (i.e. size, 
 937     // family &c don't matter much) 
 938     wxNativeEncodingInfo info
; 
 939     if ( encoding 
== wxFONTENCODING_SYSTEM 
) 
 941         // This will always work so we don't test to save time 
 942         wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM
, &info
); 
 946         if ( !wxGetNativeFontEncoding(encoding
, &info
) || 
 947              !wxTestFontEncoding(info
) ) 
 950             if ( !wxFontMapper::Get()->GetAltForEncoding(encoding
, &info
) ) 
 951 #endif // wxUSE_FONTMAP 
 953                 // unspported encoding - replace it with the default 
 955                 // NB: we can't just return 0 from here because wxGTK code doesn't 
 956                 //     check for it (i.e. it supposes that we'll always succeed), 
 957                 //     so it would provoke a crash 
 958                 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM
, &info
); 
 963     // OK, we have the correct xregistry/xencoding in info structure 
 964     wxNativeFont font 
= 0; 
 966     // if we already have the X font name, try to use it 
 967     if( xFontName 
&& !xFontName
->empty() ) 
 970         //  Make sure point size is correct for scale factor. 
 972         wxStringTokenizer 
tokenizer(*xFontName
, _T("-"), wxTOKEN_RET_DELIMS
); 
 973         wxString newFontName
; 
 975         for(int i 
= 0; i 
< 8; i
++) 
 976           newFontName 
+= tokenizer
.NextToken(); 
 978         (void) tokenizer
.NextToken(); 
 980         newFontName 
+= wxString::Format(wxT("%d-"), pointSize
); 
 982         while(tokenizer
.HasMoreTokens()) 
 983           newFontName 
+= tokenizer
.GetNextToken(); 
 985         font 
= wxLoadFont(newFontName
); 
 988           *xFontName 
= newFontName
; 
 993         // search up and down by stepsize 10 
 994         int max_size 
= pointSize 
+ 20 * (1 + (pointSize
/180)); 
 995         int min_size 
= pointSize 
- 20 * (1 + (pointSize
/180)); 
 997         int i
, round
; // counters 
 999         // first round: search for equal, then for smaller and for larger size with the given weight and style 
1000         int testweight 
= weight
; 
1001         int teststyle 
= style
; 
1003         for ( round 
= 0; round 
< 3; round
++ ) 
1005             // second round: use normal weight 
1008                 if ( testweight 
!= wxNORMAL 
) 
1010                     testweight 
= wxNORMAL
; 
1014                     ++round
; // fall through to third round 
1018             // third round: ... and use normal style 
1021                 if ( teststyle 
!= wxNORMAL 
) 
1023                     teststyle 
= wxNORMAL
; 
1030             // Search for equal or smaller size (approx.) 
1031             for ( i 
= pointSize
; !font 
&& i 
>= 10 && i 
>= min_size
; i 
-= 10 ) 
1033                 font 
= wxLoadQueryFont(i
, family
, teststyle
, testweight
, underlined
, 
1034                                    facename
, info
.xregistry
, info
.xencoding
, 
1038             // Search for larger size (approx.) 
1039             for ( i 
= pointSize 
+ 10; !font 
&& i 
<= max_size
; i 
+= 10 ) 
1041                 font 
= wxLoadQueryFont(i
, family
, teststyle
, testweight
, underlined
, 
1042                                    facename
, info
.xregistry
, info
.xencoding
, 
1047         // Try default family 
1048         if ( !font 
&& family 
!= wxDEFAULT 
) 
1050             font 
= wxLoadQueryFont(pointSize
, wxDEFAULT
, style
, weight
, 
1051                                    underlined
, facename
, 
1052                                    info
.xregistry
, info
.xencoding
, 
1056         // ignore size, family, style and weight but try to find font with the 
1057         // given facename and encoding 
1060             font 
= wxLoadQueryFont(120, wxDEFAULT
, wxNORMAL
, wxNORMAL
, 
1061                                    underlined
, facename
, 
1062                                    info
.xregistry
, info
.xencoding
, 
1065             // ignore family as well 
1068                 font 
= wxLoadQueryFont(120, wxDEFAULT
, wxNORMAL
, wxNORMAL
, 
1069                                        underlined
, wxEmptyString
, 
1070                                        info
.xregistry
, info
.xencoding
, 
1073                 // if it still failed, try to get the font of any size but 
1074                 // with the requested encoding: this can happen if the 
1075                 // encoding is only available in one size which happens to be 
1076                 // different from 120 
1079                     font 
= wxLoadQueryFont(-1, wxDEFAULT
, wxNORMAL
, wxNORMAL
, 
1080                                            false, wxEmptyString
, 
1081                                            info
.xregistry
, info
.xencoding
, 
1084                     // this should never happen as we had tested for it in the 
1085                     // very beginning, but if it does, do return something non 
1086                     // NULL or we'd crash in wxFont code 
1089                         wxFAIL_MSG( _T("this encoding should be available!") ); 
1091                         font 
= wxLoadQueryFont(-1, 
1092                                                wxDEFAULT
, wxNORMAL
, wxNORMAL
, 
1093                                                false, wxEmptyString
, 
1105 // ---------------------------------------------------------------------------- 
1106 // private functions 
1107 // ---------------------------------------------------------------------------- 
1109 // returns true if there are any fonts matching this font spec 
1110 static bool wxTestFontSpec(const wxString
& fontspec
) 
1112     // some X servers will fail to load this font because there are too many 
1113     // matches so we must test explicitly for this 
1114     if ( fontspec 
== _T("-*-*-*-*-*-*-*-*-*-*-*-*-*-*") ) 
1119     wxNativeFont test 
= (wxNativeFont
) g_fontHash
->Get( fontspec 
); 
1125     test 
= wxLoadFont(fontspec
); 
1126     g_fontHash
->Put( fontspec
, (wxObject
*) test 
); 
1140 static wxNativeFont 
wxLoadQueryFont(int pointSize
, 
1144                                     bool WXUNUSED(underlined
), 
1145                                     const wxString
& facename
, 
1146                                     const wxString
& xregistry
, 
1147                                     const wxString
& xencoding
, 
1148                                     wxString
* xFontName
) 
1153         case wxDECORATIVE
: xfamily 
= wxT("lucida"); break; 
1154         case wxROMAN
:      xfamily 
= wxT("times");  break; 
1155         case wxMODERN
:     xfamily 
= wxT("courier"); break; 
1156         case wxSWISS
:      xfamily 
= wxT("helvetica"); break; 
1157         case wxTELETYPE
:   xfamily 
= wxT("lucidatypewriter"); break; 
1158         case wxSCRIPT
:     xfamily 
= wxT("utopia"); break; 
1159         default:           xfamily 
= wxT("*"); 
1167                  xweight 
= MWLF_WEIGHT_BOLD
; 
1172                  xweight 
= MWLF_WEIGHT_LIGHT
; 
1177                  xweight 
= MWLF_WEIGHT_NORMAL
; 
1183                  xweight 
= MWLF_WEIGHT_DEFAULT
; 
1187     GR_SCREEN_INFO screenInfo
; 
1188     GrGetScreenInfo(& screenInfo
); 
1190     int yPixelsPerCM 
= screenInfo
.ydpcm
; 
1192     // A point is 1/72 of an inch. 
1193     // An inch is 2.541 cm. 
1194     // So pixelHeight = (pointSize / 72) (inches) * 2.541 (for cm) * yPixelsPerCM (for pixels) 
1195     // In fact pointSize is 10 * the normal point size so 
1198     int pixelHeight 
= (int) ( (((float)pointSize
) / 720.0) * 2.541 * (float) yPixelsPerCM
) ; 
1200     // An alternative: assume that the screen is 72 dpi. 
1201     //int pixelHeight = (int) (((float)pointSize / 720.0) * 72.0) ; 
1202     //int pixelHeight = (int) ((float)pointSize / 10.0) ; 
1205     logFont
.lfHeight 
= pixelHeight
; 
1206     logFont
.lfWidth 
= 0; 
1207     logFont
.lfEscapement 
= 0; 
1208     logFont
.lfOrientation 
= 0; 
1209     logFont
.lfWeight 
= xweight
; 
1210     logFont
.lfItalic 
= (style 
== wxNORMAL 
? 0 : 1) ; 
1211     logFont
.lfUnderline 
= 0; 
1212     logFont
.lfStrikeOut 
= 0; 
1213     logFont
.lfCharSet 
= MWLF_CHARSET_DEFAULT
; // TODO: select appropriate one 
1214     logFont
.lfOutPrecision 
= MWLF_TYPE_DEFAULT
; 
1215     logFont
.lfClipPrecision 
= 0; // Not used 
1216     logFont
.lfRoman 
= (family 
== wxROMAN 
? 1 : 0) ; 
1217     logFont
.lfSerif 
= (family 
== wxSWISS 
? 0 : 1) ; 
1218     logFont
.lfSansSerif 
= !logFont
.lfSerif 
; 
1219     logFont
.lfModern 
= (family 
== wxMODERN 
? 1 : 0) ; 
1220     logFont
.lfProportional 
= (family 
== wxTELETYPE 
? 0 : 1) ; 
1221     logFont
.lfOblique 
= 0; 
1222     logFont
.lfSmallCaps 
= 0; 
1223     logFont
.lfPitch 
= 0; // 0 = default 
1224     strcpy(logFont
.lfFaceName
, facename
.c_str()); 
1226     XFontStruct
* fontInfo 
= (XFontStruct
*) malloc(sizeof(XFontStruct
)); 
1227     fontInfo
->fid 
= GrCreateFont((GR_CHAR
*) facename
.c_str(), pixelHeight
, & logFont
); 
1228     GrGetFontInfo(fontInfo
->fid
, & fontInfo
->info
); 
1229     return (wxNativeFont
) fontInfo
; 
1233     if (!facename
.empty()) 
1235         fontSpec
.Printf(wxT("-*-%s-*-*-normal-*-*-*-*-*-*-*-*-*"), 
1238         if ( wxTestFontSpec(fontSpec
) ) 
1242         //else: no such family, use default one instead 
1249             fontSpec
.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"), 
1251             if ( wxTestFontSpec(fontSpec
) ) 
1256             // fall through - try wxITALIC now 
1259             fontSpec
.Printf(wxT("-*-%s-*-i-*-*-*-*-*-*-*-*-*-*"), 
1261             if ( wxTestFontSpec(fontSpec
) ) 
1265             else if ( style 
== wxITALIC 
) // and not wxSLANT 
1268                 fontSpec
.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"), 
1270                 if ( wxTestFontSpec(fontSpec
) ) 
1276                     // no italic, no slant - leave default 
1283             wxFAIL_MSG(_T("unknown font style")); 
1284             // fall back to normal 
1296                   fontSpec
.Printf(wxT("-*-%s-bold-*-*-*-*-*-*-*-*-*-*-*"), 
1298                   if ( wxTestFontSpec(fontSpec
) ) 
1300                        xweight 
= wxT("bold"); 
1303                   fontSpec
.Printf(wxT("-*-%s-heavy-*-*-*-*-*-*-*-*-*-*-*"), 
1305                   if ( wxTestFontSpec(fontSpec
) ) 
1307                        xweight 
= wxT("heavy"); 
1310                   fontSpec
.Printf(wxT("-*-%s-extrabold-*-*-*-*-*-*-*-*-*-*-*"), 
1312                   if ( wxTestFontSpec(fontSpec
) ) 
1314                       xweight 
= wxT("extrabold"); 
1317                   fontSpec
.Printf(wxT("-*-%s-demibold-*-*-*-*-*-*-*-*-*-*-*"), 
1319                   if ( wxTestFontSpec(fontSpec
) ) 
1321                       xweight 
= wxT("demibold"); 
1324                   fontSpec
.Printf(wxT("-*-%s-black-*-*-*-*-*-*-*-*-*-*-*"), 
1326                   if ( wxTestFontSpec(fontSpec
) ) 
1328                       xweight 
= wxT("black"); 
1331                   fontSpec
.Printf(wxT("-*-%s-ultrablack-*-*-*-*-*-*-*-*-*-*-*"), 
1333                   if ( wxTestFontSpec(fontSpec
) ) 
1335                       xweight 
= wxT("ultrablack"); 
1342                   fontSpec
.Printf(wxT("-*-%s-light-*-*-*-*-*-*-*-*-*-*-*"), 
1344                   if ( wxTestFontSpec(fontSpec
) ) 
1346                        xweight 
= wxT("light"); 
1349                   fontSpec
.Printf(wxT("-*-%s-thin-*-*-*-*-*-*-*-*-*-*-*"), 
1351                   if ( wxTestFontSpec(fontSpec
) ) 
1353                        xweight 
= wxT("thin"); 
1360                   fontSpec
.Printf(wxT("-*-%s-medium-*-*-*-*-*-*-*-*-*-*-*"), 
1362                   if ( wxTestFontSpec(fontSpec
) ) 
1364                        xweight 
= wxT("medium"); 
1367                   fontSpec
.Printf(wxT("-*-%s-normal-*-*-*-*-*-*-*-*-*-*-*"), 
1369                   if ( wxTestFontSpec(fontSpec
) ) 
1371                        xweight 
= wxT("normal"); 
1374                   fontSpec
.Printf(wxT("-*-%s-regular-*-*-*-*-*-*-*-*-*-*-*"), 
1376                   if ( wxTestFontSpec(fontSpec
) ) 
1378                       xweight 
= wxT("regular"); 
1384         default:           xweight 
= wxT("*"); break; 
1387     // if pointSize is -1, don't specify any 
1389     if ( pointSize 
== -1 ) 
1395         sizeSpec
.Printf(_T("%d"), pointSize
); 
1398     // construct the X font spec from our data 
1399     fontSpec
.Printf(wxT("-*-%s-%s-%s-normal-*-*-%s-*-*-*-*-%s-%s"), 
1400                     xfamily
.c_str(), xweight
.c_str(), xstyle
.c_str(), 
1401                     sizeSpec
.c_str(), xregistry
.c_str(), xencoding
.c_str()); 
1404         *xFontName 
= fontSpec
; 
1406     return wxLoadFont(fontSpec
); 
1411 // ---------------------------------------------------------------------------- 
1413 // ---------------------------------------------------------------------------- 
1415 class wxFontModule 
: public wxModule
 
1422     DECLARE_DYNAMIC_CLASS(wxFontModule
) 
1425 IMPLEMENT_DYNAMIC_CLASS(wxFontModule
, wxModule
) 
1427 bool wxFontModule::OnInit() 
1429     g_fontHash 
= new wxHashTable( wxKEY_STRING 
); 
1434 void wxFontModule::OnExit() 
1438     g_fontHash 
= (wxHashTable 
*)NULL
; 
1441 #endif // GTK 2.0/1.x