1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/unix/fontutil.cpp 
   3 // Purpose:     Font helper functions for wxX11, wxGTK, wxMotif 
   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) s.utf8_str() 
  57     #define wxPANGO_CONV_BACK(s) wxString::FromUTF8Unchecked(s) 
  60 // ---------------------------------------------------------------------------- 
  62 // ---------------------------------------------------------------------------- 
  64 void wxNativeFontInfo::Init() 
  69 void wxNativeFontInfo::Init(const wxNativeFontInfo
& info
) 
  72         description 
= pango_font_description_copy(info
.description
); 
  77 void wxNativeFontInfo::Free() 
  80         pango_font_description_free(description
); 
  83 int wxNativeFontInfo::GetPointSize() const 
  85     return pango_font_description_get_size( description 
) / PANGO_SCALE
; 
  88 wxFontStyle 
wxNativeFontInfo::GetStyle() const 
  90     wxFontStyle m_style 
= wxFONTSTYLE_NORMAL
; 
  92     switch (pango_font_description_get_style( description 
)) 
  94         case PANGO_STYLE_NORMAL
: 
  95             m_style 
= wxFONTSTYLE_NORMAL
; 
  97         case PANGO_STYLE_ITALIC
: 
  98             m_style 
= wxFONTSTYLE_ITALIC
; 
 100         case PANGO_STYLE_OBLIQUE
: 
 101             m_style 
= wxFONTSTYLE_SLANT
; 
 108 wxFontWeight 
wxNativeFontInfo::GetWeight() const 
 110     // We seem to currently initialize only by string. 
 111     // In that case PANGO_FONT_MASK_WEIGHT is always set. 
 112     // if (!(pango_font_description_get_set_fields(description) & PANGO_FONT_MASK_WEIGHT)) 
 113     //    return wxFONTWEIGHT_NORMAL; 
 115     PangoWeight pango_weight 
= pango_font_description_get_weight( description 
); 
 117     // Until the API can be changed the following ranges of weight values are used: 
 118     // wxFONTWEIGHT_LIGHT:  100 .. 349 - range of 250 
 119     // wxFONTWEIGHT_NORMAL: 350 .. 599 - range of 250 
 120     // wxFONTWEIGHT_BOLD:   600 .. 900 - range of 301 (600 is "semibold" already) 
 122     if (pango_weight 
>= 600) 
 123         return wxFONTWEIGHT_BOLD
; 
 125     if (pango_weight 
< 350) 
 126         return wxFONTWEIGHT_LIGHT
; 
 128     return wxFONTWEIGHT_NORMAL
; 
 131 bool wxNativeFontInfo::GetUnderlined() const 
 136 wxString 
wxNativeFontInfo::GetFaceName() const 
 138     // the Pango "family" is the wx "face name" 
 139     return wxPANGO_CONV_BACK(pango_font_description_get_family(description
)); 
 142 wxFontFamily 
wxNativeFontInfo::GetFamily() const 
 144     wxFontFamily ret 
= wxFONTFAMILY_UNKNOWN
; 
 146     const char *family_name 
= pango_font_description_get_family( description 
); 
 148     // note: not passing -1 as the 2nd parameter to g_ascii_strdown to work 
 149     // around a bug in the 64-bit glib shipped with solaris 10, -1 causes it 
 150     // to try to allocate 2^32 bytes. 
 153     wxGtkString 
family_text(g_ascii_strdown(family_name
, strlen(family_name
))); 
 155     // Check for some common fonts, to salvage what we can from the current 
 156     // win32 centric wxFont API: 
 157     if (strncasecmp( family_text
, "monospace", 9 ) == 0) 
 158         ret 
= wxFONTFAMILY_TELETYPE
;    // begins with "Monospace" 
 159     else if (strncasecmp( 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
] ), 
 181                                    pango_font_description_get_family( description 
)) == 0 ) 
 183                 family 
= families
[i
]; 
 190         // Some gtk+ systems might query for a non-existing font from 
 191         // wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) on initialization, 
 192         // don't assert until wxSystemSettings::GetFont is checked for this - MR 
 193         // wxASSERT_MSG( family, "No appropriate PangoFontFamily found for ::description" ); 
 195         if (family 
!= NULL 
&& pango_font_family_is_monospace( family 
)) 
 196             ret 
= wxFONTFAMILY_TELETYPE
; // is deemed a monospace font by pango 
 198 #endif // GTK+ 2 || HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE 
 200     if (ret 
== wxFONTFAMILY_UNKNOWN
) 
 202         if (strstr( family_text
, "sans" ) != NULL 
|| strstr( family_text
, "Sans" ) != NULL
) 
 203             // 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 
|| strstr( family_text
, "Serif" ) != NULL
) 
 206             ret 
= wxFONTFAMILY_ROMAN
;       // contains "Serif" 
 207         else if (strncasecmp( family_text
, "times", 5 ) == 0) 
 208             ret 
