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(__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 wxPANGO_CONV_BACK(str
); 
 333 bool wxNativeFontInfo::FromUserString(const wxString
& s
) 
 335     return FromString( s 
); 
 338 wxString 
wxNativeFontInfo::ToUserString() const 
 347         #pragma message disable nosimpint 
 350     #include <X11/Xlib.h> 
 353         #pragma message enable nosimpint 
 356 #elif defined(__WXGTK__) 
 357     // we have to declare struct tm to avoid problems with first forward 
 358     // declaring it in C code (glib.h included from gdk.h does it) and then 
 359     // defining it when time.h is included from the headers below - this is 
 360     // known not to work at least with Sun CC 6.01 
 367 // ---------------------------------------------------------------------------- 
 369 // ---------------------------------------------------------------------------- 
 371 static wxHashTable 
*g_fontHash 
= (wxHashTable
*) NULL
; 
 373 // ---------------------------------------------------------------------------- 
 375 // ---------------------------------------------------------------------------- 
 377 // define the functions to create and destroy native fonts for this toolkit 
 379     wxNativeFont 
wxLoadFont(const wxString
& fontSpec
) 
 381         return XLoadQueryFont((Display 
*)wxGetDisplay(), fontSpec
); 
 384     inline void wxFreeFont(wxNativeFont font
) 
 386         XFreeFont((Display 
*)wxGetDisplay(), (XFontStruct 
*)font
); 
 388 #elif defined(__WXGTK__) 
 389     wxNativeFont 
wxLoadFont(const wxString
& fontSpec
) 
 391         // VZ: we should use gdk_fontset_load() instead of gdk_font_load() 
 392         //     here to be able to display Japanese fonts correctly (at least 
 393         //     this is what people report) but unfortunately doing it results 
 394         //     in tons of warnings when using GTK with "normal" European 
 395         //     languages and so we can't always do it and I don't know enough 
 396         //     to determine when should this be done... (FIXME) 
 397         return gdk_font_load( wxConvertWX2MB(fontSpec
) ); 
 400     inline void wxFreeFont(wxNativeFont font
) 
 402         gdk_font_unref(font
); 
 405     #error "Unknown GUI toolkit" 
 408 static bool wxTestFontSpec(const wxString
& fontspec
); 
 410 static wxNativeFont 
wxLoadQueryFont(int pointSize
, 
 415                                     const wxString
& facename
, 
 416                                     const wxString
& xregistry
, 
 417                                     const wxString
& xencoding
, 
 418                                     wxString
* xFontName
); 
 420 // ============================================================================ 
 422 // ============================================================================ 
 424 // ---------------------------------------------------------------------------- 
 425 // wxNativeEncodingInfo 
 426 // ---------------------------------------------------------------------------- 
 428 // convert to/from the string representation: format is 
 429 //      encodingid;registry;encoding[;facename] 
 430 bool wxNativeEncodingInfo::FromString(const wxString
& s
) 
 432     // use ";", not "-" because it may be part of encoding name 
 433     wxStringTokenizer 
tokenizer(s
, _T(";")); 
 435     wxString encid 
= tokenizer
.GetNextToken(); 
 437     if ( !encid
.ToLong(&enc
) ) 
 439     encoding 
= (wxFontEncoding
)enc
; 
 441     xregistry 
= tokenizer
.GetNextToken(); 
 445     xencoding 
= tokenizer
.GetNextToken(); 
 450     facename 
= tokenizer
.GetNextToken(); 
 455 wxString 
wxNativeEncodingInfo::ToString() const 
 458     s 
<< (long)encoding 
<< _T(';') << xregistry 
<< _T(';') << xencoding
; 
 459     if ( !facename
.empty() ) 
 461         s 
<< _T(';') << facename
; 
 467 // ---------------------------------------------------------------------------- 
 469 // ---------------------------------------------------------------------------- 
 471 void wxNativeFontInfo::Init() 
 476 bool wxNativeFontInfo::FromString(const wxString
& s
) 
 478     wxStringTokenizer 
tokenizer(s
, _T(";")); 
 481     wxString token 
= tokenizer
.GetNextToken(); 
 482     if ( token 
!= _T('0') ) 
 485     xFontName 
= tokenizer
.GetNextToken(); 
 487     // this should be the end 
 488     if ( tokenizer
.HasMoreTokens() ) 
 491     return FromXFontName(xFontName
); 
 494 wxString 
wxNativeFontInfo::ToString() const 
 497     return wxString::Format(_T("%d;%s"), 0, GetXFontName().c_str()); 
 500 bool wxNativeFontInfo::FromUserString(const wxString
& s
) 
 502     return FromXFontName(s
); 
 505 wxString 
wxNativeFontInfo::ToUserString() const 
 507     return GetXFontName(); 
 510 bool wxNativeFontInfo::HasElements() const 
 512     // we suppose that the foundry is never empty, so if it is it means that we 
 513     // had never parsed the XLFD 
 514     return !fontElements
[0].empty(); 
 517 wxString 
wxNativeFontInfo::GetXFontComponent(wxXLFDField field
) const 
 519     wxCHECK_MSG( field 
< wxXLFD_MAX
, wxEmptyString
, _T("invalid XLFD field") ); 
 521     if ( !HasElements() ) 
 524         if ( !((wxNativeFontInfo 
*)this)->FromXFontName(xFontName
) ) 
 525             return wxEmptyString
; 
 528     return fontElements
[field
]; 
 531 bool wxNativeFontInfo::FromXFontName(const wxString
& fontname
) 
 533     // TODO: we should be able to handle the font aliases here, but how? 
 534     wxStringTokenizer 
tokenizer(fontname
, _T("-")); 
 536     // skip the leading, usually empty field (font name registry) 
 537     if ( !tokenizer
.HasMoreTokens() ) 
 540     (void)tokenizer
.GetNextToken(); 
 542     for ( size_t n 
= 0; n 
< WXSIZEOF(fontElements
); n
++ ) 
 544         if ( !tokenizer
.HasMoreTokens() ) 
 546             // not enough elements in the XLFD - or maybe an alias 
 550         wxString field 
= tokenizer
.GetNextToken(); 
 551         if ( !field
.empty() && field 
!= _T('*') ) 
 553             // we're really initialized now 
 557         fontElements
[n
] = field
; 
 560     // this should be all 
 561     if ( tokenizer
.HasMoreTokens() ) 
 567 wxString 
wxNativeFontInfo::GetXFontName() const 
 569     if ( xFontName
.empty() ) 
 571         for ( size_t n 
= 0; n 
< WXSIZEOF(fontElements
); n
++ ) 
 573             // replace the non specified elements with '*' except for the 
 574             // additional style which is usually just omitted 
 575             wxString elt 
= fontElements
[n
]; 
 576             if ( elt
.empty() && n 
!= wxXLFD_ADDSTYLE 
) 
 582             ((wxNativeFontInfo 
*)this)->xFontName 
<< _T('-') << elt
; 
 590 wxNativeFontInfo::SetXFontComponent(wxXLFDField field
, const wxString
& value
) 
 592     wxCHECK_RET( field 
< wxXLFD_MAX
, _T("invalid XLFD field") ); 
 594     // this class should be initialized with a valid font spec first and only 
 595     // then the fields may be modified! 
 596     wxASSERT_MSG( !IsDefault(), _T("can't modify an uninitialized XLFD") ); 
 598     if ( !HasElements() ) 
 601         if ( !((wxNativeFontInfo 
*)this)->FromXFontName(xFontName
) ) 
 603             wxFAIL_MSG( _T("can't set font element for invalid XLFD") ); 
 609     fontElements
[field
] = value
; 
 611     // invalidate the XFLD, it doesn't correspond to the font elements any more 
 615 void wxNativeFontInfo::SetXFontName(const wxString
& xFontName_
) 
 617     // invalidate the font elements, GetXFontComponent() will reparse the XLFD 
 618     fontElements
[0].clear(); 
 620     xFontName 
= xFontName_
; 
 625 int wxNativeFontInfo::GetPointSize() const 
 627     const wxString s 
= GetXFontComponent(wxXLFD_POINTSIZE
); 
 629     // return -1 to indicate that the size is unknown 
 631     return s
.ToLong(&l
) ? l 
: -1; 
 634 wxFontStyle 
wxNativeFontInfo::GetStyle() const 
 636     const wxString s 
= GetXFontComponent(wxXLFD_SLANT
); 
 638     if ( s
.length() != 1 ) 
 640         // it is really unknown but we don't have any way to return it from 
 642         return wxFONTSTYLE_NORMAL
; 
 645     switch ( s
[0].GetValue() ) 
 648             // again, unknown but consider normal by default 
 651             return wxFONTSTYLE_NORMAL
; 
 654             return wxFONTSTYLE_ITALIC
; 
 657             return wxFONTSTYLE_SLANT
; 
 661 wxFontWeight 
wxNativeFontInfo::GetWeight() const 
 663     const wxString s 
= GetXFontComponent(wxXLFD_WEIGHT
).MakeLower(); 
 664     if ( s
.find(_T("bold")) != wxString::npos 
|| s 
== _T("black") ) 
 665         return wxFONTWEIGHT_BOLD
; 
 666     else if ( s 
== _T("light") ) 
 667         return wxFONTWEIGHT_LIGHT
; 
 669     return wxFONTWEIGHT_NORMAL
; 
 672 bool wxNativeFontInfo::GetUnderlined() const 
 674     // X fonts are never underlined 
 678 wxString 
wxNativeFontInfo::GetFaceName() const 
 680     // wxWidgets facename probably more accurately corresponds to X family 
 681     return GetXFontComponent(wxXLFD_FAMILY
); 
 684 wxFontFamily 
wxNativeFontInfo::GetFamily() const 
 686     // and wxWidgets family -- to X foundry, but we have to translate it to 
 687     // wxFontFamily somehow... 
 688     wxFAIL_MSG(_T("not implemented")); // GetXFontComponent(wxXLFD_FOUNDRY); 
 690     return wxFONTFAMILY_DEFAULT
; 
 693 wxFontEncoding 
wxNativeFontInfo::GetEncoding() const 
 695     // we already have the code for this but need to refactor it first 
 696     wxFAIL_MSG( _T("not implemented") ); 
 698     return wxFONTENCODING_MAX
; 
 701 void wxNativeFontInfo::SetPointSize(int pointsize
) 
 703     SetXFontComponent(wxXLFD_POINTSIZE
, wxString::Format(_T("%d"), pointsize
)); 
 706 void wxNativeFontInfo::SetStyle(wxFontStyle style
) 
 711         case wxFONTSTYLE_ITALIC
: 
 715         case wxFONTSTYLE_SLANT
: 
 719         case wxFONTSTYLE_NORMAL
: 
 723             wxFAIL_MSG( _T("unknown wxFontStyle in wxNativeFontInfo::SetStyle") ); 
 727     SetXFontComponent(wxXLFD_SLANT
, s
); 
 730 void wxNativeFontInfo::SetWeight(wxFontWeight weight
) 
 735         case wxFONTWEIGHT_BOLD
: 
 739         case wxFONTWEIGHT_LIGHT
: 
 743         case wxFONTWEIGHT_NORMAL
: 
 748             wxFAIL_MSG( _T("unknown wxFontWeight in wxNativeFontInfo::SetWeight") ); 
 752     SetXFontComponent(wxXLFD_WEIGHT
, s
); 
 755 void wxNativeFontInfo::SetUnderlined(bool WXUNUSED(underlined
)) 
 757     // can't do this under X 
 760 bool wxNativeFontInfo::SetFaceName(const wxString
& facename
) 
 762     SetXFontComponent(wxXLFD_FAMILY
, facename
); 
 766 void wxNativeFontInfo::SetFamily(wxFontFamily 
WXUNUSED(family
)) 
 768     // wxFontFamily -> X foundry, anyone? 
 769     wxFAIL_MSG( _T("not implemented") ); 
 771     // SetXFontComponent(wxXLFD_FOUNDRY, ...); 
 774 void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding
) 
 776     wxNativeEncodingInfo info
