1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        unix/fontutil.cpp 
   3 // Purpose:     Font helper functions for X11 (GDK/X) 
   4 // Author:      Vadim Zeitlin 
   8 // Copyright:   (c) Vadim Zeitlin 
   9 // Licence:     wxWindows license 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  21     #pragma implementation "fontutil.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  36 #pragma message disable nosimpint 
  40 #pragma message enable nosimpint 
  43     #include "wx/utils.h"       // for wxGetDisplay() 
  44 #elif defined(__WXGTK__) 
  48 #include "wx/fontutil.h" 
  49 #include "wx/fontmap.h" 
  50 #include "wx/tokenzr.h" 
  52 #include "wx/module.h" 
  54 // ---------------------------------------------------------------------------- 
  56 // ---------------------------------------------------------------------------- 
  58 static wxHashTable 
*g_fontHash 
= (wxHashTable
*) NULL
; 
  60 // ---------------------------------------------------------------------------- 
  62 // ---------------------------------------------------------------------------- 
  64 // define the functions to create and destroy native fonts for this toolkit 
  66     static inline wxNativeFont 
wxLoadFont(const wxString
& fontSpec
) 
  68         return XLoadQueryFont((Display 
*)wxGetDisplay(), fontSpec
); 
  71     static inline void wxFreeFont(wxNativeFont font
) 
  73         XFreeFont((Display 
*)wxGetDisplay(), (XFontStruct 
*)font
); 
  75 #elif defined(__WXGTK__) 
  76     static inline wxNativeFont 
wxLoadFont(const wxString
& fontSpec
) 
  78        return gdk_font_load( wxConvertWX2MB(fontSpec
) ); 
  81     static inline void wxFreeFont(wxNativeFont font
) 
  86     #error "Unknown GUI toolkit" 
  89 static bool wxTestFontSpec(const wxString
& fontspec
); 
  91 static wxNativeFont 
wxLoadQueryFont(int pointSize
, 
  96                                     const wxString
& facename
, 
  97                                     const wxString
& xregistry
, 
  98                                     const wxString
& xencoding
); 
 100 // ============================================================================ 
 102 // ============================================================================ 
 104 // ---------------------------------------------------------------------------- 
 105 // wxNativeEncodingInfo 
 106 // ---------------------------------------------------------------------------- 
 108 // convert to/from the string representation: format is 
 109 //      encodingid;registry;encoding[;facename] 
 110 bool wxNativeEncodingInfo::FromString(const wxString
& s
) 
 112     wxStringTokenizer 
tokenizer(s
, _T(";")); 
 113             // cannot use "-" because it may be part of encoding name 
 115     wxString encid 
= tokenizer
.GetNextToken(); 
 117     if ( !encid
.ToLong(&enc
) ) 
 119     encoding 
= (wxFontEncoding
)enc
; 
 121     xregistry 
= tokenizer
.GetNextToken(); 
 125     xencoding 
= tokenizer
.GetNextToken(); 
 130     facename 
= tokenizer
.GetNextToken(); 
 135 wxString 
wxNativeEncodingInfo::ToString() const 
 138     s 
<< (long)encoding 
<< _T(';') << xregistry 
<< _T(';') << xencoding
; 
 141         s 
<< _T(';') << facename
; 
 147 // ---------------------------------------------------------------------------- 
 149 // ---------------------------------------------------------------------------- 
 151 bool wxGetNativeFontEncoding(wxFontEncoding encoding
, 
 152                              wxNativeEncodingInfo 
*info
) 
 154     wxCHECK_MSG( info
, FALSE
, _T("bad pointer in wxGetNativeFontEncoding") ); 
 156     if ( encoding 
== wxFONTENCODING_DEFAULT 
) 
 158         encoding 
= wxFont::GetDefaultEncoding(); 
 163         case wxFONTENCODING_ISO8859_1
: 
 164         case wxFONTENCODING_ISO8859_2
: 
 165         case wxFONTENCODING_ISO8859_3
: 
 166         case wxFONTENCODING_ISO8859_4
: 
 167         case wxFONTENCODING_ISO8859_5