= wxFONTFAMILY_ROMAN
;       // begins with "Times" 
 209         else if (strncasecmp( 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
; 
 221 void wxNativeFontInfo::SetPointSize(int pointsize
) 
 223     pango_font_description_set_size( description
, pointsize 
* PANGO_SCALE 
); 
 226 void wxNativeFontInfo::SetStyle(wxFontStyle style
) 
 230         case wxFONTSTYLE_ITALIC
: 
 231             pango_font_description_set_style( description
, PANGO_STYLE_ITALIC 
); 
 233         case wxFONTSTYLE_SLANT
: 
 234             pango_font_description_set_style( description
, PANGO_STYLE_OBLIQUE 
); 
 237             wxFAIL_MSG( "unknown font style" ); 
 239         case wxFONTSTYLE_NORMAL
: 
 240             pango_font_description_set_style( description
, PANGO_STYLE_NORMAL 
); 
 245 void wxNativeFontInfo::SetWeight(wxFontWeight weight
) 
 249         case wxFONTWEIGHT_BOLD
: 
 250             pango_font_description_set_weight(description
, PANGO_WEIGHT_BOLD
); 
 252         case wxFONTWEIGHT_LIGHT
: 
 253             pango_font_description_set_weight(description
, PANGO_WEIGHT_LIGHT
); 
 256             wxFAIL_MSG( "unknown font weight" ); 
 258         case wxFONTWEIGHT_NORMAL
: 
 259             pango_font_description_set_weight(description
, PANGO_WEIGHT_NORMAL
); 
 263 void wxNativeFontInfo::SetUnderlined(bool WXUNUSED(underlined
)) 
 265     // wxWindowDCImpl::DoDrawText will take care of rendering font with 
 266     // the underline attribute! 
 267     wxFAIL_MSG( "not implemented" ); 
 270 bool wxNativeFontInfo::SetFaceName(const wxString
& facename
) 
 272     pango_font_description_set_family(description
, wxPANGO_CONV(facename
)); 
 274     // we return true because Pango doesn't tell us if the call failed or not; 
 275     // instead on wxGTK wxFont::SetFaceName() will call wxFontBase::SetFaceName() 
 276     // which does the check 
 280 void wxNativeFontInfo::SetFamily(wxFontFamily family
) 
 282     wxArrayString facename
; 
 284     // the list of fonts associated with a family was partially 
 285     // taken from http://www.codestyle.org/css/font-family 
 289         case wxFONTFAMILY_SCRIPT
: 
 290             // corresponds to the cursive font family in the page linked above 
 291             facename
.Add(wxS("URW Chancery L")); 
 292             facename
.Add(wxS("Comic Sans MS")); 
 295         case wxFONTFAMILY_DECORATIVE
: 
 296             // corresponds to the fantasy font family in the page linked above 
 297             facename
.Add(wxS("Impact")); 
 300         case wxFONTFAMILY_ROMAN
: 
 301             // corresponds to the serif font family in the page linked above 
 302             facename
.Add(wxS("Century Schoolbook L")); 
 303             facename
.Add(wxS("URW Bookman L")); 
 304             facename
.Add(wxS("URW Palladio L")); 
 305             facename
.Add(wxS("DejaVu Serif")); 
 306             facename
.Add(wxS("FreeSerif")); 
 307             facename
.Add(wxS("Times New Roman")); 
 308             facename
.Add(wxS("Times")); 
 311         case wxFONTFAMILY_TELETYPE
: 
 312         case wxFONTFAMILY_MODERN
: 
 313             // corresponds to the monospace font family in the page linked above 
 314             facename
.Add(wxS("DejaVu Sans Mono")); 
 315             facename
.Add(wxS("Nimbus Mono L")); 
 316             facename
.Add(wxS("Bitstream Vera Sans Mono")); 
 317             facename
.Add(wxS("Andale Mono")); 
 318             facename
.Add(wxS("Lucida Sans Typewriter")); 
 319             facename
.Add(wxS("FreeMono")); 
 320             facename
.Add(wxS("Courier New")); 
 321             facename
.Add(wxS("Courier")); 
 324         case wxFONTFAMILY_SWISS
: 
 325         case wxFONTFAMILY_DEFAULT
: 
 327             // corresponds to the sans-serif font family in the page linked above 
 328             facename
.Add(wxS("DejaVu Sans")); 
 329             facename
.Add(wxS("URW Gothic L")); 
 330             facename
.Add(wxS("Nimbus Sans L")); 
 331             facename
.Add(wxS("Bitstream Vera Sans")); 
 332             facename
.Add(wxS("Lucida Sans")); 
 333             facename
.Add(wxS("Arial")); 
 334             facename
.Add(wxS("FreeSans")); 
 338     SetFaceName(facename
); 
 341 void wxNativeFontInfo::SetEncoding(wxFontEncoding 
WXUNUSED(encoding
)) 
 343     wxFAIL_MSG( "not implemented: Pango encoding is always UTF8" ); 
 346 bool wxNativeFontInfo::FromString(const wxString
& s
) 
 349         pango_font_description_free( description 
); 
 351     // there is a bug in at least pango <= 1.13 which makes it (or its backends) 
 352     // segfault for very big point sizes and for negative point sizes. 
 353     // To workaround that bug for pango <= 1.13 
 354     // (see http://bugzilla.gnome.org/show_bug.cgi?id=340229) 
 355     // we do the check on the size here using same (arbitrary) limits used by 
 356     // pango > 1.13. Note that the segfault could happen also for pointsize 
 357     // smaller than this limit !! 
 359     const size_t pos 
= str
.find_last_of(wxS(" ")); 
 361     if ( pos 
!= wxString::npos 
&& wxString(str
, pos 
+ 1).ToDouble(&size
) ) 
 366         else if ( size 
>= 1E6 
) 
 367             sizeStr 
= wxS("1E6"); 
 369         if ( !sizeStr
.empty() ) 
 371             // replace the old size with the adjusted one 
 372             str 
= wxString(s
, 0, pos
) + sizeStr
; 
 376     description 
= pango_font_description_from_string(wxPANGO_CONV(str
)); 
 379     // ensure a valid facename is selected 
 380     if (!wxFontEnumerator::IsValidFacename(GetFaceName())) 
 381         SetFaceName(wxNORMAL_FONT
->GetFaceName()); 
 382 #endif // wxUSE_FONTENUM 
 387 wxString 
wxNativeFontInfo::ToString() const 
 389     wxGtkString 
str(pango_font_description_to_string( description 
)); 
 391     return wxPANGO_CONV_BACK(str
); 
 394 bool wxNativeFontInfo::FromUserString(const wxString
& s
) 
 396     return FromString( s 
); 
 399 wxString 
wxNativeFontInfo::ToUserString() const 
 408         #pragma message disable nosimpint 
 411     #include <X11/Xlib.h> 
 414         #pragma message enable nosimpint 
 417 #elif defined(__WXGTK__) 
 418     // we have to declare struct tm to avoid problems with first forward 
 419     // declaring it in C code (glib.h included from gdk.h does it) and then 
 420     // defining it when time.h is included from the headers below - this is 
 421     // known not to work at least with Sun CC 6.01 
 428 // ---------------------------------------------------------------------------- 
 430 // ---------------------------------------------------------------------------- 
 432 static wxHashTable 
*g_fontHash 
= NULL
; 
 434 // ---------------------------------------------------------------------------- 
 436 // ---------------------------------------------------------------------------- 
 438 // define the functions to create and destroy native fonts for this toolkit 
 440     wxNativeFont 
wxLoadFont(const wxString
& fontSpec
) 
 442         return XLoadQueryFont((Display 
*)wxGetDisplay(), fontSpec
); 
 445     inline void wxFreeFont(wxNativeFont font
) 
 447         XFreeFont((Display 
*)wxGetDisplay(), (XFontStruct 
*)font
); 
 449 #elif defined(__WXGTK__) 
 450     wxNativeFont 
wxLoadFont(const wxString
& fontSpec
) 
 452         // VZ: we should use gdk_fontset_load() instead of gdk_font_load() 
 453         //     here to be able to display Japanese fonts correctly (at least 
 454         //     this is what people report) but unfortunately doing it results 
 455         //     in tons of warnings when using GTK with "normal" European 
 456         //     languages and so we can't always do it and I don't know enough 
 457         //     to determine when should this be done... (FIXME) 
 458         return gdk_font_load( wxConvertWX2MB(fontSpec
) ); 
 461     inline void wxFreeFont(wxNativeFont font
) 
 463         gdk_font_unref(font
); 
 466     #error "Unknown GUI toolkit" 
 469 static bool wxTestFontSpec(const wxString
& fontspec
); 
 471 static wxNativeFont 
wxLoadQueryFont(int pointSize
, 
 476                                     const wxString
& facename
, 
 477                                     const wxString
& xregistry
, 
 478                                     const wxString
& xencoding
, 
 479                                     wxString
* xFontName
); 
 481 // ============================================================================ 
 483 // ============================================================================ 
 485 // ---------------------------------------------------------------------------- 
 486 // wxNativeEncodingInfo 
 487 // ---------------------------------------------------------------------------- 
 489 // convert to/from the string representation: format is 
 490 //      encodingid;registry;encoding[;facename] 
 491 bool wxNativeEncodingInfo::FromString(const wxString
& s
) 
 493     // use ";", not "-" because it may be part of encoding name 
 494     wxStringTokenizer 
tokenizer(s
, wxT(";")); 
 496     wxString encid 
= tokenizer
.GetNextToken(); 
 498     if ( !encid
.ToLong(&enc
) ) 
 500     encoding 
= (wxFontEncoding
)enc
; 
 502     xregistry 
= tokenizer
.GetNextToken(); 
 506     xencoding 
= tokenizer
.GetNextToken(); 
 511     facename 
= tokenizer
.GetNextToken(); 
 516 wxString 
wxNativeEncodingInfo::ToString() const 
 519     s 
<< (long)encoding 
<< wxT(';') << xregistry 
<< wxT(';') << xencoding
; 
 520     if ( !facename
.empty() ) 
 522         s 
<< wxT(';') << facename
; 
 528 // ---------------------------------------------------------------------------- 
 530 // ---------------------------------------------------------------------------- 
 532 void wxNativeFontInfo::Init() 
 537 bool wxNativeFontInfo::FromString(const wxString
& s
) 
 539     wxStringTokenizer 
tokenizer(s
, wxT(";")); 
 542     wxString token 
= tokenizer
.GetNextToken(); 
 543     if ( token 
!= wxT('0') ) 
 546     xFontName 
= tokenizer
.GetNextToken(); 
 548     // this should be the end 
 549     if ( tokenizer
.HasMoreTokens() ) 
 552     return FromXFontName(xFontName
); 
 555 wxString 
wxNativeFontInfo::ToString() const 
 558     return wxString::Format(wxT("%d;%s"), 0, GetXFontName().c_str()); 
 561 bool wxNativeFontInfo::FromUserString(const wxString
& s
) 
 563     return FromXFontName(s
); 
 566 wxString 
wxNativeFontInfo::ToUserString() const 
 568     return GetXFontName(); 
 571 bool wxNativeFontInfo::HasElements() const 
 573     // we suppose that the foundry is never empty, so if it is it means that we 
 574     // had never parsed the XLFD 
 575     return !fontElements
[0].empty(); 
 578 wxString 
wxNativeFontInfo::GetXFontComponent(wxXLFDField field
) const 
 580     wxCHECK_MSG( field 
< wxXLFD_MAX
, wxEmptyString
, wxT("invalid XLFD field") ); 
 582     if ( !HasElements() ) 
 584         if ( !const_cast<wxNativeFontInfo 
*>(this)->FromXFontName(xFontName
) ) 
 585             return wxEmptyString
; 
 588     return fontElements
[field
]; 
 591 bool wxNativeFontInfo::FromXFontName(const wxString
& fontname
) 
 593     // TODO: we should be able to handle the font aliases here, but how? 
 594     wxStringTokenizer 
tokenizer(fontname
, wxT("-")); 
 596     // skip the leading, usually empty field (font name registry) 
 597     if ( !tokenizer
.HasMoreTokens() ) 
 600     (void)tokenizer
.GetNextToken(); 
 602     for ( size_t n 
= 0; n 
< WXSIZEOF(fontElements
); n
++ ) 
 604         if ( !tokenizer
.HasMoreTokens() ) 
 606             // not enough elements in the XLFD - or maybe an alias 
 610         wxString field 
= tokenizer
.GetNextToken(); 
 611         if ( !field
.empty() && field 
!= wxT('*') ) 
 613             // we're really initialized now 
 617         fontElements
[n
] = field
; 
 620     // this should be all 
 621     if ( tokenizer
.HasMoreTokens() ) 
 627 wxString 
wxNativeFontInfo::GetXFontName() const 
 629     if ( xFontName
.empty() ) 
 631         for ( size_t n 
= 0; n 
< WXSIZEOF(fontElements
); n
++ ) 
 633             // replace the non specified elements with '*' except for the 
 634             // additional style which is usually just omitted 
 635             wxString elt 
= fontElements
[n
]; 
 636             if ( elt
.empty() && n 
!= wxXLFD_ADDSTYLE 
) 
 641             const_cast<wxNativeFontInfo 
*>(this)->xFontName 
<< wxT('-') << elt
; 
 649 wxNativeFontInfo::SetXFontComponent(wxXLFDField field
, const wxString
& value
) 
 651     wxCHECK_RET( field 
< wxXLFD_MAX
, wxT("invalid XLFD field") ); 
 653     // this class should be initialized with a valid font spec first and only 
 654     // then the fields may be modified! 
 655     wxASSERT_MSG( !IsDefault(), wxT("can't modify an uninitialized XLFD") ); 
 657     if ( !HasElements() ) 
 659         if ( !const_cast<wxNativeFontInfo 
*>(this)->FromXFontName(xFontName
) ) 
 661             wxFAIL_MSG( wxT("can't set font element for invalid XLFD") ); 
 667     fontElements
[field
] = value
; 
 669     // invalidate the XFLD, it doesn't correspond to the font elements any more 
 673 void wxNativeFontInfo::SetXFontName(const wxString
& xFontName_
) 
 675     // invalidate the font elements, GetXFontComponent() will reparse the XLFD 
 676     fontElements
[0].clear(); 
 678     xFontName 
= xFontName_
; 
 683 int wxNativeFontInfo::GetPointSize() const 
 685     const wxString s 
= GetXFontComponent(wxXLFD_POINTSIZE
); 
 687     // return -1 to indicate that the size is unknown 
 689     return s
.ToLong(&l
) ? l 
: -1; 
 692 wxFontStyle 
wxNativeFontInfo::GetStyle() const 
 694     const wxString s 
= GetXFontComponent(wxXLFD_SLANT
); 
 696     if ( s
.length() != 1 ) 
 698         // it is really unknown but we don't have any way to return it from 
 700         return wxFONTSTYLE_NORMAL
; 
 703     switch ( s
[0].GetValue() ) 
 706             // again, unknown but consider normal by default 
 709             return wxFONTSTYLE_NORMAL
; 
 712             return wxFONTSTYLE_ITALIC
; 
 715             return wxFONTSTYLE_SLANT
; 
 719 wxFontWeight 
wxNativeFontInfo::GetWeight() const 
 721     const wxString s 
= GetXFontComponent(wxXLFD_WEIGHT
).MakeLower(); 
 722     if ( s
.find(wxT("bold")) != wxString::npos 
|| s 
== wxT("black") ) 
 723         return wxFONTWEIGHT_BOLD
; 
 724     else if ( s 
== wxT("light") ) 
 725         return wxFONTWEIGHT_LIGHT
; 
 727     return wxFONTWEIGHT_NORMAL
; 
 730 bool wxNativeFontInfo::GetUnderlined() const 
 732     // X fonts are never underlined 
 736 wxString 
wxNativeFontInfo::GetFaceName() const 
 738     // wxWidgets facename probably more accurately corresponds to X family 
 739     return GetXFontComponent(wxXLFD_FAMILY
); 
 742 wxFontFamily 
wxNativeFontInfo::GetFamily() const 
 744     // and wxWidgets family -- to X foundry, but we have to translate it to 
 745     // wxFontFamily somehow... 
 746     wxFAIL_MSG(wxT("not implemented")); // GetXFontComponent(wxXLFD_FOUNDRY); 
 748     return wxFONTFAMILY_DEFAULT
; 
 751 wxFontEncoding 
wxNativeFontInfo::GetEncoding() const 
 753     // we already have the code for this but need to refactor it first 
 754     wxFAIL_MSG( wxT("not implemented") ); 
 756     return wxFONTENCODING_MAX
; 
 759 void wxNativeFontInfo::SetPointSize(int pointsize
) 
 761     SetXFontComponent(wxXLFD_POINTSIZE
, wxString::Format(wxT("%d"), pointsize
)); 
 764 void wxNativeFontInfo::SetStyle(wxFontStyle style
) 
 769         case wxFONTSTYLE_ITALIC
: 
 773         case wxFONTSTYLE_SLANT
: 
 777         case wxFONTSTYLE_NORMAL
: 
 781             wxFAIL_MSG( wxT("unknown wxFontStyle in wxNativeFontInfo::SetStyle") ); 
 785     SetXFontComponent(wxXLFD_SLANT
, s
); 
 788 void wxNativeFontInfo::SetWeight(wxFontWeight weight
) 
 793         case wxFONTWEIGHT_BOLD
: 
 797         case wxFONTWEIGHT_LIGHT
: 
 801         case wxFONTWEIGHT_NORMAL
: 
 806             wxFAIL_MSG( wxT("unknown wxFontWeight in wxNativeFontInfo::SetWeight") ); 
 810     SetXFontComponent(wxXLFD_WEIGHT
, s
); 
 813 void wxNativeFontInfo::SetUnderlined(bool WXUNUSED(underlined
)) 
 815     // can't do this under X 
 818 bool wxNativeFontInfo::SetFaceName(const wxString
& facename
) 
 820     SetXFontComponent(wxXLFD_FAMILY
, facename
); 
 824 void wxNativeFontInfo::SetFamily(wxFontFamily 
WXUNUSED(family
)) 
 826     // wxFontFamily -> X foundry, anyone? 
 827     wxFAIL_MSG( wxT("not implemented") ); 
 829     // SetXFontComponent(wxXLFD_FOUNDRY, ...); 
 832 void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding
) 
 834     wxNativeEncodingInfo info
; 
 835     if ( wxGetNativeFontEncoding(encoding
, &info
) ) 
 837         SetXFontComponent(wxXLFD_ENCODING
, info
.xencoding
); 
 838         SetXFontComponent(wxXLFD_REGISTRY
, info
.xregistry
); 
 842 // ---------------------------------------------------------------------------- 
 844 // ---------------------------------------------------------------------------- 
 846 bool wxGetNativeFontEncoding(wxFontEncoding encoding
, 
 847                              wxNativeEncodingInfo 
*info
) 
 849     wxCHECK_MSG( info
, false, wxT("bad pointer in wxGetNativeFontEncoding") ); 
 851     if ( encoding 
== wxFONTENCODING_DEFAULT 
) 
 853         encoding 
= wxFont::GetDefaultEncoding(); 
 858         case wxFONTENCODING_ISO8859_1
: 
 859         case wxFONTENCODING_ISO8859_2
: 
 860         case wxFONTENCODING_ISO8859_3
: 
 861         case wxFONTENCODING_ISO8859_4
: 
 862         case wxFONTENCODING_ISO8859_5
: 
 863         case wxFONTENCODING_ISO8859_6
: 
 864         case wxFONTENCODING_ISO8859_7
: 
 865         case wxFONTENCODING_ISO8859_8
: 
 866         case wxFONTENCODING_ISO8859_9
: 
 867         case wxFONTENCODING_ISO8859_10
: 
 868         case wxFONTENCODING_ISO8859_11
: 
 869         case wxFONTENCODING_ISO8859_12
: 
 870         case wxFONTENCODING_ISO8859_13
: 
 871         case wxFONTENCODING_ISO8859_14
: 
 872         case wxFONTENCODING_ISO8859_15
: 
 874                 int cp 
= encoding 
- wxFONTENCODING_ISO8859_1 
+ 1; 
 875                 info
->xregistry 
= wxT("iso8859"); 
 876                 info
->xencoding
.Printf(wxT("%d"), cp
); 
 880         case wxFONTENCODING_UTF8
: 
 881             info
->xregistry 
= wxT("iso10646"); 
 882             info
->xencoding 
= wxT("*"); 
 885         case wxFONTENCODING_GB2312
: 
 886             info
->xregistry 
= wxT("GB2312");   // or the otherway round? 
 887             info
->xencoding 
= wxT("*"); 
 890         case wxFONTENCODING_KOI8
: 
 891         case wxFONTENCODING_KOI8_U
: 
 892             info
->xregistry 
= wxT("koi8"); 
 894             // we don't make distinction between koi8-r, koi8-u and koi8-ru (so far) 
 895             info
->xencoding 
= wxT("*"); 
 898         case wxFONTENCODING_CP1250
: 
 899         case wxFONTENCODING_CP1251
: 
 900         case wxFONTENCODING_CP1252
: 
 901         case wxFONTENCODING_CP1253
: 
 902         case wxFONTENCODING_CP1254
: 
 903         case wxFONTENCODING_CP1255
: 
 904         case wxFONTENCODING_CP1256
: 
 905         case wxFONTENCODING_CP1257
: 
 907                 int cp 
= encoding 
- wxFONTENCODING_CP1250 
+ 1250; 
 908                 info
->xregistry 
= wxT("microsoft"); 
 909                 info
->xencoding
.Printf(wxT("cp%d"), cp
); 
 913         case wxFONTENCODING_EUC_JP
: 
 914         case wxFONTENCODING_SHIFT_JIS
: 
 915             info
->xregistry 
= "jis*"; 
 916             info
->xencoding 
= "*"; 
 919         case wxFONTENCODING_SYSTEM
: 
 921             info
->xencoding 
= wxT("*"); 
 925             // don't know how to translate this encoding into X fontspec 
 929     info
->encoding 
= encoding
; 
 934 bool wxTestFontEncoding(const wxNativeEncodingInfo
& info
) 
 937     fontspec
.Printf(wxT("-*-%s-*-*-*-*-*-*-*-*-*-*-%s-%s"), 
 938                     !info
.facename 
? wxT("*") : info
.facename
.c_str(), 
 939                     info
.xregistry
.c_str(), 
 940                     info
.xencoding
.c_str()); 
 942     return wxTestFontSpec(fontspec
); 
 945 // ---------------------------------------------------------------------------- 
 946 // X-specific functions 
 947 // ---------------------------------------------------------------------------- 
 949 wxNativeFont 
wxLoadQueryNearestFont(int pointSize
, 
 954                                     const wxString 
&facename
, 
 955                                     wxFontEncoding encoding
, 
 958     if ( encoding 
== wxFONTENCODING_DEFAULT 
) 
 960         encoding 
= wxFont::GetDefaultEncoding(); 
 963     // first determine the encoding - if the font doesn't exist at all in this 
 964     // encoding, it's useless to do all other approximations (i.e. size, 
 965     // family &c don't matter much) 
 966     wxNativeEncodingInfo info
; 
 967     if ( encoding 
== wxFONTENCODING_SYSTEM 
) 
 969         // This will always work so we don't test to save time 
 970         wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM
, &info
); 
 974         if ( !wxGetNativeFontEncoding(encoding
, &info
) || 
 975              !wxTestFontEncoding(info
) ) 
 978             if ( !wxFontMapper::Get()->GetAltForEncoding(encoding
, &info
) ) 
 979 #endif // wxUSE_FONTMAP 
 981                 // unspported encoding - replace it with the default 
 983                 // NB: we can't just return 0 from here because wxGTK code doesn't 
 984                 //     check for it (i.e. it supposes that we'll always succeed), 
 985                 //     so it would provoke a crash 
 986                 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM
, &info
); 
 991     // OK, we have the correct xregistry/xencoding in info structure 
 992     wxNativeFont font 