; 
 777     if ( wxGetNativeFontEncoding(encoding
, &info
) ) 
 779         SetXFontComponent(wxXLFD_ENCODING
, info
.xencoding
); 
 780         SetXFontComponent(wxXLFD_REGISTRY
, info
.xregistry
); 
 784 // ---------------------------------------------------------------------------- 
 786 // ---------------------------------------------------------------------------- 
 788 bool wxGetNativeFontEncoding(wxFontEncoding encoding
, 
 789                              wxNativeEncodingInfo 
*info
) 
 791     wxCHECK_MSG( info
, false, _T("bad pointer in wxGetNativeFontEncoding") ); 
 793     if ( encoding 
== wxFONTENCODING_DEFAULT 
) 
 795         encoding 
= wxFont::GetDefaultEncoding(); 
 800         case wxFONTENCODING_ISO8859_1
: 
 801         case wxFONTENCODING_ISO8859_2
: 
 802         case wxFONTENCODING_ISO8859_3
: 
 803         case wxFONTENCODING_ISO8859_4
: 
 804         case wxFONTENCODING_ISO8859_5
: 
 805         case wxFONTENCODING_ISO8859_6
: 
 806         case wxFONTENCODING_ISO8859_7
: 
 807         case wxFONTENCODING_ISO8859_8