: 
 168         case wxFONTENCODING_ISO8859_6
: 
 169         case wxFONTENCODING_ISO8859_7
: 
 170         case wxFONTENCODING_ISO8859_8
: 
 171         case wxFONTENCODING_ISO8859_9
: 
 172         case wxFONTENCODING_ISO8859_10
: 
 173         case wxFONTENCODING_ISO8859_11
: 
 174         case wxFONTENCODING_ISO8859_13
: 
 175         case wxFONTENCODING_ISO8859_14
: 
 176         case wxFONTENCODING_ISO8859_15
: 
 178                 int cp 
= encoding 
- wxFONTENCODING_ISO8859_1 
+ 1; 
 179                 info
->xregistry 
= wxT("iso8859"); 
 180                 info
->xencoding
.Printf(wxT("%d"), cp
); 
 184         case wxFONTENCODING_KOI8
: 
 185             info
->xregistry 
= wxT("koi8"); 
 187             // we don't make distinction between koi8-r and koi8-u (so far) 
 188             info
->xencoding 
= wxT("*"); 
 191         case wxFONTENCODING_CP1250
: 
 192         case wxFONTENCODING_CP1251
: 
 193         case wxFONTENCODING_CP1252
: 
 194         case wxFONTENCODING_CP1253
: 
 195         case wxFONTENCODING_CP1254
: 
 196         case wxFONTENCODING_CP1255
: 
 197         case wxFONTENCODING_CP1256
: 
 198         case wxFONTENCODING_CP1257
: 
 200                 int cp 
= encoding 
- wxFONTENCODING_CP1250 
+ 1250; 
 201                 info
->xregistry 
= wxT("microsoft"); 
 202                 info
->xencoding
.Printf(wxT("cp%d"), cp
); 
 206         case wxFONTENCODING_SYSTEM
: 
 208             info
->xencoding 
= wxT("*"); 
 212             // don't know how to translate this encoding into X fontspec 
 216    info
->encoding 
= encoding
; 
 221 bool wxTestFontEncoding(const wxNativeEncodingInfo
& info
) 
 224     fontspec
.Printf(_T("-*-%s-*-*-*-*-*-*-*-*-*-*-%s-%s"), 
 225                     !info
.facename 
? _T("*") : info
.facename
.c_str(), 
 226                     info
.xregistry
.c_str(), 
 227                     info
.xencoding
.c_str()); 
 229     return wxTestFontSpec(fontspec
); 
 232 // ---------------------------------------------------------------------------- 
 233 // X-specific functions 
 234 // ---------------------------------------------------------------------------- 
 236 wxNativeFont 
wxLoadQueryNearestFont(int pointSize
, 
 241                                     const wxString 
&facename
, 
 242                                     wxFontEncoding encoding
) 
 244     if ( encoding 
== wxFONTENCODING_DEFAULT 
) 
 246         encoding 
= wxFont::GetDefaultEncoding(); 
 249     // first determine the encoding - if the font doesn't exist at all in this 
 250     // encoding, it's useless to do all other approximations (i.e. size, 
 251     // family &c don't matter much) 
 252     wxNativeEncodingInfo info
; 
 253     if ( encoding 
== wxFONTENCODING_SYSTEM 
) 
 255         // This will always work so we don't test to save time 
 256         wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM
, &info
); 
 260         if ( !wxGetNativeFontEncoding(encoding
, &info
) || 
 261              !wxTestFontEncoding(info
) ) 
 263             if ( !wxTheFontMapper
->GetAltForEncoding(encoding
, &info
) ) 
 265                 // unspported encoding - replace it with the default 
 267                 // NB: we can't just return 0 from here because wxGTK code doesn't 
 268                 //     check for it (i.e. it supposes that we'll always succeed), 
 269                 //     so it would provoke a crash 
 270                 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM
, &info
); 
 275     // OK, we have the correct xregistry/xencoding in info structure 
 276     wxNativeFont font 
= wxLoadQueryFont( pointSize
, family
, style
, weight
, 
 277                                          underlined
, facename
, 
 278                                          info
.xregistry
, info
.xencoding 
); 
 282         // search up and down by stepsize 10 
 283         int max_size 