= 0; 
 994     // if we already have the X font name, try to use it 
 995     if( xFontName 
&& !xFontName
->empty() ) 
 998         //  Make sure point size is correct for scale factor. 
1000         wxStringTokenizer 
tokenizer(*xFontName
, wxT("-"), wxTOKEN_RET_DELIMS
); 
1001         wxString newFontName
; 
1003         for(int i 
= 0; i 
< 8; i
++) 
1004           newFontName 
+= tokenizer
.NextToken(); 
1006         (void) tokenizer
.NextToken(); 
1008         newFontName 
+= wxString::Format(wxT("%d-"), pointSize
); 
1010         while(tokenizer
.HasMoreTokens()) 
1011           newFontName 
+= tokenizer
.GetNextToken(); 
1013         font 
= wxLoadFont(newFontName
); 
1016           *xFontName 
= newFontName
; 
1021         // search up and down by stepsize 10 
1022         int max_size 
= pointSize 
+ 20 * (1 + (pointSize
/180)); 
1023         int min_size 
= pointSize 
- 20 * (1 + (pointSize
/180)); 
1025         int i
, round
; // counters 
1027         // first round: search for equal, then for smaller and for larger size 
1028         // with the given weight and style 
1029         int testweight 
= weight
; 
1030         int teststyle 
= style
; 
1032         for ( round 
= 0; round 
< 3; round
++ ) 
1034             // second round: use normal weight 
1037                 if ( testweight 
!= wxNORMAL 
) 
1039                     testweight 
= wxNORMAL
; 
1043                     ++round
; // fall through to third round 
1047             // third round: ... and use normal style 
1050                 if ( teststyle 
!= wxNORMAL 
) 
1052                     teststyle 
= wxNORMAL
; 
1059             // Search for equal or smaller size (approx.) 
1060             for ( i 
= pointSize
; !font 
&& i 
>= 10 && i 
>= min_size
; i 
-= 10 ) 
1062                 font 
= wxLoadQueryFont(i
, family
, teststyle
, testweight
, underlined
, 
1063                                    facename
, info
.xregistry
, info
.xencoding
, 
1067             // Search for larger size (approx.) 
1068             for ( i 
= pointSize 
+ 10; !font 
&& i 
<= max_size
; i 
+= 10 ) 
1070                 font 
= wxLoadQueryFont(i
, family
, teststyle
, testweight
, underlined
, 
1071                                    facename
, info
.xregistry
, info
.xencoding
, 
1076         // Try default family 
1077         if ( !font 
&& family 
!= wxDEFAULT 
) 
1079             font 
= wxLoadQueryFont(pointSize
, wxDEFAULT
, style
, weight
, 
1080                                    underlined
, facename
, 
1081                                    info
.xregistry
, info
.xencoding
, 
1085         // ignore size, family, style and weight but try to find font with the 
1086         // given facename and encoding 
1089             font 
= wxLoadQueryFont(120, wxDEFAULT
, wxNORMAL
, wxNORMAL
, 
1090                                    underlined
, facename
, 
1091                                    info
.xregistry
, info
.xencoding
, 
1094             // ignore family as well 
1097                 font 
= wxLoadQueryFont(120, wxDEFAULT
, wxNORMAL
, wxNORMAL
, 
1098                                        underlined
, wxEmptyString
, 
1099                                        info
.xregistry
, info
.xencoding
, 
1102                 // if it still failed, try to get the font of any size but 
1103                 // with the requested encoding: this can happen if the 
1104                 // encoding is only available in one size which happens to be 
1105                 // different from 120 
1108                     font 
= wxLoadQueryFont(-1, wxDEFAULT
, wxNORMAL
, wxNORMAL
, 
1109                                            false, wxEmptyString
, 
1110                                            info
.xregistry
, info
.xencoding
, 
1113                     // this should never happen as we had tested for it in the 
1114                     // very beginning, but if it does, do return something non 
1115                     // NULL or we'd crash in wxFont code 
1118                         wxFAIL_MSG( wxT("this encoding should be available!") ); 
1120                         font 
= wxLoadQueryFont(-1, 
1121                                                wxDEFAULT
, wxNORMAL
, wxNORMAL
, 
1122                                                false, wxEmptyString
, 
1134 // ---------------------------------------------------------------------------- 
1135 // private functions 
1136 // ---------------------------------------------------------------------------- 
1138 // returns true if there are any fonts matching this font spec 
1139 static bool wxTestFontSpec(const wxString
& fontspec
) 
1141     // some X servers will fail to load this font because there are too many 
1142     // matches so we must test explicitly for this 
1143     if ( fontspec 
== wxT("-*-*-*-*-*-*-*-*-*-*-*-*-*-*") ) 
1148     wxNativeFont test 
= (wxNativeFont
) g_fontHash
->Get( fontspec 
); 
1154     test 
= wxLoadFont(fontspec
); 
1155     g_fontHash
->Put( fontspec
, (wxObject
*) test 
); 
1169 static wxNativeFont 
wxLoadQueryFont(int pointSize
, 
1173                                     bool WXUNUSED(underlined
), 
1174                                     const wxString
& facename
, 
1175                                     const wxString
& xregistry
, 
1176                                     const wxString
& xencoding
, 
1177                                     wxString
* xFontName
) 
1182         case wxDECORATIVE
: xfamily 
= wxT("lucida"); break; 
1183         case wxROMAN
:      xfamily 
= wxT("times");  break; 
1184         case wxMODERN
:     xfamily 
= wxT("courier"); break; 
1185         case wxSWISS
:      xfamily 
= wxT("helvetica"); break; 
1186         case wxTELETYPE
:   xfamily 
= wxT("lucidatypewriter"); break; 
1187         case wxSCRIPT
:     xfamily 
= wxT("utopia"); break; 
1188         default:           xfamily 
= wxT("*"); 
1196                  xweight 
= MWLF_WEIGHT_BOLD
; 
1201                  xweight 
= MWLF_WEIGHT_LIGHT
; 
1206                  xweight 
= MWLF_WEIGHT_NORMAL
; 
1212                  xweight 
= MWLF_WEIGHT_DEFAULT
; 
1216     GR_SCREEN_INFO screenInfo
; 
1217     GrGetScreenInfo(& screenInfo
); 
1219     int yPixelsPerCM 
= screenInfo
.ydpcm
; 
1221     // A point is 1/72 of an inch. 
1222     // An inch is 2.541 cm. 
1223     // So pixelHeight = (pointSize / 72) (inches) * 2.541 (for cm) * yPixelsPerCM (for pixels) 
1224     // In fact pointSize is 10 * the normal point size so 
1227     int pixelHeight 
= (int) ( (((float)pointSize
) / 720.0) * 2.541 * (float) yPixelsPerCM
) ; 
1229     // An alternative: assume that the screen is 72 dpi. 
1230     //int pixelHeight = (int) (((float)pointSize / 720.0) * 72.0) ; 
1231     //int pixelHeight = (int) ((float)pointSize / 10.0) ; 
1234     logFont
.lfHeight 
= pixelHeight
; 
1235     logFont
.lfWidth 
= 0; 
1236     logFont
.lfEscapement 
= 0; 
1237     logFont
.lfOrientation 
= 0; 
1238     logFont
.lfWeight 
= xweight
; 
1239     logFont
.lfItalic 
= (style 
== wxNORMAL 
? 0 : 1) ; 
1240     logFont
.lfUnderline 
= 0; 
1241     logFont
.lfStrikeOut 
= 0; 
1242     logFont
.lfCharSet 
= MWLF_CHARSET_DEFAULT
; // TODO: select appropriate one 
1243     logFont
.lfOutPrecision 
= MWLF_TYPE_DEFAULT
; 
1244     logFont
.lfClipPrecision 
= 0; // Not used 
1245     logFont
.lfRoman 
= (family 
== wxROMAN 
? 1 : 0) ; 
1246     logFont
.lfSerif 
= (family 
== wxSWISS 
? 0 : 1) ; 
1247     logFont
.lfSansSerif 
= !logFont
.lfSerif 
; 
1248     logFont
.lfModern 
= (family 
== wxMODERN 
? 1 : 0) ; 
1249     logFont
.lfProportional 
= (family 
== wxTELETYPE 
? 0 : 1) ; 
1250     logFont
.lfOblique 
= 0; 
1251     logFont
.lfSmallCaps 
= 0; 
1252     logFont
.lfPitch 
= 0; // 0 = default 
1253     strcpy(logFont
.lfFaceName
, facename
.c_str()); 
1255     XFontStruct
* fontInfo 
= (XFontStruct
*) malloc(sizeof(XFontStruct
)); 
1256     fontInfo
->fid 
= GrCreateFont((GR_CHAR
*) facename
.c_str(), pixelHeight
, & logFont
); 
1257     GrGetFontInfo(fontInfo
->fid
, & fontInfo
->info
); 
1258     return (wxNativeFont
) fontInfo
; 
1262     if (!facename
.empty()) 
1264         fontSpec
.Printf(wxT("-*-%s-*-*-normal-*-*-*-*-*-*-*-*-*"), 
1267         if ( wxTestFontSpec(fontSpec
) ) 
1271         //else: no such family, use default one instead 
1278             fontSpec
.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"), 
1280             if ( wxTestFontSpec(fontSpec
) ) 
1285             // fall through - try wxITALIC now 
1288             fontSpec
.Printf(wxT("-*-%s-*-i-*-*-*-*-*-*-*-*-*-*"), 
1290             if ( wxTestFontSpec(fontSpec
) ) 
1294             else if ( style 
== wxITALIC 
) // and not wxSLANT 
1297                 fontSpec
.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"), 
1299                 if ( wxTestFontSpec(fontSpec
) ) 
1305                     // no italic, no slant - leave default 
1312             wxFAIL_MSG(wxT("unknown font style")); 
1313             // fall back to normal 
1325                   fontSpec
.Printf(wxT("-*-%s-bold-*-*-*-*-*-*-*-*-*-*-*"), 
1327                   if ( wxTestFontSpec(fontSpec
) ) 
1329                        xweight 
= wxT("bold"); 
1332                   fontSpec
.Printf(wxT("-*-%s-heavy-*-*-*-*-*-*-*-*-*-*-*"), 
1334                   if ( wxTestFontSpec(fontSpec
) ) 
1336                        xweight 
= wxT("heavy"); 
1339                   fontSpec
.Printf(wxT("-*-%s-extrabold-*-*-*-*-*-*-*-*-*-*-*"), 
1341                   if ( wxTestFontSpec(fontSpec
) ) 
1343                       xweight 
= wxT("extrabold"); 
1346                   fontSpec
.Printf(wxT("-*-%s-demibold-*-*-*-*-*-*-*-*-*-*-*"), 
1348                   if ( wxTestFontSpec(fontSpec
) ) 
1350                       xweight 
= wxT("demibold"); 
1353                   fontSpec
.Printf(wxT("-*-%s-black-*-*-*-*-*-*-*-*-*-*-*"), 
1355                   if ( wxTestFontSpec(fontSpec
) ) 
1357                       xweight 
= wxT("black"); 
1360                   fontSpec
.Printf(wxT("-*-%s-ultrablack-*-*-*-*-*-*-*-*-*-*-*"), 
1362                   if ( wxTestFontSpec(fontSpec
) ) 
1364                       xweight 
= wxT("ultrablack"); 
1371                   fontSpec
.Printf(wxT("-*-%s-light-*-*-*-*-*-*-*-*-*-*-*"), 
1373                   if ( wxTestFontSpec(fontSpec
) ) 
1375                        xweight 
= wxT("light"); 
1378                   fontSpec
.Printf(wxT("-*-%s-thin-*-*-*-*-*-*-*-*-*-*-*"), 
1380                   if ( wxTestFontSpec(fontSpec
) ) 
1382                        xweight 
= wxT("thin"); 
1389                   fontSpec
.Printf(wxT("-*-%s-medium-*-*-*-*-*-*-*-*-*-*-*"), 
1391                   if ( wxTestFontSpec(fontSpec
) ) 
1393                        xweight 
= wxT("medium"); 
1396                   fontSpec
.Printf(wxT("-*-%s-normal-*-*-*-*-*-*-*-*-*-*-*"), 
1398                   if ( wxTestFontSpec(fontSpec
) ) 
1400                        xweight 
= wxT("normal"); 
1403                   fontSpec
.Printf(wxT("-*-%s-regular-*-*-*-*-*-*-*-*-*-*-*"), 
1405                   if ( wxTestFontSpec(fontSpec
) ) 
1407                       xweight 
= wxT("regular"); 
1413         default:           xweight 
= wxT("*"); break; 
1416     // if pointSize is -1, don't specify any 
1418     if ( pointSize 
== -1 ) 
1420         sizeSpec 
= wxT('*'); 
1424         sizeSpec
.Printf(wxT("%d"), pointSize
); 
1427     // construct the X font spec from our data 
1428     fontSpec
.Printf(wxT("-*-%s-%s-%s-normal-*-*-%s-*-*-*-*-%s-%s"), 
1429                     xfamily
.c_str(), xweight
.c_str(), xstyle
.c_str(), 
1430                     sizeSpec
.c_str(), xregistry
.c_str(), xencoding
.c_str()); 
1433         *xFontName 
= fontSpec
; 
1435     return wxLoadFont(fontSpec
); 
1440 // ---------------------------------------------------------------------------- 
1442 // ---------------------------------------------------------------------------- 
1444 class wxFontModule 
: public wxModule
 
1451     DECLARE_DYNAMIC_CLASS(wxFontModule
) 
1454 IMPLEMENT_DYNAMIC_CLASS(wxFontModule
, wxModule
) 
1456 bool wxFontModule::OnInit() 
1458     g_fontHash 
= new wxHashTable( wxKEY_STRING 
); 
1463 void wxFontModule::OnExit() 
1465     wxDELETE(g_fontHash
); 
1468 #endif // GTK 2.0/1.x