: 
 808         case wxFONTENCODING_ISO8859_9
: 
 809         case wxFONTENCODING_ISO8859_10
: 
 810         case wxFONTENCODING_ISO8859_11
: 
 811         case wxFONTENCODING_ISO8859_12
: 
 812         case wxFONTENCODING_ISO8859_13
: 
 813         case wxFONTENCODING_ISO8859_14
: 
 814         case wxFONTENCODING_ISO8859_15
: 
 816                 int cp 
= encoding 
- wxFONTENCODING_ISO8859_1 
+ 1; 
 817                 info
->xregistry 
= wxT("iso8859"); 
 818                 info
->xencoding
.Printf(wxT("%d"), cp
); 
 822         case wxFONTENCODING_UTF8
: 
 823             info
->xregistry 
= wxT("iso10646"); 
 824             info
->xencoding 
= wxT("*"); 
 827         case wxFONTENCODING_GB2312
: 
 828             info
->xregistry 
= wxT("GB2312");   // or the otherway round? 
 829             info
->xencoding 
= wxT("*"); 
 832         case wxFONTENCODING_KOI8
: 
 833         case wxFONTENCODING_KOI8_U
: 
 834             info
->xregistry 
= wxT("koi8"); 
 836             // we don't make distinction between koi8-r, koi8-u and koi8-ru (so far) 
 837             info