= pointSize 
+ 20 * (1 + (pointSize
/180)); 
 284         int min_size 
= pointSize 
- 20 * (1 + (pointSize
/180)); 
 288         // Search for smaller size (approx.) 
 289         for ( i 
= pointSize 
- 10; !font 
&& i 
>= 10 && i 
>= min_size
; i 
-= 10 ) 
 291             font 
= wxLoadQueryFont(i
, family
, style
, weight
, underlined
, 
 292                                    facename
, info
.xregistry
, info
.xencoding
); 
 295         // Search for larger size (approx.) 
 296         for ( i 
= pointSize 
+ 10; !font 
&& i 
<= max_size
; i 
+= 10 ) 
 298             font 
= wxLoadQueryFont(i
, family
, style
, weight
, underlined
, 
 299                                    facename
, info
.xregistry
, info
.xencoding
); 
 302         // Try default family 
 303         if ( !font 
&& family 
!= wxDEFAULT 
) 
 305             font 
= wxLoadQueryFont(pointSize
, wxDEFAULT
, style
, weight
, 
 306                                    underlined
, facename
, 
 307                                    info
.xregistry
, info
.xencoding 
); 
 313             font 
= wxLoadQueryFont(120, wxDEFAULT
, wxNORMAL
, wxNORMAL
, 
 314                                    underlined
, facename
, 
 315                                    info
.xregistry
, info
.xencoding
); 
 321             font 
= wxLoadQueryFont(120, wxDEFAULT
, wxNORMAL
, wxNORMAL
, 
 322                                    underlined
, wxEmptyString
, 
 323                                    info
.xregistry
, info
.xencoding
); 
 330 // ---------------------------------------------------------------------------- 
 332 // ---------------------------------------------------------------------------- 
 334 // returns TRUE if there are any fonts matching this font spec 
 335 static bool wxTestFontSpec(const wxString
& fontspec
) 
 337     // some X servers will fail to load this font because there are too many 
 338     // matches so we must test explicitly for this 
 339     if ( fontspec 
== _T("-*-*-*-*-*-*-*-*-*-*-*-*-*-*") ) 
 344     wxNativeFont test 
= (wxNativeFont
) g_fontHash
->Get( fontspec 
); 
 347 //        printf( "speed up\n" ); 
 351     test 
= wxLoadFont(fontspec
); 
 352     g_fontHash
->Put( fontspec
, (wxObject
*) test 
); 
 366 static wxNativeFont 
wxLoadQueryFont(int pointSize
, 
 370                                     bool WXUNUSED(underlined
), 
 371                                     const wxString
& facename
, 
 372                                     const wxString
& xregistry
, 
 373                                     const wxString
& xencoding
) 
 378         case wxDECORATIVE
: xfamily 
= wxT("lucida"); break; 
 379         case wxROMAN
:      xfamily 
= wxT("times");  break; 
 380         case wxMODERN
:     xfamily 
= wxT("courier"); break; 
 381         case wxSWISS
:      xfamily 
= wxT("helvetica"); break; 
 382         case wxTELETYPE
:   xfamily 
= wxT("lucidatypewriter"); break; 
 383         case wxSCRIPT
:     xfamily 
= wxT("utopia"); break; 
 384         default:           xfamily 
= wxT("*"); 
 388     if (!facename
.IsEmpty()) 
 390         fontSpec
