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 bool wxNativeFontInfo::GetStrikethrough() const
141 wxString
wxNativeFontInfo::GetFaceName() const
143 // the Pango "family" is the wx "face name"
144 return wxPANGO_CONV_BACK(pango_font_description_get_family(description
));
147 wxFontFamily
wxNativeFontInfo::GetFamily() const
149 wxFontFamily ret
= wxFONTFAMILY_UNKNOWN
;
151 const char *family_name
= pango_font_description_get_family( description
);
153 // note: not passing -1 as the 2nd parameter to g_ascii_strdown to work
154 // around a bug in the 64-bit glib shipped with solaris 10, -1 causes it
155 // to try to allocate 2^32 bytes.
158 wxGtkString
family_text(g_ascii_strdown(family_name
, strlen(family_name
)));
160 // Check for some common fonts, to salvage what we can from the current
161 // win32 centric wxFont API:
162 if (wxStrnicmp( family_text
, "monospace", 9 ) == 0)
163 ret
= wxFONTFAMILY_TELETYPE
; // begins with "Monospace"
164 else if (wxStrnicmp( family_text
, "courier", 7 ) == 0)
165 ret
= wxFONTFAMILY_TELETYPE
; // begins with "Courier"
166 #if defined(__WXGTK20__) || defined(HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE)
169 PangoFontFamily
**families
;
170 PangoFontFamily
*family
= NULL
;
172 pango_context_list_families(
174 gtk_widget_get_pango_context( wxGetRootWindow() ),
176 wxTheApp
->GetPangoContext(),
178 &families
, &n_families
);
180 for (int i
= 0; i
< n_families
; ++i
)
182 if (g_ascii_strcasecmp(pango_font_family_get_name( families
[i
] ),
183 pango_font_description_get_family( description
)) == 0 )
185 family
= families
[i
];
192 // Some gtk+ systems might query for a non-existing font from
193 // wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) on initialization,
194 // don't assert until wxSystemSettings::GetFont is checked for this - MR
195 // wxASSERT_MSG( family, "No appropriate PangoFontFamily found for ::description" );
197 if (family
!= NULL
&& pango_font_family_is_monospace( family
))
198 ret
= wxFONTFAMILY_TELETYPE
; // is deemed a monospace font by pango
200 #endif // GTK+ 2 || HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE
202 if (ret
== wxFONTFAMILY_UNKNOWN
)
204 if (strstr( family_text
, "sans" ) != NULL
|| strstr( family_text
, "Sans" ) != NULL
)
205 // checked before serif, so that "* Sans Serif" fonts are detected correctly
206 ret
= wxFONTFAMILY_SWISS
; // contains "Sans"
207 else if (strstr( family_text
, "serif" ) != NULL
|| strstr( family_text
, "Serif" ) != NULL
)
208 ret
= wxFONTFAMILY_ROMAN
; // contains "Serif"
209 else if (wxStrnicmp( family_text
, "times", 5 ) == 0)
210 ret
= wxFONTFAMILY_ROMAN
; // begins with "Times"
211 else if (wxStrnicmp( family_text
, "old", 3 ) == 0)
212 ret
= wxFONTFAMILY_DECORATIVE
; // begins with "Old" - "Old English", "Old Town"
218 wxFontEncoding
wxNativeFontInfo::GetEncoding() const
220 return wxFONTENCODING_SYSTEM
;
223 void wxNativeFontInfo::SetPointSize(int pointsize
)
225 pango_font_description_set_size( description
, pointsize
* PANGO_SCALE
);
228 void wxNativeFontInfo::SetStyle(wxFontStyle style
)
232 case wxFONTSTYLE_ITALIC
:
233 pango_font_description_set_style( description
, PANGO_STYLE_ITALIC
);
235 case wxFONTSTYLE_SLANT
:
236 pango_font_description_set_style( description
, PANGO_STYLE_OBLIQUE
);
239 wxFAIL_MSG( "unknown font style" );
241 case wxFONTSTYLE_NORMAL
:
242 pango_font_description_set_style( description
, PANGO_STYLE_NORMAL
);
247 void wxNativeFontInfo::SetWeight(wxFontWeight weight
)
251 case wxFONTWEIGHT_BOLD
:
252 pango_font_description_set_weight(description
, PANGO_WEIGHT_BOLD
);
254 case wxFONTWEIGHT_LIGHT
:
255 pango_font_description_set_weight(description
, PANGO_WEIGHT_LIGHT
);
258 wxFAIL_MSG( "unknown font weight" );
260 case wxFONTWEIGHT_NORMAL
:
261 pango_font_description_set_weight(description
, PANGO_WEIGHT_NORMAL
);
265 void wxNativeFontInfo::SetUnderlined(bool WXUNUSED(underlined
))
267 // wxWindowDCImpl::DoDrawText will take care of rendering font with
268 // the underline attribute!
269 wxFAIL_MSG( "not implemented" );
272 void wxNativeFontInfo::SetStrikethrough(bool WXUNUSED(strikethrough
))
274 wxFAIL_MSG( "not implemented" );
277 bool wxNativeFontInfo::SetFaceName(const wxString
& facename
)
279 pango_font_description_set_family(description
, wxPANGO_CONV(facename
));
281 // we return true because Pango doesn't tell us if the call failed or not;
282 // instead on wxGTK wxFont::SetFaceName() will call wxFontBase::SetFaceName()
283 // which does the check
287 void wxNativeFontInfo::SetFamily(wxFontFamily family
)
289 wxArrayString facename
;
291 // the list of fonts associated with a family was partially
292 // taken from http://www.codestyle.org/css/font-family
296 case wxFONTFAMILY_SCRIPT
:
297 // corresponds to the cursive font family in the page linked above
298 facename
.Add(wxS("URW Chancery L"));
299 facename
.Add(wxS("Comic Sans MS"));
302 case wxFONTFAMILY_DECORATIVE
:
303 // corresponds to the fantasy font family in the page linked above
304 facename
.Add(wxS("Impact"));
307 case wxFONTFAMILY_ROMAN
:
308 // corresponds to the serif font family in the page linked above
309 facename
.Add(wxS("Serif"));
310 facename
.Add(wxS("DejaVu Serif"));
311 facename
.Add(wxS("DejaVu LGC Serif"));
312 facename
.Add(wxS("Bitstream Vera Serif"));
313 facename
.Add(wxS("Liberation Serif"));
314 facename
.Add(wxS("FreeSerif"));
315 facename
.Add(wxS("Luxi Serif"));
316 facename
.Add(wxS("Times New Roman"));
317 facename
.Add(wxS("Century Schoolbook L"));
318 facename
.Add(wxS("URW Bookman L"));
319 facename
.Add(wxS("URW Palladio L"));
320 facename
.Add(wxS("Times"));
323 case wxFONTFAMILY_TELETYPE
:
324 case wxFONTFAMILY_MODERN
:
325 // corresponds to the monospace font family in the page linked above
326 facename
.Add(wxS("Monospace"));
327 facename
.Add(wxS("DejaVu Sans Mono"));
328 facename
.Add(wxS("DejaVu LGC Sans Mono"));
329 facename
.Add(wxS("Bitstream Vera Sans Mono"));
330 facename
.Add(wxS("Liberation Mono"));
331 facename
.Add(wxS("FreeMono"));
332 facename
.Add(wxS("Luxi Mono"));
333 facename
.Add(wxS("Courier New"));
334 facename
.Add(wxS("Lucida Sans Typewriter"));
335 facename
.Add(wxS("Nimbus Mono L"));
336 facename
.Add(wxS("Andale Mono"));
337 facename
.Add(wxS("Courier"));
340 case wxFONTFAMILY_SWISS
:
341 case wxFONTFAMILY_DEFAULT
:
343 // corresponds to the sans-serif font family in the page linked above
344 facename
.Add(wxS("Sans"));
345 facename
.Add(wxS("DejaVu Sans"));
346 facename
.Add(wxS("DejaVu LGC Sans"));
347 facename
.Add(wxS("Bitstream Vera Sans"));
348 facename
.Add(wxS("Liberation Sans"));
349 facename
.Add(wxS("FreeSans"));
350 facename
.Add(wxS("Luxi Sans"));
351 facename
.Add(wxS("Arial"));
352 facename
.Add(wxS("Lucida Sans"));
353 facename
.Add(wxS("Nimbus Sans L"));
354 facename
.Add(wxS("URW Gothic L"));
358 SetFaceName(facename
);
361 void wxNativeFontInfo::SetEncoding(wxFontEncoding
WXUNUSED(encoding
))
363 wxFAIL_MSG( "not implemented: Pango encoding is always UTF8" );
366 bool wxNativeFontInfo::FromString(const wxString
& s
)
369 pango_font_description_free( description
);
371 // there is a bug in at least pango <= 1.13 which makes it (or its backends)
372 // segfault for very big point sizes and for negative point sizes.
373 // To workaround that bug for pango <= 1.13
374 // (see http://bugzilla.gnome.org/show_bug.cgi?id=340229)
375 // we do the check on the size here using same (arbitrary) limits used by
376 // pango > 1.13. Note that the segfault could happen also for pointsize
377 // smaller than this limit !!
379 const size_t pos
= str
.find_last_of(wxS(" "));
381 if ( pos
!= wxString::npos
&& wxString(str
, pos
+ 1).ToDouble(&size
) )
386 else if ( size
>= 1E6
)
387 sizeStr
= wxS("1E6");
389 if ( !sizeStr
.empty() )
391 // replace the old size with the adjusted one
392 str
= wxString(s
, 0, pos
) + sizeStr
;
396 description
= pango_font_description_from_string(wxPANGO_CONV(str
));
399 // ensure a valid facename is selected
400 if (!wxFontEnumerator::IsValidFacename(GetFaceName()))
401 SetFaceName(wxNORMAL_FONT
->GetFaceName());
402 #endif // wxUSE_FONTENUM
407 wxString
wxNativeFontInfo::ToString() const
409 wxGtkString
str(pango_font_description_to_string( description
));
411 return wxPANGO_CONV_BACK(str
);
414 bool wxNativeFontInfo::FromUserString(const wxString
& s
)
416 return FromString( s
);
419 wxString
wxNativeFontInfo::ToUserString() const
428 #pragma message disable nosimpint
431 #include <X11/Xlib.h>
434 #pragma message enable nosimpint
437 #elif defined(__WXGTK__)
438 // we have to declare struct tm to avoid problems with first forward
439 // declaring it in C code (glib.h included from gdk.h does it) and then
440 // defining it when time.h is included from the headers below - this is
441 // known not to work at least with Sun CC 6.01
448 // ----------------------------------------------------------------------------
450 // ----------------------------------------------------------------------------
452 static wxHashTable
*g_fontHash
= NULL
;
454 // ----------------------------------------------------------------------------
456 // ----------------------------------------------------------------------------
458 // define the functions to create and destroy native fonts for this toolkit
460 wxNativeFont
wxLoadFont(const wxString
& fontSpec
)
462 return XLoadQueryFont((Display
*)wxGetDisplay(), fontSpec
);
465 inline void wxFreeFont(wxNativeFont font
)
467 XFreeFont((Display
*)wxGetDisplay(), (XFontStruct
*)font
);
469 #elif defined(__WXGTK__)
470 wxNativeFont
wxLoadFont(const wxString
& fontSpec
)
472 // VZ: we should use gdk_fontset_load() instead of gdk_font_load()
473 // here to be able to display Japanese fonts correctly (at least
474 // this is what people report) but unfortunately doing it results
475 // in tons of warnings when using GTK with "normal" European
476 // languages and so we can't always do it and I don't know enough
477 // to determine when should this be done... (FIXME)
478 return gdk_font_load( wxConvertWX2MB(fontSpec
) );
481 inline void wxFreeFont(wxNativeFont font
)
483 gdk_font_unref(font
);
486 #error "Unknown GUI toolkit"
489 static bool wxTestFontSpec(const wxString
& fontspec
);
491 static wxNativeFont
wxLoadQueryFont(int pointSize
,
496 const wxString
& facename
,
497 const wxString
& xregistry
,
498 const wxString
& xencoding
,
499 wxString
* xFontName
);
501 // ============================================================================
503 // ============================================================================
505 // ----------------------------------------------------------------------------
506 // wxNativeEncodingInfo
507 // ----------------------------------------------------------------------------
509 // convert to/from the string representation: format is
510 // encodingid;registry;encoding[;facename]
511 bool wxNativeEncodingInfo::FromString(const wxString
& s
)
513 // use ";", not "-" because it may be part of encoding name
514 wxStringTokenizer
tokenizer(s
, wxT(";"));
516 wxString encid
= tokenizer
.GetNextToken();
518 if ( !encid
.ToLong(&enc
) )
520 encoding
= (wxFontEncoding
)enc
;
522 xregistry
= tokenizer
.GetNextToken();
526 xencoding
= tokenizer
.GetNextToken();
531 facename
= tokenizer
.GetNextToken();
536 wxString
wxNativeEncodingInfo::ToString() const
539 s
<< (long)encoding
<< wxT(';') << xregistry
<< wxT(';') << xencoding
;
540 if ( !facename
.empty() )
542 s
<< wxT(';') << facename
;
548 // ----------------------------------------------------------------------------
550 // ----------------------------------------------------------------------------
552 void wxNativeFontInfo::Init()
557 bool wxNativeFontInfo::FromString(const wxString
& s
)
559 wxStringTokenizer
tokenizer(s
, wxT(";"));
562 wxString token
= tokenizer
.GetNextToken();
563 if ( token
!= wxT('0') )
566 xFontName
= tokenizer
.GetNextToken();
568 // this should be the end
569 if ( tokenizer
.HasMoreTokens() )
572 return FromXFontName(xFontName
);
575 wxString
wxNativeFontInfo::ToString() const
578 return wxString::Format(wxT("%d;%s"), 0, GetXFontName().c_str());
581 bool wxNativeFontInfo::FromUserString(const wxString
& s
)
583 return FromXFontName(s
);
586 wxString
wxNativeFontInfo::ToUserString() const
588 return GetXFontName();
591 bool wxNativeFontInfo::HasElements() const
593 // we suppose that the foundry is never empty, so if it is it means that we
594 // had never parsed the XLFD
595 return !fontElements
[0].empty();
598 wxString
wxNativeFontInfo::GetXFontComponent(wxXLFDField field
) const
600 wxCHECK_MSG( field
< wxXLFD_MAX
, wxEmptyString
, wxT("invalid XLFD field") );
602 if ( !HasElements() )
604 if ( !const_cast<wxNativeFontInfo
*>(this)->FromXFontName(xFontName
) )
605 return wxEmptyString
;
608 return fontElements
[field
];
611 bool wxNativeFontInfo::FromXFontName(const wxString
& fontname
)
613 // TODO: we should be able to handle the font aliases here, but how?
614 wxStringTokenizer
tokenizer(fontname
, wxT("-"));
616 // skip the leading, usually empty field (font name registry)
617 if ( !tokenizer
.HasMoreTokens() )
620 (void)tokenizer
.GetNextToken();
622 for ( size_t n
= 0; n
< WXSIZEOF(fontElements
); n
++ )
624 if ( !tokenizer
.HasMoreTokens() )
626 // not enough elements in the XLFD - or maybe an alias
630 wxString field
= tokenizer
.GetNextToken();
631 if ( !field
.empty() && field
!= wxT('*') )
633 // we're really initialized now
637 fontElements
[n
] = field
;
640 // this should be all
641 if ( tokenizer
.HasMoreTokens() )
647 wxString
wxNativeFontInfo::GetXFontName() const
649 if ( xFontName
.empty() )
651 for ( size_t n
= 0; n
< WXSIZEOF(fontElements
); n
++ )
653 // replace the non specified elements with '*' except for the
654 // additional style which is usually just omitted
655 wxString elt
= fontElements
[n
];
656 if ( elt
.empty() && n
!= wxXLFD_ADDSTYLE
)
661 const_cast<wxNativeFontInfo
*>(this)->xFontName
<< wxT('-') << elt
;
669 wxNativeFontInfo::SetXFontComponent(wxXLFDField field
, const wxString
& value
)
671 wxCHECK_RET( field
< wxXLFD_MAX
, wxT("invalid XLFD field") );
673 // this class should be initialized with a valid font spec first and only
674 // then the fields may be modified!
675 wxASSERT_MSG( !IsDefault(), wxT("can't modify an uninitialized XLFD") );
677 if ( !HasElements() )
679 if ( !const_cast<wxNativeFontInfo
*>(this)->FromXFontName(xFontName
) )
681 wxFAIL_MSG( wxT("can't set font element for invalid XLFD") );
687 fontElements
[field
] = value
;
689 // invalidate the XFLD, it doesn't correspond to the font elements any more
693 void wxNativeFontInfo::SetXFontName(const wxString
& xFontName_
)
695 // invalidate the font elements, GetXFontComponent() will reparse the XLFD
696 fontElements
[0].clear();
698 xFontName
= xFontName_
;
703 int wxNativeFontInfo::GetPointSize() const
705 const wxString s
= GetXFontComponent(wxXLFD_POINTSIZE
);
707 // return -1 to indicate that the size is unknown
709 return s
.ToLong(&l
) ? l
: -1;
712 wxFontStyle
wxNativeFontInfo::GetStyle() const
714 const wxString s
= GetXFontComponent(wxXLFD_SLANT
);
716 if ( s
.length() != 1 )
718 // it is really unknown but we don't have any way to return it from
720 return wxFONTSTYLE_NORMAL
;
723 switch ( s
[0].GetValue() )
726 // again, unknown but consider normal by default
729 return wxFONTSTYLE_NORMAL
;
732 return wxFONTSTYLE_ITALIC
;
735 return wxFONTSTYLE_SLANT
;
739 wxFontWeight
wxNativeFontInfo::GetWeight() const
741 const wxString s
= GetXFontComponent(wxXLFD_WEIGHT
).MakeLower();
742 if ( s
.find(wxT("bold")) != wxString::npos
|| s
== wxT("black") )
743 return wxFONTWEIGHT_BOLD
;
744 else if ( s
== wxT("light") )
745 return wxFONTWEIGHT_LIGHT
;
747 return wxFONTWEIGHT_NORMAL
;
750 bool wxNativeFontInfo::GetUnderlined() const
752 // X fonts are never underlined
756 wxString
wxNativeFontInfo::GetFaceName() const
758 // wxWidgets facename probably more accurately corresponds to X family
759 return GetXFontComponent(wxXLFD_FAMILY
);
762 wxFontFamily
wxNativeFontInfo::GetFamily() const
764 // and wxWidgets family -- to X foundry, but we have to translate it to
765 // wxFontFamily somehow...
766 wxFAIL_MSG(wxT("not implemented")); // GetXFontComponent(wxXLFD_FOUNDRY);
768 return wxFONTFAMILY_DEFAULT
;
771 wxFontEncoding
wxNativeFontInfo::GetEncoding() const
773 // we already have the code for this but need to refactor it first
774 wxFAIL_MSG( wxT("not implemented") );
776 return wxFONTENCODING_MAX
;
779 void wxNativeFontInfo::SetPointSize(int pointsize
)
781 SetXFontComponent(wxXLFD_POINTSIZE
, wxString::Format(wxT("%d"), pointsize
));
784 void wxNativeFontInfo::SetStyle(wxFontStyle style
)
789 case wxFONTSTYLE_ITALIC
:
793 case wxFONTSTYLE_SLANT
:
797 case wxFONTSTYLE_NORMAL
:
801 wxFAIL_MSG( wxT("unknown wxFontStyle in wxNativeFontInfo::SetStyle") );
805 SetXFontComponent(wxXLFD_SLANT
, s
);
808 void wxNativeFontInfo::SetWeight(wxFontWeight weight
)
813 case wxFONTWEIGHT_BOLD
:
817 case wxFONTWEIGHT_LIGHT
:
821 case wxFONTWEIGHT_NORMAL
:
826 wxFAIL_MSG( wxT("unknown wxFontWeight in wxNativeFontInfo::SetWeight") );
830 SetXFontComponent(wxXLFD_WEIGHT
, s
);
833 void wxNativeFontInfo::SetUnderlined(bool WXUNUSED(underlined
))
835 // can't do this under X
838 void wxNativeFontInfo::SetStrikethrough(bool WXUNUSED(strikethrough
))
840 // this is not supported by Pango fonts neither
843 bool wxNativeFontInfo::SetFaceName(const wxString
& facename
)
845 SetXFontComponent(wxXLFD_FAMILY
, facename
);
849 void wxNativeFontInfo::SetFamily(wxFontFamily
WXUNUSED(family
))
851 // wxFontFamily -> X foundry, anyone?
852 wxFAIL_MSG( wxT("not implemented") );
854 // SetXFontComponent(wxXLFD_FOUNDRY, ...);
857 void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding
)
859 wxNativeEncodingInfo info
;
860 if ( wxGetNativeFontEncoding(encoding
, &info
) )
862 SetXFontComponent(wxXLFD_ENCODING
, info
.xencoding
);
863 SetXFontComponent(wxXLFD_REGISTRY
, info
.xregistry
);
867 // ----------------------------------------------------------------------------
869 // ----------------------------------------------------------------------------
871 bool wxGetNativeFontEncoding(wxFontEncoding encoding
,
872 wxNativeEncodingInfo
*info
)
874 wxCHECK_MSG( info
, false, wxT("bad pointer in wxGetNativeFontEncoding") );
876 if ( encoding
== wxFONTENCODING_DEFAULT
)
878 encoding
= wxFont::GetDefaultEncoding();
883 case wxFONTENCODING_ISO8859_1
:
884 case wxFONTENCODING_ISO8859_2
:
885 case wxFONTENCODING_ISO8859_3
:
886 case wxFONTENCODING_ISO8859_4
:
887 case wxFONTENCODING_ISO8859_5
:
888 case wxFONTENCODING_ISO8859_6
:
889 case wxFONTENCODING_ISO8859_7
:
890 case wxFONTENCODING_ISO8859_8
:
891 case wxFONTENCODING_ISO8859_9
:
892 case wxFONTENCODING_ISO8859_10
:
893 case wxFONTENCODING_ISO8859_11
:
894 case wxFONTENCODING_ISO8859_12
:
895 case wxFONTENCODING_ISO8859_13
:
896 case wxFONTENCODING_ISO8859_14
:
897 case wxFONTENCODING_ISO8859_15
:
899 int cp
= encoding
- wxFONTENCODING_ISO8859_1
+ 1;
900 info
->xregistry
= wxT("iso8859");
901 info
->xencoding
.Printf(wxT("%d"), cp
);
905 case wxFONTENCODING_UTF8
:
906 info
->xregistry
= wxT("iso10646");
907 info
->xencoding
= wxT("*");
910 case wxFONTENCODING_GB2312
:
911 info
->xregistry
= wxT("GB2312"); // or the otherway round?
912 info
->xencoding
= wxT("*");
915 case wxFONTENCODING_KOI8
:
916 case wxFONTENCODING_KOI8_U
:
917 info
->xregistry
= wxT("koi8");
919 // we don't make distinction between koi8-r, koi8-u and koi8-ru (so far)
920 info
->xencoding
= wxT("*");
923 case wxFONTENCODING_CP1250
:
924 case wxFONTENCODING_CP1251
:
925 case wxFONTENCODING_CP1252
:
926 case wxFONTENCODING_CP1253
:
927 case wxFONTENCODING_CP1254
:
928 case wxFONTENCODING_CP1255
:
929 case wxFONTENCODING_CP1256
:
930 case wxFONTENCODING_CP1257
:
932 int cp
= encoding
- wxFONTENCODING_CP1250
+ 1250;
933 info
->xregistry
= wxT("microsoft");
934 info
->xencoding
.Printf(wxT("cp%d"), cp
);
938 case wxFONTENCODING_EUC_JP
:
939 case wxFONTENCODING_SHIFT_JIS
:
940 info
->xregistry
= "jis*";
941 info
->xencoding
= "*";
944 case wxFONTENCODING_SYSTEM
:
946 info
->xencoding
= wxT("*");
950 // don't know how to translate this encoding into X fontspec
954 info
->encoding
= encoding
;
959 bool wxTestFontEncoding(const wxNativeEncodingInfo
& info
)
962 fontspec
.Printf(wxT("-*-%s-*-*-*-*-*-*-*-*-*-*-%s-%s"),
963 !info
.facename
? wxT("*") : info
.facename
.c_str(),
964 info
.xregistry
.c_str(),
965 info
.xencoding
.c_str());
967 return wxTestFontSpec(fontspec
);
970 // ----------------------------------------------------------------------------
971 // X-specific functions
972 // ----------------------------------------------------------------------------
974 wxNativeFont
wxLoadQueryNearestFont(int pointSize
,
979 const wxString
&facename
,
980 wxFontEncoding encoding
,
983 if ( encoding
== wxFONTENCODING_DEFAULT
)
985 encoding
= wxFont::GetDefaultEncoding();
988 // first determine the encoding - if the font doesn't exist at all in this
989 // encoding, it's useless to do all other approximations (i.e. size,
990 // family &c don't matter much)
991 wxNativeEncodingInfo info
;
992 if ( encoding
== wxFONTENCODING_SYSTEM
)
994 // This will always work so we don't test to save time
995 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM
, &info
);
999 if ( !wxGetNativeFontEncoding(encoding
, &info
) ||
1000 !wxTestFontEncoding(info
) )
1003 if ( !wxFontMapper::Get()->GetAltForEncoding(encoding
, &info
) )
1004 #endif // wxUSE_FONTMAP
1006 // unspported encoding - replace it with the default
1008 // NB: we can't just return 0 from here because wxGTK code doesn't
1009 // check for it (i.e. it supposes that we'll always succeed),
1010 // so it would provoke a crash
1011 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM
, &info
);
1016 // OK, we have the correct xregistry/xencoding in info structure
1017 wxNativeFont font
= 0;
1019 // if we already have the X font name, try to use it
1020 if( xFontName
&& !xFontName
->empty() )
1023 // Make sure point size is correct for scale factor.
1025 wxStringTokenizer
tokenizer(*xFontName
, wxT("-"), wxTOKEN_RET_DELIMS
);
1026 wxString newFontName
;
1028 for(int i
= 0; i
< 8; i
++)
1029 newFontName
+= tokenizer
.NextToken();
1031 (void) tokenizer
.NextToken();
1033 newFontName
+= wxString::Format(wxT("%d-"), pointSize
);
1035 while(tokenizer
.HasMoreTokens())
1036 newFontName
+= tokenizer
.GetNextToken();
1038 font
= wxLoadFont(newFontName
);
1041 *xFontName
= newFontName
;
1046 // search up and down by stepsize 10
1047 int max_size
= pointSize
+ 20 * (1 + (pointSize
/180));
1048 int min_size
= pointSize
- 20 * (1 + (pointSize
/180));
1050 int i
, round
; // counters
1052 // first round: search for equal, then for smaller and for larger size
1053 // with the given weight and style
1054 int testweight
= weight
;
1055 int teststyle
= style
;
1057 for ( round
= 0; round
< 3; round
++ )
1059 // second round: use normal weight
1062 if ( testweight
!= wxNORMAL
)
1064 testweight
= wxNORMAL
;
1068 ++round
; // fall through to third round
1072 // third round: ... and use normal style
1075 if ( teststyle
!= wxNORMAL
)
1077 teststyle
= wxNORMAL
;
1084 // Search for equal or smaller size (approx.)
1085 for ( i
= pointSize
; !font
&& i
>= 10 && i
>= min_size
; i
-= 10 )
1087 font
= wxLoadQueryFont(i
, family
, teststyle
, testweight
, underlined
,
1088 facename
, info
.xregistry
, info
.xencoding
,
1092 // Search for larger size (approx.)
1093 for ( i
= pointSize
+ 10; !font
&& i
<= max_size
; i
+= 10 )
1095 font
= wxLoadQueryFont(i
, family
, teststyle
, testweight
, underlined
,
1096 facename
, info
.xregistry
, info
.xencoding
,
1101 // Try default family
1102 if ( !font
&& family
!= wxDEFAULT
)
1104 font
= wxLoadQueryFont(pointSize
, wxDEFAULT
, style
, weight
,
1105 underlined
, facename
,
1106 info
.xregistry
, info
.xencoding
,
1110 // ignore size, family, style and weight but try to find font with the
1111 // given facename and encoding
1114 font
= wxLoadQueryFont(120, wxDEFAULT
, wxNORMAL
, wxNORMAL
,
1115 underlined
, facename
,
1116 info
.xregistry
, info
.xencoding
,
1119 // ignore family as well
1122 font
= wxLoadQueryFont(120, wxDEFAULT
, wxNORMAL
, wxNORMAL
,
1123 underlined
, wxEmptyString
,
1124 info
.xregistry
, info
.xencoding
,
1127 // if it still failed, try to get the font of any size but
1128 // with the requested encoding: this can happen if the
1129 // encoding is only available in one size which happens to be
1130 // different from 120
1133 font
= wxLoadQueryFont(-1, wxDEFAULT
, wxNORMAL
, wxNORMAL
,
1134 false, wxEmptyString
,
1135 info
.xregistry
, info
.xencoding
,
1138 // this should never happen as we had tested for it in the
1139 // very beginning, but if it does, do return something non
1140 // NULL or we'd crash in wxFont code
1143 wxFAIL_MSG( wxT("this encoding should be available!") );
1145 font
= wxLoadQueryFont(-1,
1146 wxDEFAULT
, wxNORMAL
, wxNORMAL
,
1147 false, wxEmptyString
,
1159 // ----------------------------------------------------------------------------
1160 // private functions
1161 // ----------------------------------------------------------------------------
1163 // returns true if there are any fonts matching this font spec
1164 static bool wxTestFontSpec(const wxString
& fontspec
)
1166 // some X servers will fail to load this font because there are too many
1167 // matches so we must test explicitly for this
1168 if ( fontspec
== wxT("-*-*-*-*-*-*-*-*-*-*-*-*-*-*") )
1173 wxNativeFont test
= (wxNativeFont
) g_fontHash
->Get( fontspec
);
1179 test
= wxLoadFont(fontspec
);
1180 g_fontHash
->Put( fontspec
, (wxObject
*) test
);
1194 static wxNativeFont
wxLoadQueryFont(int pointSize
,
1198 bool WXUNUSED(underlined
),
1199 const wxString
& facename
,
1200 const wxString
& xregistry
,
1201 const wxString
& xencoding
,
1202 wxString
* xFontName
)
1207 case wxDECORATIVE
: xfamily
= wxT("lucida"); break;
1208 case wxROMAN
: xfamily
= wxT("times"); break;
1209 case wxMODERN
: xfamily
= wxT("courier"); break;
1210 case wxSWISS
: xfamily
= wxT("helvetica"); break;
1211 case wxTELETYPE
: xfamily
= wxT("lucidatypewriter"); break;
1212 case wxSCRIPT
: xfamily
= wxT("utopia"); break;
1213 default: xfamily
= wxT("*");
1221 xweight
= MWLF_WEIGHT_BOLD
;
1226 xweight
= MWLF_WEIGHT_LIGHT
;
1231 xweight
= MWLF_WEIGHT_NORMAL
;
1237 xweight
= MWLF_WEIGHT_DEFAULT
;
1241 GR_SCREEN_INFO screenInfo
;
1242 GrGetScreenInfo(& screenInfo
);
1244 int yPixelsPerCM
= screenInfo
.ydpcm
;
1246 // A point is 1/72 of an inch.
1247 // An inch is 2.541 cm.
1248 // So pixelHeight = (pointSize / 72) (inches) * 2.541 (for cm) * yPixelsPerCM (for pixels)
1249 // In fact pointSize is 10 * the normal point size so
1252 int pixelHeight
= (int) ( (((float)pointSize
) / 720.0) * 2.541 * (float) yPixelsPerCM
) ;
1254 // An alternative: assume that the screen is 72 dpi.
1255 //int pixelHeight = (int) (((float)pointSize / 720.0) * 72.0) ;
1256 //int pixelHeight = (int) ((float)pointSize / 10.0) ;
1259 logFont
.lfHeight
= pixelHeight
;
1260 logFont
.lfWidth
= 0;
1261 logFont
.lfEscapement
= 0;
1262 logFont
.lfOrientation
= 0;
1263 logFont
.lfWeight
= xweight
;
1264 logFont
.lfItalic
= (style
== wxNORMAL
? 0 : 1) ;
1265 logFont
.lfUnderline
= 0;
1266 logFont
.lfStrikeOut
= 0;
1267 logFont
.lfCharSet
= MWLF_CHARSET_DEFAULT
; // TODO: select appropriate one
1268 logFont
.lfOutPrecision
= MWLF_TYPE_DEFAULT
;
1269 logFont
.lfClipPrecision
= 0; // Not used
1270 logFont
.lfRoman
= (family
== wxROMAN
? 1 : 0) ;
1271 logFont
.lfSerif
= (family
== wxSWISS
? 0 : 1) ;
1272 logFont
.lfSansSerif
= !logFont
.lfSerif
;
1273 logFont
.lfModern
= (family
== wxMODERN
? 1 : 0) ;
1274 logFont
.lfProportional
= (family
== wxTELETYPE
? 0 : 1) ;
1275 logFont
.lfOblique
= 0;
1276 logFont
.lfSmallCaps
= 0;
1277 logFont
.lfPitch
= 0; // 0 = default
1278 strcpy(logFont
.lfFaceName
, facename
.c_str());
1280 XFontStruct
* fontInfo
= (XFontStruct
*) malloc(sizeof(XFontStruct
));
1281 fontInfo
->fid
= GrCreateFont((GR_CHAR
*) facename
.c_str(), pixelHeight
, & logFont
);
1282 GrGetFontInfo(fontInfo
->fid
, & fontInfo
->info
);
1283 return (wxNativeFont
) fontInfo
;
1287 if (!facename
.empty())
1289 fontSpec
.Printf(wxT("-*-%s-*-*-normal-*-*-*-*-*-*-*-*-*"),
1292 if ( wxTestFontSpec(fontSpec
) )
1296 //else: no such family, use default one instead
1303 fontSpec
.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
1305 if ( wxTestFontSpec(fontSpec
) )
1310 // fall through - try wxITALIC now
1313 fontSpec
.Printf(wxT("-*-%s-*-i-*-*-*-*-*-*-*-*-*-*"),
1315 if ( wxTestFontSpec(fontSpec
) )
1319 else if ( style
== wxITALIC
) // and not wxSLANT
1322 fontSpec
.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
1324 if ( wxTestFontSpec(fontSpec
) )
1330 // no italic, no slant - leave default
1337 wxFAIL_MSG(wxT("unknown font style"));
1338 // fall back to normal
1350 fontSpec
.Printf(wxT("-*-%s-bold-*-*-*-*-*-*-*-*-*-*-*"),
1352 if ( wxTestFontSpec(fontSpec
) )
1354 xweight
= wxT("bold");
1357 fontSpec
.Printf(wxT("-*-%s-heavy-*-*-*-*-*-*-*-*-*-*-*"),
1359 if ( wxTestFontSpec(fontSpec
) )
1361 xweight
= wxT("heavy");
1364 fontSpec
.Printf(wxT("-*-%s-extrabold-*-*-*-*-*-*-*-*-*-*-*"),
1366 if ( wxTestFontSpec(fontSpec
) )
1368 xweight
= wxT("extrabold");
1371 fontSpec
.Printf(wxT("-*-%s-demibold-*-*-*-*-*-*-*-*-*-*-*"),
1373 if ( wxTestFontSpec(fontSpec
) )
1375 xweight
= wxT("demibold");
1378 fontSpec
.Printf(wxT("-*-%s-black-*-*-*-*-*-*-*-*-*-*-*"),
1380 if ( wxTestFontSpec(fontSpec
) )
1382 xweight
= wxT("black");
1385 fontSpec
.Printf(wxT("-*-%s-ultrablack-*-*-*-*-*-*-*-*-*-*-*"),
1387 if ( wxTestFontSpec(fontSpec
) )
1389 xweight
= wxT("ultrablack");
1396 fontSpec
.Printf(wxT("-*-%s-light-*-*-*-*-*-*-*-*-*-*-*"),
1398 if ( wxTestFontSpec(fontSpec
) )
1400 xweight
= wxT("light");
1403 fontSpec
.Printf(wxT("-*-%s-thin-*-*-*-*-*-*-*-*-*-*-*"),
1405 if ( wxTestFontSpec(fontSpec
) )
1407 xweight
= wxT("thin");
1414 fontSpec
.Printf(wxT("-*-%s-medium-*-*-*-*-*-*-*-*-*-*-*"),
1416 if ( wxTestFontSpec(fontSpec
) )
1418 xweight
= wxT("medium");
1421 fontSpec
.Printf(wxT("-*-%s-normal-*-*-*-*-*-*-*-*-*-*-*"),
1423 if ( wxTestFontSpec(fontSpec
) )
1425 xweight
= wxT("normal");
1428 fontSpec
.Printf(wxT("-*-%s-regular-*-*-*-*-*-*-*-*-*-*-*"),
1430 if ( wxTestFontSpec(fontSpec
) )
1432 xweight
= wxT("regular");
1438 default: xweight
= wxT("*"); break;
1441 // if pointSize is -1, don't specify any
1443 if ( pointSize
== -1 )
1445 sizeSpec
= wxT('*');
1449 sizeSpec
.Printf(wxT("%d"), pointSize
);
1452 // construct the X font spec from our data
1453 fontSpec
.Printf(wxT("-*-%s-%s-%s-normal-*-*-%s-*-*-*-*-%s-%s"),
1454 xfamily
.c_str(), xweight
.c_str(), xstyle
.c_str(),
1455 sizeSpec
.c_str(), xregistry
.c_str(), xencoding
.c_str());
1458 *xFontName
= fontSpec
;
1460 return wxLoadFont(fontSpec
);
1465 // ----------------------------------------------------------------------------
1467 // ----------------------------------------------------------------------------
1469 class wxFontModule
: public wxModule
1476 DECLARE_DYNAMIC_CLASS(wxFontModule
)
1479 IMPLEMENT_DYNAMIC_CLASS(wxFontModule
, wxModule
)
1481 bool wxFontModule::OnInit()
1483 g_fontHash
= new wxHashTable( wxKEY_STRING
);
1488 void wxFontModule::OnExit()
1490 wxDELETE(g_fontHash
);
1493 #endif // GTK 2.0/1.x