->xencoding 
= wxT("*"); 
 840         case wxFONTENCODING_CP1250
: 
 841         case wxFONTENCODING_CP1251
: 
 842         case wxFONTENCODING_CP1252
: 
 843         case wxFONTENCODING_CP1253
: 
 844         case wxFONTENCODING_CP1254
: 
 845         case wxFONTENCODING_CP1255
: 
 846         case wxFONTENCODING_CP1256
: 
 847         case wxFONTENCODING_CP1257
: 
 849                 int cp 
= encoding 
- wxFONTENCODING_CP1250 
+ 1250; 
 850                 info
->xregistry 
= wxT("microsoft"); 
 851                 info
->xencoding
.Printf(wxT("cp%d"), cp
); 
 855         case wxFONTENCODING_EUC_JP
: 
 856         case wxFONTENCODING_SHIFT_JIS
: 
 857             info
->xregistry 
= "jis*"; 
 858             info
->xencoding 
= "*"; 
 861         case wxFONTENCODING_SYSTEM
: 
 863             info
->xencoding 
= wxT("*"); 
 867             // don't know how to translate this encoding into X fontspec 
 871     info
->encoding 
= encoding
; 
 876 bool wxTestFontEncoding(const wxNativeEncodingInfo
& info
) 
 879     fontspec