.Printf(wxT("-*-%s-*-*-normal-*-*-*-*-*-*-*-*-*"), 
 393         if ( wxTestFontSpec(fontSpec
) ) 
 397         //else: no such family, use default one instead 
 404             fontSpec
.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"), 
 406             if ( wxTestFontSpec(fontSpec
) ) 
 411             // fall through - try wxITALIC now 
 414             fontSpec
.Printf(wxT("-*-%s-*-i-*-*-*-*-*-*-*-*-*-*"), 
 416             if ( wxTestFontSpec(fontSpec
) ) 
 420             else if ( style 
== wxITALIC 
) // and not wxSLANT 
 423                 fontSpec
.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"), 
 425                 if ( wxTestFontSpec(fontSpec
) ) 
 431                     // no italic, no slant - leave default 
 438             wxFAIL_MSG(_T("unknown font style")); 
 439             // fall back to normal 
 451                   fontSpec
.Printf(wxT("-*-%s-bold-*-*-*-*-*-*-*-*-*-*-*"), 
 453                   if ( wxTestFontSpec(fontSpec
) ) 
 455                        xweight 
= wxT("bold"); 
 458                   fontSpec
.Printf(wxT("-*-%s-heavy-*-*-*-*-*-*-*-*-*-*-*"), 
 460                   if ( wxTestFontSpec(fontSpec
) ) 
 462                        xweight 
= wxT("heavy"); 
 465                   fontSpec
.Printf(wxT("-*-%s-extrabold-*-*-*-*-*-*-*-*-*-*-*"), 
 467                   if ( wxTestFontSpec(fontSpec
) ) 
 469                       xweight 
= wxT("extrabold"); 
 472                   fontSpec
.Printf(wxT("-*-%s-demibold-*-*-*-*-*-*-*-*-*-*-*"), 
 474                   if ( wxTestFontSpec(fontSpec
) ) 
 476                       xweight 
= wxT("demibold"); 
 479                   fontSpec
.Printf(wxT("-*-%s-black-*-*-*-*-*-*-*-*-*-*-*"), 
 481                   if ( wxTestFontSpec(fontSpec
) ) 
 483                       xweight 
= wxT("black"); 
 486                   fontSpec
.Printf(wxT("-*-%s-ultrablack-*-*-*-*-*-*-*-*-*-*-*"), 
 488                   if ( wxTestFontSpec(fontSpec
) ) 
 490                       xweight 
= wxT("ultrablack"); 
 497                   fontSpec
.Printf(wxT("-*-%s-light-*-*-*-*-*-*-*-*-*-*-*"), 
 499                   if ( wxTestFontSpec(fontSpec
) ) 
 501                        xweight 
= wxT("light"); 
 504                   fontSpec
.Printf(wxT("-*-%s-thin-*-*-*-*-*-*-*-*-*-*-*"), 
 506                   if ( wxTestFontSpec(fontSpec
) ) 
 508                        xweight 
= wxT("thin"); 
 515                   fontSpec
.Printf(wxT("-*-%s-medium-*-*-*-*-*-*-*-*-*-*-*"), 
 517                   if ( wxTestFontSpec(fontSpec
) ) 
 519                        xweight 
= wxT("medium"); 
 522                   fontSpec
.Printf(wxT("-*-%s-normal-*-*-*-*-*-*-*-*-*-*-*"), 
 524                   if ( wxTestFontSpec(fontSpec
) ) 
 526                        xweight 
= wxT("normal"); 
 529                   fontSpec
.Printf(wxT("-*-%s-regular-*-*-*-*-*-*-*-*-*-*-*"), 
 531                   if ( wxTestFontSpec(fontSpec
) ) 
 533                       xweight 
= wxT("regular"); 
 539         default:           xweight 
= wxT("*"); break; 
 542     // construct the X font spec from our data 
 543     fontSpec
.Printf(wxT("-*-%s-%s-%s-normal-*-*-%d-*-*-*-*-%s-%s"), 
 544                     xfamily
.c_str(), xweight
.c_str(), xstyle
.c_str(), 
 545                     pointSize
, xregistry
.c_str(), xencoding
.c_str()); 
 547     return wxLoadFont(fontSpec
); 
 550 // ---------------------------------------------------------------------------- 
 552 // ---------------------------------------------------------------------------- 
 554 class wxFontModule 
: public wxModule
 
 561     DECLARE_DYNAMIC_CLASS(wxFontModule
) 
 564 IMPLEMENT_DYNAMIC_CLASS(wxFontModule
, wxModule
) 
 566 bool wxFontModule::OnInit() 
 568     g_fontHash 
= new wxHashTable( wxKEY_STRING 
); 
 573 void wxFontModule::OnExit() 
 577     g_fontHash 
= (wxHashTable 
*)NULL
;