.Printf(_T("-*-%s-*-*-*-*-*-*-*-*-*-*-%s-%s"), 
 880                     !info
.facename 
? _T("*") : info
.facename
.c_str(), 
 881                     info
.xregistry
.c_str(), 
 882                     info
.xencoding
.c_str()); 
 884     return wxTestFontSpec(fontspec
); 
 887 // ---------------------------------------------------------------------------- 
 888 // X-specific functions 
 889 // ---------------------------------------------------------------------------- 
 891 wxNativeFont 
wxLoadQueryNearestFont(int pointSize
, 
 896                                     const wxString 
&facename
, 
 897                                     wxFontEncoding encoding
, 
 900     if ( encoding 
== wxFONTENCODING_DEFAULT 
) 
 902         encoding 
= wxFont::GetDefaultEncoding(); 
 905     // first determine the encoding - if the font doesn't exist at all in this 
 906     // encoding, it's useless to do all other approximations (i.e. size, 
 907     // family &c don't matter much) 
 908     wxNativeEncodingInfo info
; 
 909     if ( encoding 
== wxFONTENCODING_SYSTEM 
) 
 911         // This will always work so we don't test to save time 
 912         wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM
, &info
); 
 916         if ( !wxGetNativeFontEncoding(encoding
, &info
) || 
 917              !wxTestFontEncoding(info
) ) 
 920             if ( !wxFontMapper::Get()->GetAltForEncoding(encoding
, &info
) ) 
 921 #endif // wxUSE_FONTMAP 
 923                 // unspported encoding - replace it with the default 
 925                 // NB: we can't just return 0 from here because wxGTK code doesn't 
 926                 //     check for it (i.e. it supposes that we'll always succeed), 
 927                 //     so it would provoke a crash 
 928                 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM
, &info
); 
 933     // OK, we have the correct xregistry/xencoding in info structure 
 934     wxNativeFont font 
= 0; 
 936     // if we already have the X font name, try to use it 
 937     if( xFontName 
&& !xFontName
->empty() ) 
 940         //  Make sure point size is correct for scale factor. 
 942         wxStringTokenizer 
tokenizer(*xFontName
, _T("-"), wxTOKEN_RET_DELIMS
); 
 943         wxString newFontName
; 
 945         for(int i 
= 0; i 
< 8; i
++) 
 946           newFontName 
+= tokenizer
.NextToken(); 
 948         (void) tokenizer
.NextToken(); 
 950         newFontName 
+= wxString::Format(wxT("%d-"), pointSize
); 
 952         while(tokenizer
.HasMoreTokens()) 
 953           newFontName 
+= tokenizer
.GetNextToken(); 
 955         font 
= wxLoadFont(newFontName
); 
 958           *xFontName 
= newFontName
; 
 963         // search up and down by stepsize 10 
 964         int max_size 
= pointSize 
+ 20 * (1 + (pointSize
/180)); 
 965         int min_size 
= pointSize 
- 20 * (1 + (pointSize
/180)); 
 967         int i
, round
; // counters 
 969         // first round: search for equal, then for smaller and for larger size with the given weight and style 
 970         int testweight 
= weight
; 
 971         int teststyle 
= style
; 
 973         for ( round 
= 0; round 
< 3; round
++ ) 
 975             // second round: use normal weight 
 978                 if ( testweight 
!= wxNORMAL 
) 
 980                     testweight 
= wxNORMAL
; 
 984                     ++round
; // fall through to third round 
 988             // third round: ... and use normal style 
 991                 if ( teststyle 
!= wxNORMAL 
) 
 993                     teststyle 
= wxNORMAL
; 
1000             // Search for equal or smaller size (approx.) 
1001             for ( i 
= pointSize
; !font 
&& i 
>= 10 && i 
>= min_size
; i 
-= 10 ) 
1003                 font 
= wxLoadQueryFont(i
, family
, teststyle
, testweight
, underlined
, 
1004                                    facename
, info
.xregistry
, info
.xencoding
, 
1008             // Search for larger size (approx.) 
1009             for ( i 
= pointSize 
+ 10; !font 
&& i 
<= max_size
; i 
+= 10 ) 
1011                 font 
= wxLoadQueryFont(i
, family
, teststyle
, testweight
, underlined
, 
1012                                    facename
, info
.xregistry
, info
.xencoding
, 
1017         // Try default family 
1018         if ( !font 
&& family 
!= wxDEFAULT 
) 
1020             font 
= wxLoadQueryFont(pointSize
, wxDEFAULT
, style
, weight
, 
1021                                    underlined
, facename
, 
1022                                    info
.xregistry
, info
.xencoding
, 
1026         // ignore size, family, style and weight but try to find font with the 
1027         // given facename and encoding 
1030             font 
= wxLoadQueryFont(120, wxDEFAULT
, wxNORMAL
, wxNORMAL
, 
1031                                    underlined
, facename
, 
1032                                    info
.xregistry
, info
.xencoding
, 
1035             // ignore family as well 
1038                 font 
= wxLoadQueryFont(120, wxDEFAULT
, wxNORMAL
, wxNORMAL
, 
1039                                        underlined
, wxEmptyString
, 
1040                                        info
.xregistry
, info
.xencoding
, 
1043                 // if it still failed, try to get the font of any size but 
1044                 // with the requested encoding: this can happen if the 
1045                 // encoding is only available in one size which happens to be 
1046                 // different from 120 
1049                     font 
= wxLoadQueryFont(-1, wxDEFAULT
, wxNORMAL
, wxNORMAL
, 
1050                                            false, wxEmptyString
, 
1051                                            info
.xregistry
, info
.xencoding
, 
1054                     // this should never happen as we had tested for it in the 
1055                     // very beginning, but if it does, do return something non 
1056                     // NULL or we'd crash in wxFont code 
1059                         wxFAIL_MSG( _T("this encoding should be available!") ); 
1061                         font 
= wxLoadQueryFont(-1, 
1062                                                wxDEFAULT
, wxNORMAL
, wxNORMAL
, 
1063                                                false, wxEmptyString
, 
1075 // ---------------------------------------------------------------------------- 
1076 // private functions 
1077 // ---------------------------------------------------------------------------- 
1079 // returns true if there are any fonts matching this font spec 
1080 static bool wxTestFontSpec(const wxString
& fontspec
) 
1082     // some X servers will fail to load this font because there are too many 
1083     // matches so we must test explicitly for this 
1084     if ( fontspec 
== _T("-*-*-*-*-*-*-*-*-*-*-*-*-*-*") ) 
1089     wxNativeFont test 
= (wxNativeFont
) g_fontHash
->Get( fontspec 
); 
1095     test 
= wxLoadFont(fontspec
); 
1096     g_fontHash
->Put( fontspec
, (wxObject
*) test 
); 
1110 static wxNativeFont 
wxLoadQueryFont(int pointSize
, 
1114                                     bool WXUNUSED(underlined
), 
1115                                     const wxString
& facename
, 
1116                                     const wxString
& xregistry
, 
1117                                     const wxString
& xencoding
, 
1118                                     wxString
* xFontName
) 
1123         case wxDECORATIVE
: xfamily 
= wxT("lucida"); break; 
1124         case wxROMAN
:      xfamily 
= wxT("times");  break; 
1125         case wxMODERN
:     xfamily 
= wxT("courier"); break; 
1126         case wxSWISS
:      xfamily 
= wxT("helvetica"); break; 
1127         case wxTELETYPE
:   xfamily 
= wxT("lucidatypewriter"); break; 
1128         case wxSCRIPT
:     xfamily 
= wxT("utopia"); break; 
1129         default:           xfamily 
= wxT("*"); 
1137                  xweight 
= MWLF_WEIGHT_BOLD
; 
1142                  xweight 
= MWLF_WEIGHT_LIGHT
; 
1147                  xweight 
= MWLF_WEIGHT_NORMAL
; 
1153                  xweight 
= MWLF_WEIGHT_DEFAULT
; 
1157     GR_SCREEN_INFO screenInfo
; 
1158     GrGetScreenInfo(& screenInfo
); 
1160     int yPixelsPerCM 
= screenInfo
.ydpcm
; 
1162     // A point is 1/72 of an inch. 
1163     // An inch is 2.541 cm. 
1164     // So pixelHeight = (pointSize / 72) (inches) * 2.541 (for cm) * yPixelsPerCM (for pixels) 
1165     // In fact pointSize is 10 * the normal point size so 
1168     int pixelHeight 
= (int) ( (((float)pointSize
) / 720.0) * 2.541 * (float) yPixelsPerCM
) ; 
1170     // An alternative: assume that the screen is 72 dpi. 
1171     //int pixelHeight = (int) (((float)pointSize / 720.0) * 72.0) ; 
1172     //int pixelHeight = (int) ((float)pointSize / 10.0) ; 
1175     logFont
.lfHeight 
= pixelHeight
; 
1176     logFont
.lfWidth 
= 0; 
1177     logFont
.lfEscapement 
= 0; 
1178     logFont
.lfOrientation 
= 0; 
1179     logFont
.lfWeight 
= xweight
; 
1180     logFont
.lfItalic 
= (style 
== wxNORMAL 
? 0 : 1) ; 
1181     logFont
.lfUnderline 
= 0; 
1182     logFont
.lfStrikeOut 
= 0; 
1183     logFont
.lfCharSet 
= MWLF_CHARSET_DEFAULT
; // TODO: select appropriate one 
1184     logFont
.lfOutPrecision 
= MWLF_TYPE_DEFAULT
; 
1185     logFont
.lfClipPrecision 
= 0; // Not used 
1186     logFont
.lfRoman 
= (family 
== wxROMAN 
? 1 : 0) ; 
1187     logFont
.lfSerif 
= (family 
== wxSWISS 
? 0 : 1) ; 
1188     logFont
.lfSansSerif 
= !logFont
.lfSerif 
; 
1189     logFont
.lfModern 
= (family 
== wxMODERN 
? 1 : 0) ; 
1190     logFont
.lfProportional 
= (family 
== wxTELETYPE 
? 0 : 1) ; 
1191     logFont
.lfOblique 
= 0; 
1192     logFont
.lfSmallCaps 
= 0; 
1193     logFont
.lfPitch 
= 0; // 0 = default 
1194     strcpy(logFont
.lfFaceName
, facename
.c_str()); 
1196     XFontStruct
* fontInfo 
= (XFontStruct
*) malloc(sizeof(XFontStruct
)); 
1197     fontInfo
->fid 
= GrCreateFont((GR_CHAR
*) facename
.c_str(), pixelHeight
, & logFont
); 
1198     GrGetFontInfo(fontInfo
->fid
, & fontInfo
->info
); 
1199     return (wxNativeFont
) fontInfo
; 
1203     if (!facename
.empty()) 
1205         fontSpec
.Printf(wxT("-*-%s-*-*-normal-*-*-*-*-*-*-*-*-*"), 
1208         if ( wxTestFontSpec(fontSpec
) ) 
1212         //else: no such family, use default one instead 
1219             fontSpec
.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"), 
1221             if ( wxTestFontSpec(fontSpec
) ) 
1226             // fall through - try wxITALIC now 
1229             fontSpec
.Printf(wxT("-*-%s-*-i-*-*-*-*-*-*-*-*-*-*"), 
1231             if ( wxTestFontSpec(fontSpec
) ) 
1235             else if ( style 
== wxITALIC 
) // and not wxSLANT 
1238                 fontSpec
.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"), 
1240                 if ( wxTestFontSpec(fontSpec
) ) 
1246                     // no italic, no slant - leave default 
1253             wxFAIL_MSG(_T("unknown font style")); 
1254             // fall back to normal 
1266                   fontSpec
.Printf(wxT("-*-%s-bold-*-*-*-*-*-*-*-*-*-*-*"), 
1268                   if ( wxTestFontSpec(fontSpec
) ) 
1270                        xweight 
= wxT("bold"); 
1273                   fontSpec
.Printf(wxT("-*-%s-heavy-*-*-*-*-*-*-*-*-*-*-*"), 
1275                   if ( wxTestFontSpec(fontSpec
) ) 
1277                        xweight 
= wxT("heavy"); 
1280                   fontSpec
.Printf(wxT("-*-%s-extrabold-*-*-*-*-*-*-*-*-*-*-*"), 
1282                   if ( wxTestFontSpec(fontSpec
) ) 
1284                       xweight 
= wxT("extrabold"); 
1287                   fontSpec
.Printf(wxT("-*-%s-demibold-*-*-*-*-*-*-*-*-*-*-*"), 
1289                   if ( wxTestFontSpec(fontSpec
) ) 
1291                       xweight 
= wxT("demibold"); 
1294                   fontSpec
.Printf(wxT("-*-%s-black-*-*-*-*-*-*-*-*-*-*-*"), 
1296                   if ( wxTestFontSpec(fontSpec
) ) 
1298                       xweight 
= wxT("black"); 
1301                   fontSpec
.Printf(wxT("-*-%s-ultrablack-*-*-*-*-*-*-*-*-*-*-*"), 
1303                   if ( wxTestFontSpec(fontSpec
) ) 
1305                       xweight 
= wxT("ultrablack"); 
1312                   fontSpec
.Printf(wxT("-*-%s-light-*-*-*-*-*-*-*-*-*-*-*"), 
1314                   if ( wxTestFontSpec(fontSpec
) ) 
1316                        xweight 
= wxT("light"); 
1319                   fontSpec
.Printf(wxT("-*-%s-thin-*-*-*-*-*-*-*-*-*-*-*"), 
1321                   if ( wxTestFontSpec(fontSpec
) ) 
1323                        xweight 
= wxT("thin"); 
1330                   fontSpec
.Printf(wxT("-*-%s-medium-*-*-*-*-*-*-*-*-*-*-*"), 
1332                   if ( wxTestFontSpec(fontSpec
) ) 
1334                        xweight 
= wxT("medium"); 
1337                   fontSpec
.Printf(wxT("-*-%s-normal-*-*-*-*-*-*-*-*-*-*-*"), 
1339                   if ( wxTestFontSpec(fontSpec
) ) 
1341                        xweight 
= wxT("normal"); 
1344                   fontSpec
.Printf(wxT("-*-%s-regular-*-*-*-*-*-*-*-*-*-*-*"), 
1346                   if ( wxTestFontSpec(fontSpec
) ) 
1348                       xweight 
= wxT("regular"); 
1354         default:           xweight 
= wxT("*"); break; 
1357     // if pointSize is -1, don't specify any 
1359     if ( pointSize 
== -1 ) 
1365         sizeSpec
.Printf(_T("%d"), pointSize
); 
1368     // construct the X font spec from our data 
1369     fontSpec
.Printf(wxT("-*-%s-%s-%s-normal-*-*-%s-*-*-*-*-%s-%s"), 
1370                     xfamily
.c_str(), xweight
.c_str(), xstyle
.c_str(), 
1371                     sizeSpec
.c_str(), xregistry
.c_str(), xencoding
.c_str()); 
1374         *xFontName 
= fontSpec
; 
1376     return wxLoadFont(fontSpec
); 
1381 // ---------------------------------------------------------------------------- 
1383 // ---------------------------------------------------------------------------- 
1385 class wxFontModule 
: public wxModule
 
1392     DECLARE_DYNAMIC_CLASS(wxFontModule
) 
1395 IMPLEMENT_DYNAMIC_CLASS(wxFontModule
, wxModule
) 
1397 bool wxFontModule::OnInit() 
1399     g_fontHash 
= new wxHashTable( wxKEY_STRING 
); 
1404 void wxFontModule::OnExit() 
1408     g_fontHash 
= (wxHashTable 
*)NULL
; 
1411 #endif // GTK 2.0/1.x