]> git.saurik.com Git - wxWidgets.git/blame - src/unix/fontutil.cpp
Factor out text measurement from wxDC and wxWindow into wxTextMeasure.
[wxWidgets.git] / src / unix / fontutil.cpp
CommitLineData
7beba2fc 1/////////////////////////////////////////////////////////////////////////////
55034339 2// Name: src/unix/fontutil.cpp
b5791cc7 3// Purpose: Font helper functions for wxX11, wxGTK, wxMotif
7beba2fc
VZ
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 05.11.99
7// RCS-ID: $Id$
8// Copyright: (c) Vadim Zeitlin
65571936 9// Licence: wxWindows licence
7beba2fc
VZ
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
7beba2fc
VZ
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
d48d1eae
WS
27#include "wx/fontutil.h"
28
7beba2fc 29#ifndef WX_PRECOMP
d48d1eae 30 #include "wx/app.h"
0f6858b6 31 #include "wx/font.h" // wxFont enums
e4ffab29 32 #include "wx/encinfo.h"
32d4c30a 33 #include "wx/hash.h"
de6185e2 34 #include "wx/utils.h" // for wxGetDisplay()
02761f6c 35 #include "wx/module.h"
7beba2fc
VZ
36#endif // PCH
37
db16cab4
RR
38#include "wx/fontmap.h"
39#include "wx/tokenzr.h"
85ab460e 40#include "wx/fontenum.h"
db16cab4 41
2b5f62a0
VZ
42#if wxUSE_PANGO
43
44#include "pango/pango.h"
db16cab4 45
2b5f62a0 46#ifdef __WXGTK20__
29131e8a
VZ
47 #include "wx/gtk/private.h"
48 extern GtkWidget *wxGetRootWindow();
49
50 #define wxPANGO_CONV wxGTK_CONV_SYS
47239bd6 51 #define wxPANGO_CONV_BACK wxGTK_CONV_BACK_SYS
2b5f62a0 52#else
29131e8a
VZ
53 #include "wx/x11/private.h"
54 #include "wx/gtk/private/string.h"
55
0b2a860f
VZ
56 #define wxPANGO_CONV(s) s.utf8_str()
57 #define wxPANGO_CONV_BACK(s) wxString::FromUTF8Unchecked(s)
2b5f62a0 58#endif
db16cab4
RR
59
60// ----------------------------------------------------------------------------
61// wxNativeFontInfo
62// ----------------------------------------------------------------------------
63
64void wxNativeFontInfo::Init()
65{
66 description = NULL;
a349dc10
VZ
67 m_underlined = false;
68 m_strikethrough = false;
db16cab4
RR
69}
70
c45f5ae8 71void wxNativeFontInfo::Init(const wxNativeFontInfo& info)
fdf7514a
VS
72{
73 if (info.description)
a349dc10 74 {
fdf7514a 75 description = pango_font_description_copy(info.description);
a349dc10
VZ
76 m_underlined = info.GetUnderlined();
77 m_strikethrough = info.GetStrikethrough();
78 }
fdf7514a 79 else
a349dc10 80 {
82680055 81 description = NULL;
a349dc10
VZ
82 m_underlined = false;
83 m_strikethrough = false;
84 }
fdf7514a
VS
85}
86
82680055 87void wxNativeFontInfo::Free()
fdf7514a
VS
88{
89 if (description)
90 pango_font_description_free(description);
91}
92
db16cab4
RR
93int wxNativeFontInfo::GetPointSize() const
94{
95 return pango_font_description_get_size( description ) / PANGO_SCALE;
96}
97
98wxFontStyle wxNativeFontInfo::GetStyle() const
99{
100 wxFontStyle m_style = wxFONTSTYLE_NORMAL;
101
102 switch (pango_font_description_get_style( description ))
103 {
104 case PANGO_STYLE_NORMAL:
105 m_style = wxFONTSTYLE_NORMAL;
106 break;
107 case PANGO_STYLE_ITALIC:
108 m_style = wxFONTSTYLE_ITALIC;
109 break;
110 case PANGO_STYLE_OBLIQUE:
111 m_style = wxFONTSTYLE_SLANT;
112 break;
113 }
2b5f62a0 114
db16cab4
RR
115 return m_style;
116}
117
118wxFontWeight wxNativeFontInfo::GetWeight() const
119{
0f6858b6
RR
120 // We seem to currently initialize only by string.
121 // In that case PANGO_FONT_MASK_WEIGHT is always set.
6aea1e4a
FM
122 // if (!(pango_font_description_get_set_fields(description) & PANGO_FONT_MASK_WEIGHT))
123 // return wxFONTWEIGHT_NORMAL;
db16cab4 124
0f6858b6
RR
125 PangoWeight pango_weight = pango_font_description_get_weight( description );
126
127 // Until the API can be changed the following ranges of weight values are used:
128 // wxFONTWEIGHT_LIGHT: 100 .. 349 - range of 250
129 // wxFONTWEIGHT_NORMAL: 350 .. 599 - range of 250
130 // wxFONTWEIGHT_BOLD: 600 .. 900 - range of 301 (600 is "semibold" already)
131
132 if (pango_weight >= 600)
133 return wxFONTWEIGHT_BOLD;
134
135 if (pango_weight < 350)
136 return wxFONTWEIGHT_LIGHT;
2b5f62a0 137
0f6858b6 138 return wxFONTWEIGHT_NORMAL;
db16cab4
RR
139}
140
141bool wxNativeFontInfo::GetUnderlined() const
142{
a349dc10 143 return m_underlined;
db16cab4
RR
144}
145
ed7f03bb
VZ
146bool wxNativeFontInfo::GetStrikethrough() const
147{
a349dc10 148 return m_strikethrough;
ed7f03bb
VZ
149}
150
db16cab4
RR
151wxString wxNativeFontInfo::GetFaceName() const
152{
c45f5ae8 153 // the Pango "family" is the wx "face name"
47239bd6 154 return wxPANGO_CONV_BACK(pango_font_description_get_family(description));
db16cab4
RR
155}
156
157wxFontFamily wxNativeFontInfo::GetFamily() const
158{
6aea1e4a 159 wxFontFamily ret = wxFONTFAMILY_UNKNOWN;
c45f5ae8
FM
160
161 const char *family_name = pango_font_description_get_family( description );
162
34a35823
MW
163 // note: not passing -1 as the 2nd parameter to g_ascii_strdown to work
164 // around a bug in the 64-bit glib shipped with solaris 10, -1 causes it
165 // to try to allocate 2^32 bytes.
23f4f495
VZ
166 if ( !family_name )
167 return ret;
8361f92b
VZ
168 wxGtkString family_text(g_ascii_strdown(family_name, strlen(family_name)));
169
6aea1e4a
FM
170 // Check for some common fonts, to salvage what we can from the current
171 // win32 centric wxFont API:
36cc7650 172 if (wxStrnicmp( family_text, "monospace", 9 ) == 0)
6aea1e4a 173 ret = wxFONTFAMILY_TELETYPE; // begins with "Monospace"
36cc7650 174 else if (wxStrnicmp( family_text, "courier", 7 ) == 0)
6aea1e4a 175 ret = wxFONTFAMILY_TELETYPE; // begins with "Courier"
ff654490 176#if defined(__WXGTK20__) || defined(HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE)
b67d14be
MR
177 else
178 {
179 PangoFontFamily **families;
b20cb045 180 PangoFontFamily *family = NULL;
b67d14be
MR
181 int n_families;
182 pango_context_list_families(
38d446db 183#ifdef __WXGTK20__
b67d14be 184 gtk_widget_get_pango_context( wxGetRootWindow() ),
38d446db 185#else
b67d14be 186 wxTheApp->GetPangoContext(),
38d446db 187#endif
b67d14be 188 &families, &n_families);
38d446db 189
c45f5ae8 190 for (int i = 0; i < n_families; ++i)
38d446db 191 {
c45f5ae8
FM
192 if (g_ascii_strcasecmp(pango_font_family_get_name( families[i] ),
193 pango_font_description_get_family( description )) == 0 )
b67d14be
MR
194 {
195 family = families[i];
196 break;
197 }
38d446db 198 }
38d446db 199
b67d14be 200 g_free(families);
38d446db 201
03647350 202 // Some gtk+ systems might query for a non-existing font from
c45f5ae8
FM
203 // wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) on initialization,
204 // don't assert until wxSystemSettings::GetFont is checked for this - MR
6aea1e4a 205 // wxASSERT_MSG( family, "No appropriate PangoFontFamily found for ::description" );
38d446db 206
b20cb045 207 if (family != NULL && pango_font_family_is_monospace( family ))
b67d14be
MR
208 ret = wxFONTFAMILY_TELETYPE; // is deemed a monospace font by pango
209 }
ff654490 210#endif // GTK+ 2 || HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE
38d446db 211
6aea1e4a 212 if (ret == wxFONTFAMILY_UNKNOWN)
b67d14be 213 {
6aea1e4a 214 if (strstr( family_text, "sans" ) != NULL || strstr( family_text, "Sans" ) != NULL)
c45f5ae8 215 // checked before serif, so that "* Sans Serif" fonts are detected correctly
6aea1e4a
FM
216 ret = wxFONTFAMILY_SWISS; // contains "Sans"
217 else if (strstr( family_text, "serif" ) != NULL || strstr( family_text, "Serif" ) != NULL)
218 ret = wxFONTFAMILY_ROMAN; // contains "Serif"
36cc7650 219 else if (wxStrnicmp( family_text, "times", 5 ) == 0)
6aea1e4a 220 ret = wxFONTFAMILY_ROMAN; // begins with "Times"
36cc7650 221 else if (wxStrnicmp( family_text, "old", 3 ) == 0)
6aea1e4a 222 ret = wxFONTFAMILY_DECORATIVE; // begins with "Old" - "Old English", "Old Town"
b67d14be
MR
223 }
224
b67d14be 225 return ret;
db16cab4
RR
226}
227
228wxFontEncoding wxNativeFontInfo::GetEncoding() const
229{
230 return wxFONTENCODING_SYSTEM;
231}
232
8a15e8ba 233void wxNativeFontInfo::SetPointSize(int pointsize)
3398cf2c 234{
8a15e8ba 235 pango_font_description_set_size( description, pointsize * PANGO_SCALE );
3398cf2c
VZ
236}
237
7533ba25 238void wxNativeFontInfo::SetStyle(wxFontStyle style)
3398cf2c 239{
7533ba25
MR
240 switch (style)
241 {
242 case wxFONTSTYLE_ITALIC:
243 pango_font_description_set_style( description, PANGO_STYLE_ITALIC );
244 break;
245 case wxFONTSTYLE_SLANT:
246 pango_font_description_set_style( description, PANGO_STYLE_OBLIQUE );
247 break;
248 default:
6aea1e4a 249 wxFAIL_MSG( "unknown font style" );
7533ba25
MR
250 // fall through
251 case wxFONTSTYLE_NORMAL:
252 pango_font_description_set_style( description, PANGO_STYLE_NORMAL );
253 break;
254 }
3398cf2c
VZ
255}
256
7533ba25 257void wxNativeFontInfo::SetWeight(wxFontWeight weight)
3398cf2c 258{
7533ba25
MR
259 switch (weight)
260 {
261 case wxFONTWEIGHT_BOLD:
262 pango_font_description_set_weight(description, PANGO_WEIGHT_BOLD);
263 break;
264 case wxFONTWEIGHT_LIGHT:
265 pango_font_description_set_weight(description, PANGO_WEIGHT_LIGHT);
266 break;
267 default:
6aea1e4a 268 wxFAIL_MSG( "unknown font weight" );
7533ba25
MR
269 // fall through
270 case wxFONTWEIGHT_NORMAL:
271 pango_font_description_set_weight(description, PANGO_WEIGHT_NORMAL);
272 }
3398cf2c
VZ
273}
274
a349dc10 275void wxNativeFontInfo::SetUnderlined(bool underlined)
3398cf2c 276{
a349dc10
VZ
277 // Pango doesn't have the underlined attribute so we store it separately
278 // (and handle it specially in wxWindowDCImpl::DoDrawText()).
279 m_underlined = underlined;
3398cf2c
VZ
280}
281
a349dc10 282void wxNativeFontInfo::SetStrikethrough(bool strikethrough)
e9270aaa 283{
a349dc10
VZ
284 // As with the underlined attribute above, we handle this one separately as
285 // Pango doesn't support it as part of the font description.
286 m_strikethrough = strikethrough;
e9270aaa
VZ
287}
288
85ab460e 289bool wxNativeFontInfo::SetFaceName(const wxString& facename)
3398cf2c 290{
29131e8a 291 pango_font_description_set_family(description, wxPANGO_CONV(facename));
6aea1e4a 292
3a6a0082
FM
293 // we return true because Pango doesn't tell us if the call failed or not;
294 // instead on wxGTK wxFont::SetFaceName() will call wxFontBase::SetFaceName()
295 // which does the check
85ab460e 296 return true;
3398cf2c
VZ
297}
298
6aea1e4a 299void wxNativeFontInfo::SetFamily(wxFontFamily family)
3398cf2c 300{
6aea1e4a
FM
301 wxArrayString facename;
302
303 // the list of fonts associated with a family was partially
304 // taken from http://www.codestyle.org/css/font-family
305
306 switch ( family )
307 {
308 case wxFONTFAMILY_SCRIPT:
309 // corresponds to the cursive font family in the page linked above
310 facename.Add(wxS("URW Chancery L"));
311 facename.Add(wxS("Comic Sans MS"));
312 break;
313
314 case wxFONTFAMILY_DECORATIVE:
315 // corresponds to the fantasy font family in the page linked above
316 facename.Add(wxS("Impact"));
317 break;
318
319 case wxFONTFAMILY_ROMAN:
320 // corresponds to the serif font family in the page linked above
1b636985 321 facename.Add(wxS("Serif"));
6aea1e4a 322 facename.Add(wxS("DejaVu Serif"));
1b636985
VZ
323 facename.Add(wxS("DejaVu LGC Serif"));
324 facename.Add(wxS("Bitstream Vera Serif"));
325 facename.Add(wxS("Liberation Serif"));
6aea1e4a 326 facename.Add(wxS("FreeSerif"));
1b636985 327 facename.Add(wxS("Luxi Serif"));
6aea1e4a 328 facename.Add(wxS("Times New Roman"));
1b636985
VZ
329 facename.Add(wxS("Century Schoolbook L"));
330 facename.Add(wxS("URW Bookman L"));
331 facename.Add(wxS("URW Palladio L"));
6aea1e4a
FM
332 facename.Add(wxS("Times"));
333 break;
334
335 case wxFONTFAMILY_TELETYPE:
336 case wxFONTFAMILY_MODERN:
337 // corresponds to the monospace font family in the page linked above
1b636985 338 facename.Add(wxS("Monospace"));
6aea1e4a 339 facename.Add(wxS("DejaVu Sans Mono"));
1b636985 340 facename.Add(wxS("DejaVu LGC Sans Mono"));
6aea1e4a 341 facename.Add(wxS("Bitstream Vera Sans Mono"));
1b636985 342 facename.Add(wxS("Liberation Mono"));
6aea1e4a 343 facename.Add(wxS("FreeMono"));
1b636985 344 facename.Add(wxS("Luxi Mono"));
6aea1e4a 345 facename.Add(wxS("Courier New"));
1b636985
VZ
346 facename.Add(wxS("Lucida Sans Typewriter"));
347 facename.Add(wxS("Nimbus Mono L"));
348 facename.Add(wxS("Andale Mono"));
6aea1e4a
FM
349 facename.Add(wxS("Courier"));
350 break;
351
352 case wxFONTFAMILY_SWISS:
353 case wxFONTFAMILY_DEFAULT:
354 default:
355 // corresponds to the sans-serif font family in the page linked above
1b636985 356 facename.Add(wxS("Sans"));
6aea1e4a 357 facename.Add(wxS("DejaVu Sans"));
1b636985 358 facename.Add(wxS("DejaVu LGC Sans"));
6aea1e4a 359 facename.Add(wxS("Bitstream Vera Sans"));
1b636985 360 facename.Add(wxS("Liberation Sans"));
6aea1e4a 361 facename.Add(wxS("FreeSans"));
1b636985
VZ
362 facename.Add(wxS("Luxi Sans"));
363 facename.Add(wxS("Arial"));
364 facename.Add(wxS("Lucida Sans"));
365 facename.Add(wxS("Nimbus Sans L"));
366 facename.Add(wxS("URW Gothic L"));
6aea1e4a
FM
367 break;
368 }
369
370 SetFaceName(facename);
3398cf2c
VZ
371}
372
373void wxNativeFontInfo::SetEncoding(wxFontEncoding WXUNUSED(encoding))
374{
6aea1e4a 375 wxFAIL_MSG( "not implemented: Pango encoding is always UTF8" );
3398cf2c
VZ
376}
377
db16cab4
RR
378bool wxNativeFontInfo::FromString(const wxString& s)
379{
a349dc10
VZ
380 wxString str(s);
381
382 // Pango font description doesn't have 'underlined' or 'strikethrough'
383 // attributes, so we handle them specially by extracting them from the
384 // string before passing it to Pango.
385 m_underlined = str.StartsWith(wxS("underlined "), &str);
386 m_strikethrough = str.StartsWith(wxS("strikethrough "), &str);
387
db16cab4
RR
388 if (description)
389 pango_font_description_free( description );
390
7c55c50e
VZ
391 // there is a bug in at least pango <= 1.13 which makes it (or its backends)
392 // segfault for very big point sizes and for negative point sizes.
393 // To workaround that bug for pango <= 1.13
394 // (see http://bugzilla.gnome.org/show_bug.cgi?id=340229)
395 // we do the check on the size here using same (arbitrary) limits used by
396 // pango > 1.13. Note that the segfault could happen also for pointsize
397 // smaller than this limit !!
6aea1e4a 398 const size_t pos = str.find_last_of(wxS(" "));
7c55c50e
VZ
399 double size;
400 if ( pos != wxString::npos && wxString(str, pos + 1).ToDouble(&size) )
401 {
402 wxString sizeStr;
403 if ( size < 1 )
6aea1e4a 404 sizeStr = wxS("1");
c23d4004 405 else if ( size >= 1E6 )
6aea1e4a 406 sizeStr = wxS("1E6");
7c55c50e
VZ
407
408 if ( !sizeStr.empty() )
409 {
410 // replace the old size with the adjusted one
411 str = wxString(s, 0, pos) + sizeStr;
412 }
413 }
414
29131e8a 415 description = pango_font_description_from_string(wxPANGO_CONV(str));
db16cab4 416
8d22935d 417#if wxUSE_FONTENUM
85ab460e
VZ
418 // ensure a valid facename is selected
419 if (!wxFontEnumerator::IsValidFacename(GetFaceName()))
420 SetFaceName(wxNORMAL_FONT->GetFaceName());
8d22935d 421#endif // wxUSE_FONTENUM
85ab460e 422
55034339 423 return true;
db16cab4
RR
424}
425
426wxString wxNativeFontInfo::ToString() const
427{
8361f92b 428 wxGtkString str(pango_font_description_to_string( description ));
a349dc10
VZ
429 wxString desc = wxPANGO_CONV_BACK(str);
430
431 // Augment the string with the attributes not handled by Pango.
432 //
433 // Notice that we must add them in the same order they are extracted in
434 // FromString() above.
435 if (m_strikethrough)
436 desc.insert(0, wxS("strikethrough "));
437 if (m_underlined)
438 desc.insert(0, wxS("underlined "));
439
440 return desc;
db16cab4
RR
441}
442
443bool wxNativeFontInfo::FromUserString(const wxString& s)
444{
445 return FromString( s );
446}
447
448wxString wxNativeFontInfo::ToUserString() const
449{
450 return ToString();
451}
452
2b5f62a0 453#else // GTK+ 1.x
db16cab4 454
79e4b627 455#ifdef __X__
4ea45e6b
VZ
456 #ifdef __VMS__
457 #pragma message disable nosimpint
458 #endif
459
460 #include <X11/Xlib.h>
461
462 #ifdef __VMS__
463 #pragma message enable nosimpint
464 #endif
79e4b627 465
79e4b627 466#elif defined(__WXGTK__)
4ea45e6b
VZ
467 // we have to declare struct tm to avoid problems with first forward
468 // declaring it in C code (glib.h included from gdk.h does it) and then
469 // defining it when time.h is included from the headers below - this is
470 // known not to work at least with Sun CC 6.01
471 #include <time.h>
472
473 #include <gdk/gdk.h>
79e4b627
VZ
474#endif
475
2e0e025e
RR
476
477// ----------------------------------------------------------------------------
478// private data
479// ----------------------------------------------------------------------------
480
d3b9f782 481static wxHashTable *g_fontHash = NULL;
7beba2fc
VZ
482
483// ----------------------------------------------------------------------------
484// private functions
485// ----------------------------------------------------------------------------
486
487// define the functions to create and destroy native fonts for this toolkit
488#ifdef __X__
3fe34ed0 489 wxNativeFont wxLoadFont(const wxString& fontSpec)
7beba2fc
VZ
490 {
491 return XLoadQueryFont((Display *)wxGetDisplay(), fontSpec);
492 }
493
409d5a58 494 inline void wxFreeFont(wxNativeFont font)
7beba2fc 495 {
a5fc62a1 496 XFreeFont((Display *)wxGetDisplay(), (XFontStruct *)font);
7beba2fc
VZ
497 }
498#elif defined(__WXGTK__)
3fe34ed0 499 wxNativeFont wxLoadFont(const wxString& fontSpec)
7beba2fc 500 {
8fa3a431
VZ
501 // VZ: we should use gdk_fontset_load() instead of gdk_font_load()
502 // here to be able to display Japanese fonts correctly (at least
503 // this is what people report) but unfortunately doing it results
504 // in tons of warnings when using GTK with "normal" European
505 // languages and so we can't always do it and I don't know enough
506 // to determine when should this be done... (FIXME)
507 return gdk_font_load( wxConvertWX2MB(fontSpec) );
7beba2fc
VZ
508 }
509
409d5a58 510 inline void wxFreeFont(wxNativeFont font)
7beba2fc
VZ
511 {
512 gdk_font_unref(font);
513 }
514#else
515 #error "Unknown GUI toolkit"
516#endif
517
518static bool wxTestFontSpec(const wxString& fontspec);
519
520static wxNativeFont wxLoadQueryFont(int pointSize,
521 int family,
522 int style,
523 int weight,
524 bool underlined,
525 const wxString& facename,
526 const wxString& xregistry,
30764ab5
VZ
527 const wxString& xencoding,
528 wxString* xFontName);
7beba2fc
VZ
529
530// ============================================================================
531// implementation
532// ============================================================================
533
534// ----------------------------------------------------------------------------
535// wxNativeEncodingInfo
536// ----------------------------------------------------------------------------
537
538// convert to/from the string representation: format is
1e1d0be1 539// encodingid;registry;encoding[;facename]
7beba2fc
VZ
540bool wxNativeEncodingInfo::FromString(const wxString& s)
541{
6c49baf2 542 // use ";", not "-" because it may be part of encoding name
9a83f860 543 wxStringTokenizer tokenizer(s, wxT(";"));
1e1d0be1
VS
544
545 wxString encid = tokenizer.GetNextToken();
546 long enc;
547 if ( !encid.ToLong(&enc) )
55034339 548 return false;
1e1d0be1 549 encoding = (wxFontEncoding)enc;
7beba2fc
VZ
550
551 xregistry = tokenizer.GetNextToken();
552 if ( !xregistry )
55034339 553 return false;
7beba2fc
VZ
554
555 xencoding = tokenizer.GetNextToken();
556 if ( !xencoding )
55034339 557 return false;
7beba2fc
VZ
558
559 // ok even if empty
560 facename = tokenizer.GetNextToken();
561
55034339 562 return true;
7beba2fc
VZ
563}
564
565wxString wxNativeEncodingInfo::ToString() const
566{
567 wxString s;
9a83f860 568 s << (long)encoding << wxT(';') << xregistry << wxT(';') << xencoding;
55034339 569 if ( !facename.empty() )
7beba2fc 570 {
9a83f860 571 s << wxT(';') << facename;
7beba2fc
VZ
572 }
573
574 return s;
575}
576
ab5fe833
VZ
577// ----------------------------------------------------------------------------
578// wxNativeFontInfo
579// ----------------------------------------------------------------------------
580
581void wxNativeFontInfo::Init()
582{
55034339 583 m_isDefault = true;
ab5fe833
VZ
584}
585
586bool wxNativeFontInfo::FromString(const wxString& s)
587{
9a83f860 588 wxStringTokenizer tokenizer(s, wxT(";"));
ab5fe833
VZ
589
590 // check the version
591 wxString token = tokenizer.GetNextToken();
9a83f860 592 if ( token != wxT('0') )
55034339 593 return false;
ab5fe833
VZ
594
595 xFontName = tokenizer.GetNextToken();
596
597 // this should be the end
598 if ( tokenizer.HasMoreTokens() )
55034339 599 return false;
ab5fe833
VZ
600
601 return FromXFontName(xFontName);
602}
603
604wxString wxNativeFontInfo::ToString() const
605{
606 // 0 is the version
9a83f860 607 return wxString::Format(wxT("%d;%s"), 0, GetXFontName().c_str());
ab5fe833
VZ
608}
609
610bool wxNativeFontInfo::FromUserString(const wxString& s)
611{
612 return FromXFontName(s);
613}
614
615wxString wxNativeFontInfo::ToUserString() const
616{
617 return GetXFontName();
618}
619
409d5a58
VZ
620bool wxNativeFontInfo::HasElements() const
621{
622 // we suppose that the foundry is never empty, so if it is it means that we
623 // had never parsed the XLFD
624 return !fontElements[0].empty();
625}
626
53f6aab7
VZ
627wxString wxNativeFontInfo::GetXFontComponent(wxXLFDField field) const
628{
9a83f860 629 wxCHECK_MSG( field < wxXLFD_MAX, wxEmptyString, wxT("invalid XLFD field") );
53f6aab7 630
409d5a58 631 if ( !HasElements() )
53f6aab7 632 {
f48a1159 633 if ( !const_cast<wxNativeFontInfo *>(this)->FromXFontName(xFontName) )
55034339 634 return wxEmptyString;
53f6aab7
VZ
635 }
636
637 return fontElements[field];
638}
639
295272bd 640bool wxNativeFontInfo::FromXFontName(const wxString& fontname)
ab5fe833
VZ
641{
642 // TODO: we should be able to handle the font aliases here, but how?
9a83f860 643 wxStringTokenizer tokenizer(fontname, wxT("-"));
409d5a58
VZ
644
645 // skip the leading, usually empty field (font name registry)
646 if ( !tokenizer.HasMoreTokens() )
55034339 647 return false;
409d5a58
VZ
648
649 (void)tokenizer.GetNextToken();
ab5fe833
VZ
650
651 for ( size_t n = 0; n < WXSIZEOF(fontElements); n++ )
652 {
653 if ( !tokenizer.HasMoreTokens() )
654 {
655 // not enough elements in the XLFD - or maybe an alias
55034339 656 return false;
ab5fe833
VZ
657 }
658
b4e4abb5 659 wxString field = tokenizer.GetNextToken();
9a83f860 660 if ( !field.empty() && field != wxT('*') )
b4e4abb5
VZ
661 {
662 // we're really initialized now
55034339 663 m_isDefault = false;
b4e4abb5
VZ
664 }
665
666 fontElements[n] = field;
ab5fe833
VZ
667 }
668
669 // this should be all
011ba5ed 670 if ( tokenizer.HasMoreTokens() )
55034339 671 return false;
011ba5ed 672
55034339 673 return true;
ab5fe833
VZ
674}
675
676wxString wxNativeFontInfo::GetXFontName() const
677{
678 if ( xFontName.empty() )
679 {
680 for ( size_t n = 0; n < WXSIZEOF(fontElements); n++ )
681 {
682 // replace the non specified elements with '*' except for the
683 // additional style which is usually just omitted
684 wxString elt = fontElements[n];
409d5a58 685 if ( elt.empty() && n != wxXLFD_ADDSTYLE )
ab5fe833 686 {
9a83f860 687 elt = wxT('*');
ab5fe833
VZ
688 }
689
f48a1159 690 const_cast<wxNativeFontInfo *>(this)->xFontName << wxT('-') << elt;
ab5fe833
VZ
691 }
692 }
693
694 return xFontName;
695}
696
409d5a58
VZ
697void
698wxNativeFontInfo::SetXFontComponent(wxXLFDField field, const wxString& value)
699{
9a83f860 700 wxCHECK_RET( field < wxXLFD_MAX, wxT("invalid XLFD field") );
409d5a58
VZ
701
702 // this class should be initialized with a valid font spec first and only
703 // then the fields may be modified!
9a83f860 704 wxASSERT_MSG( !IsDefault(), wxT("can't modify an uninitialized XLFD") );
409d5a58
VZ
705
706 if ( !HasElements() )
707 {
f48a1159 708 if ( !const_cast<wxNativeFontInfo *>(this)->FromXFontName(xFontName) )
409d5a58 709 {
9a83f860 710 wxFAIL_MSG( wxT("can't set font element for invalid XLFD") );
409d5a58
VZ
711
712 return;
713 }
714 }
715
716 fontElements[field] = value;
717
718 // invalidate the XFLD, it doesn't correspond to the font elements any more
719 xFontName.clear();
720}
721
722void wxNativeFontInfo::SetXFontName(const wxString& xFontName_)
723{
724 // invalidate the font elements, GetXFontComponent() will reparse the XLFD
725 fontElements[0].clear();
726
727 xFontName = xFontName_;
728
55034339 729 m_isDefault = false;
409d5a58
VZ
730}
731
2b5f62a0
VZ
732int wxNativeFontInfo::GetPointSize() const
733{
734 const wxString s = GetXFontComponent(wxXLFD_POINTSIZE);
735
736 // return -1 to indicate that the size is unknown
737 long l;
738 return s.ToLong(&l) ? l : -1;
739}
740
741wxFontStyle wxNativeFontInfo::GetStyle() const
742{
743 const wxString s = GetXFontComponent(wxXLFD_SLANT);
744
745 if ( s.length() != 1 )
746 {
747 // it is really unknown but we don't have any way to return it from
748 // here
749 return wxFONTSTYLE_NORMAL;
750 }
751
102798af 752 switch ( s[0].GetValue() )
2b5f62a0
VZ
753 {
754 default:
755 // again, unknown but consider normal by default
756
9a83f860 757 case wxT('r'):
2b5f62a0
VZ
758 return wxFONTSTYLE_NORMAL;
759
9a83f860 760 case wxT('i'):
2b5f62a0
VZ
761 return wxFONTSTYLE_ITALIC;
762
9a83f860 763 case wxT('o'):
2b5f62a0
VZ
764 return wxFONTSTYLE_SLANT;
765 }
766}
767
768wxFontWeight wxNativeFontInfo::GetWeight() const
769{
770 const wxString s = GetXFontComponent(wxXLFD_WEIGHT).MakeLower();
9a83f860 771 if ( s.find(wxT("bold")) != wxString::npos || s == wxT("black") )
2b5f62a0 772 return wxFONTWEIGHT_BOLD;
9a83f860 773 else if ( s == wxT("light") )
2b5f62a0
VZ
774 return wxFONTWEIGHT_LIGHT;
775
776 return wxFONTWEIGHT_NORMAL;
777}
778
779bool wxNativeFontInfo::GetUnderlined() const
780{
781 // X fonts are never underlined
55034339 782 return false;
2b5f62a0
VZ
783}
784
785wxString wxNativeFontInfo::GetFaceName() const
786{
77ffb593 787 // wxWidgets facename probably more accurately corresponds to X family
2b5f62a0
VZ
788 return GetXFontComponent(wxXLFD_FAMILY);
789}
790
791wxFontFamily wxNativeFontInfo::GetFamily() const
792{
77ffb593 793 // and wxWidgets family -- to X foundry, but we have to translate it to
2b5f62a0 794 // wxFontFamily somehow...
9a83f860 795 wxFAIL_MSG(wxT("not implemented")); // GetXFontComponent(wxXLFD_FOUNDRY);
2b5f62a0
VZ
796
797 return wxFONTFAMILY_DEFAULT;
798}
799
800wxFontEncoding wxNativeFontInfo::GetEncoding() const
801{
802 // we already have the code for this but need to refactor it first
9a83f860 803 wxFAIL_MSG( wxT("not implemented") );
2b5f62a0
VZ
804
805 return wxFONTENCODING_MAX;
806}
807
808void wxNativeFontInfo::SetPointSize(int pointsize)
809{
9a83f860 810 SetXFontComponent(wxXLFD_POINTSIZE, wxString::Format(wxT("%d"), pointsize));
2b5f62a0
VZ
811}
812
813void wxNativeFontInfo::SetStyle(wxFontStyle style)
814{
815 wxString s;
816 switch ( style )
817 {
818 case wxFONTSTYLE_ITALIC:
9a83f860 819 s = wxT('i');
2b5f62a0
VZ
820 break;
821
822 case wxFONTSTYLE_SLANT:
9a83f860 823 s = wxT('o');
2b5f62a0
VZ
824 break;
825
826 case wxFONTSTYLE_NORMAL:
9a83f860 827 s = wxT('r');
2b5f62a0
VZ
828
829 default:
9a83f860 830 wxFAIL_MSG( wxT("unknown wxFontStyle in wxNativeFontInfo::SetStyle") );
2b5f62a0
VZ
831 return;
832 }
833
834 SetXFontComponent(wxXLFD_SLANT, s);
835}
836
837void wxNativeFontInfo::SetWeight(wxFontWeight weight)
838{
839 wxString s;
840 switch ( weight )
841 {
842 case wxFONTWEIGHT_BOLD:
9a83f860 843 s = wxT("bold");
2b5f62a0
VZ
844 break;
845
846 case wxFONTWEIGHT_LIGHT:
9a83f860 847 s = wxT("light");
2b5f62a0
VZ
848 break;
849
850 case wxFONTWEIGHT_NORMAL:
9a83f860 851 s = wxT("medium");
2b5f62a0
VZ
852 break;
853
854 default:
9a83f860 855 wxFAIL_MSG( wxT("unknown wxFontWeight in wxNativeFontInfo::SetWeight") );
2b5f62a0
VZ
856 return;
857 }
858
859 SetXFontComponent(wxXLFD_WEIGHT, s);
860}
861
862void wxNativeFontInfo::SetUnderlined(bool WXUNUSED(underlined))
863{
864 // can't do this under X
865}
866
ed7f03bb
VZ
867void wxNativeFontInfo::SetStrikethrough(bool WXUNUSED(strikethrough))
868{
869 // this is not supported by Pango fonts neither
870}
871
85ab460e 872bool wxNativeFontInfo::SetFaceName(const wxString& facename)
2b5f62a0
VZ
873{
874 SetXFontComponent(wxXLFD_FAMILY, facename);
85ab460e 875 return true;
2b5f62a0
VZ
876}
877
55034339 878void wxNativeFontInfo::SetFamily(wxFontFamily WXUNUSED(family))
2b5f62a0
VZ
879{
880 // wxFontFamily -> X foundry, anyone?
9a83f860 881 wxFAIL_MSG( wxT("not implemented") );
2b5f62a0
VZ
882
883 // SetXFontComponent(wxXLFD_FOUNDRY, ...);
884}
885
886void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding)
887{
888 wxNativeEncodingInfo info;
889 if ( wxGetNativeFontEncoding(encoding, &info) )
890 {
891 SetXFontComponent(wxXLFD_ENCODING, info.xencoding);
892 SetXFontComponent(wxXLFD_REGISTRY, info.xregistry);
893 }
894}
895
7beba2fc
VZ
896// ----------------------------------------------------------------------------
897// common functions
898// ----------------------------------------------------------------------------
899
900bool wxGetNativeFontEncoding(wxFontEncoding encoding,
901 wxNativeEncodingInfo *info)
902{
9a83f860 903 wxCHECK_MSG( info, false, wxT("bad pointer in wxGetNativeFontEncoding") );
7beba2fc
VZ
904
905 if ( encoding == wxFONTENCODING_DEFAULT )
906 {
907 encoding = wxFont::GetDefaultEncoding();
908 }
909
910 switch ( encoding )
911 {
912 case wxFONTENCODING_ISO8859_1:
913 case wxFONTENCODING_ISO8859_2:
914 case wxFONTENCODING_ISO8859_3:
915 case wxFONTENCODING_ISO8859_4:
916 case wxFONTENCODING_ISO8859_5:
917 case wxFONTENCODING_ISO8859_6:
918 case wxFONTENCODING_ISO8859_7:
919 case wxFONTENCODING_ISO8859_8:
920 case wxFONTENCODING_ISO8859_9:
921 case wxFONTENCODING_ISO8859_10:
922 case wxFONTENCODING_ISO8859_11:
80a24267 923 case wxFONTENCODING_ISO8859_12:
7beba2fc
VZ
924 case wxFONTENCODING_ISO8859_13:
925 case wxFONTENCODING_ISO8859_14:
926 case wxFONTENCODING_ISO8859_15:
927 {
928 int cp = encoding - wxFONTENCODING_ISO8859_1 + 1;
929 info->xregistry = wxT("iso8859");
930 info->xencoding.Printf(wxT("%d"), cp);
931 }
932 break;
933
bb84929e 934 case wxFONTENCODING_UTF8:
5707316c 935 info->xregistry = wxT("iso10646");
bb84929e
VZ
936 info->xencoding = wxT("*");
937 break;
938
2b5f62a0 939 case wxFONTENCODING_GB2312:
82680055 940 info->xregistry = wxT("GB2312"); // or the otherway round?
2b5f62a0
VZ
941 info->xencoding = wxT("*");
942 break;
943
7beba2fc 944 case wxFONTENCODING_KOI8:
15ad38c3 945 case wxFONTENCODING_KOI8_U:
7beba2fc
VZ
946 info->xregistry = wxT("koi8");
947
5707316c 948 // we don't make distinction between koi8-r, koi8-u and koi8-ru (so far)
7beba2fc
VZ
949 info->xencoding = wxT("*");
950 break;
951
952 case wxFONTENCODING_CP1250:
953 case wxFONTENCODING_CP1251:
954 case wxFONTENCODING_CP1252:
955 case wxFONTENCODING_CP1253:
956 case wxFONTENCODING_CP1254:
957 case wxFONTENCODING_CP1255:
958 case wxFONTENCODING_CP1256:
959 case wxFONTENCODING_CP1257:
960 {
961 int cp = encoding - wxFONTENCODING_CP1250 + 1250;
962 info->xregistry = wxT("microsoft");
963 info->xencoding.Printf(wxT("cp%d"), cp);
964 }
965 break;
966
d946915c
MB
967 case wxFONTENCODING_EUC_JP:
968 case wxFONTENCODING_SHIFT_JIS:
969 info->xregistry = "jis*";
970 info->xencoding = "*";
971 break;
972
7beba2fc
VZ
973 case wxFONTENCODING_SYSTEM:
974 info->xregistry =
81c67e27 975 info->xencoding = wxT("*");
7beba2fc
VZ
976 break;
977
978 default:
979 // don't know how to translate this encoding into X fontspec
55034339 980 return false;
7beba2fc
VZ
981 }
982
ab5fe833 983 info->encoding = encoding;
6b0eebc5 984
55034339 985 return true;
7beba2fc
VZ
986}
987
988bool wxTestFontEncoding(const wxNativeEncodingInfo& info)
989{
990 wxString fontspec;
9a83f860
VZ
991 fontspec.Printf(wxT("-*-%s-*-*-*-*-*-*-*-*-*-*-%s-%s"),
992 !info.facename ? wxT("*") : info.facename.c_str(),
7beba2fc
VZ
993 info.xregistry.c_str(),
994 info.xencoding.c_str());
995
996 return wxTestFontSpec(fontspec);
997}
998
999// ----------------------------------------------------------------------------
1000// X-specific functions
1001// ----------------------------------------------------------------------------
1002
1003wxNativeFont wxLoadQueryNearestFont(int pointSize,
1004 int family,
1005 int style,
1006 int weight,
1007 bool underlined,
1008 const wxString &facename,
30764ab5
VZ
1009 wxFontEncoding encoding,
1010 wxString* xFontName)
7beba2fc 1011{
97d3f0ee
VZ
1012 if ( encoding == wxFONTENCODING_DEFAULT )
1013 {
1014 encoding = wxFont::GetDefaultEncoding();
1015 }
1016
7beba2fc
VZ
1017 // first determine the encoding - if the font doesn't exist at all in this
1018 // encoding, it's useless to do all other approximations (i.e. size,
1019 // family &c don't matter much)
1020 wxNativeEncodingInfo info;
97d3f0ee 1021 if ( encoding == wxFONTENCODING_SYSTEM )
81c67e27
RR
1022 {
1023 // This will always work so we don't test to save time
1024 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
1025 }
1026 else
7beba2fc 1027 {
81c67e27
RR
1028 if ( !wxGetNativeFontEncoding(encoding, &info) ||
1029 !wxTestFontEncoding(info) )
7beba2fc 1030 {
1e6feb95 1031#if wxUSE_FONTMAP
142b3bc2 1032 if ( !wxFontMapper::Get()->GetAltForEncoding(encoding, &info) )
1e6feb95 1033#endif // wxUSE_FONTMAP
81c67e27
RR
1034 {
1035 // unspported encoding - replace it with the default
1036 //
1037 // NB: we can't just return 0 from here because wxGTK code doesn't
1038 // check for it (i.e. it supposes that we'll always succeed),
1039 // so it would provoke a crash
1040 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
1041 }
97d3f0ee 1042 }
7beba2fc 1043 }
6c49baf2 1044
81c67e27 1045 // OK, we have the correct xregistry/xencoding in info structure
30764ab5
VZ
1046 wxNativeFont font = 0;
1047
1048 // if we already have the X font name, try to use it
55034339 1049 if( xFontName && !xFontName->empty() )
6c49baf2
VZ
1050 {
1051 //
1052 // Make sure point size is correct for scale factor.
1053 //
9a83f860 1054 wxStringTokenizer tokenizer(*xFontName, wxT("-"), wxTOKEN_RET_DELIMS);
6c49baf2
VZ
1055 wxString newFontName;
1056
1057 for(int i = 0; i < 8; i++)
1058 newFontName += tokenizer.NextToken();
1059
1060 (void) tokenizer.NextToken();
1061
401eb3de 1062 newFontName += wxString::Format(wxT("%d-"), pointSize);
6c49baf2
VZ
1063
1064 while(tokenizer.HasMoreTokens())
1065 newFontName += tokenizer.GetNextToken();
1066
1067 font = wxLoadFont(newFontName);
1068
1069 if(font)
1070 *xFontName = newFontName;
1071 }
30764ab5 1072
7beba2fc
VZ
1073 if ( !font )
1074 {
1075 // search up and down by stepsize 10
1076 int max_size = pointSize + 20 * (1 + (pointSize/180));
1077 int min_size = pointSize - 20 * (1 + (pointSize/180));
1078
34791896 1079 int i, round; // counters
7beba2fc 1080
03647350 1081 // first round: search for equal, then for smaller and for larger size
c45f5ae8 1082 // with the given weight and style
34791896
RR
1083 int testweight = weight;
1084 int teststyle = style;
1085
1086 for ( round = 0; round < 3; round++ )
1087 {
1088 // second round: use normal weight
1089 if ( round == 1 )
b12401e0 1090 {
34791896
RR
1091 if ( testweight != wxNORMAL )
1092 {
1093 testweight = wxNORMAL;
1094 }
1095 else
1096 {
1097 ++round; // fall through to third round
1098 }
1099 }
1100
1101 // third round: ... and use normal style
1102 if ( round == 2 )
1103 {
1104 if ( teststyle != wxNORMAL )
1105 {
1106 teststyle = wxNORMAL;
1107 }
1108 else
1109 {
1110 break;
1111 }
1112 }
1113 // Search for equal or smaller size (approx.)
1114 for ( i = pointSize; !font && i >= 10 && i >= min_size; i -= 10 )
1115 {
1116 font = wxLoadQueryFont(i, family, teststyle, testweight, underlined,
30764ab5
VZ
1117 facename, info.xregistry, info.xencoding,
1118 xFontName);
b12401e0 1119 }
7beba2fc 1120
b12401e0
MB
1121 // Search for larger size (approx.)
1122 for ( i = pointSize + 10; !font && i <= max_size; i += 10 )
1123 {
34791896 1124 font = wxLoadQueryFont(i, family, teststyle, testweight, underlined,
30764ab5
VZ
1125 facename, info.xregistry, info.xencoding,
1126 xFontName);
34791896 1127 }
7beba2fc
VZ
1128 }
1129
1130 // Try default family
1131 if ( !font && family != wxDEFAULT )
1132 {
1133 font = wxLoadQueryFont(pointSize, wxDEFAULT, style, weight,
1134 underlined, facename,
30764ab5
VZ
1135 info.xregistry, info.xencoding,
1136 xFontName );
7beba2fc
VZ
1137 }
1138
f139dfe8
VZ
1139 // ignore size, family, style and weight but try to find font with the
1140 // given facename and encoding
7beba2fc
VZ
1141 if ( !font )
1142 {
1143 font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
1144 underlined, facename,
30764ab5
VZ
1145 info.xregistry, info.xencoding,
1146 xFontName);
7beba2fc 1147
f139dfe8
VZ
1148 // ignore family as well
1149 if ( !font )
1150 {
1151 font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
1152 underlined, wxEmptyString,
1153 info.xregistry, info.xencoding,
1154 xFontName);
1155
1156 // if it still failed, try to get the font of any size but
1157 // with the requested encoding: this can happen if the
1158 // encoding is only available in one size which happens to be
1159 // different from 120
1160 if ( !font )
1161 {
1162 font = wxLoadQueryFont(-1, wxDEFAULT, wxNORMAL, wxNORMAL,
55034339 1163 false, wxEmptyString,
f139dfe8
VZ
1164 info.xregistry, info.xencoding,
1165 xFontName);
1166
1167 // this should never happen as we had tested for it in the
1168 // very beginning, but if it does, do return something non
1169 // NULL or we'd crash in wxFont code
1170 if ( !font )
1171 {
9a83f860 1172 wxFAIL_MSG( wxT("this encoding should be available!") );
f139dfe8
VZ
1173
1174 font = wxLoadQueryFont(-1,
1175 wxDEFAULT, wxNORMAL, wxNORMAL,
55034339 1176 false, wxEmptyString,
9a83f860 1177 wxT("*"), wxT("*"),
f139dfe8
VZ
1178 xFontName);
1179 }
1180 }
1181 }
7beba2fc
VZ
1182 }
1183 }
1184
1185 return font;
1186}
1187
1188// ----------------------------------------------------------------------------
1189// private functions
1190// ----------------------------------------------------------------------------
1191
55034339 1192// returns true if there are any fonts matching this font spec
7beba2fc
VZ
1193static bool wxTestFontSpec(const wxString& fontspec)
1194{
97d3f0ee
VZ
1195 // some X servers will fail to load this font because there are too many
1196 // matches so we must test explicitly for this
9a83f860 1197 if ( fontspec == wxT("-*-*-*-*-*-*-*-*-*-*-*-*-*-*") )
97d3f0ee 1198 {
55034339 1199 return true;
97d3f0ee
VZ
1200 }
1201
2e0e025e
RR
1202 wxNativeFont test = (wxNativeFont) g_fontHash->Get( fontspec );
1203 if (test)
1204 {
55034339 1205 return true;
2e0e025e
RR
1206 }
1207
1208 test = wxLoadFont(fontspec);
1209 g_fontHash->Put( fontspec, (wxObject*) test );
6c49baf2 1210
7beba2fc
VZ
1211 if ( test )
1212 {
1213 wxFreeFont(test);
1214
55034339 1215 return true;
7beba2fc
VZ
1216 }
1217 else
1218 {
55034339 1219 return false;
7beba2fc
VZ
1220 }
1221}
1222
1223static wxNativeFont wxLoadQueryFont(int pointSize,
1224 int family,
1225 int style,
1226 int weight,
1227 bool WXUNUSED(underlined),
1228 const wxString& facename,
1229 const wxString& xregistry,
30764ab5
VZ
1230 const wxString& xencoding,
1231 wxString* xFontName)
7beba2fc
VZ
1232{
1233 wxString xfamily;
1234 switch (family)
1235 {
1236 case wxDECORATIVE: xfamily = wxT("lucida"); break;
1237 case wxROMAN: xfamily = wxT("times"); break;
1238 case wxMODERN: xfamily = wxT("courier"); break;
1239 case wxSWISS: xfamily = wxT("helvetica"); break;
1240 case wxTELETYPE: xfamily = wxT("lucidatypewriter"); break;
1241 case wxSCRIPT: xfamily = wxT("utopia"); break;
1242 default: xfamily = wxT("*");
1243 }
16d865f7 1244#if wxUSE_NANOX
c2ff68d3
JS
1245 int xweight;
1246 switch (weight)
1247 {
1248 case wxBOLD:
1249 {
1250 xweight = MWLF_WEIGHT_BOLD;
1251 break;
1252 }
1253 case wxLIGHT:
1254 {
1255 xweight = MWLF_WEIGHT_LIGHT;
1256 break;
1257 }
1258 case wxNORMAL:
1259 {
1260 xweight = MWLF_WEIGHT_NORMAL;
1261 break;
1262 }
1263
1264 default:
1265 {
1266 xweight = MWLF_WEIGHT_DEFAULT;
1267 break;
1268 }
1269 }
16d865f7
JS
1270 GR_SCREEN_INFO screenInfo;
1271 GrGetScreenInfo(& screenInfo);
1272
1273 int yPixelsPerCM = screenInfo.ydpcm;
1274
0a68bc69 1275 // A point is 1/72 of an inch.
16d865f7 1276 // An inch is 2.541 cm.
0a68bc69 1277 // So pixelHeight = (pointSize / 72) (inches) * 2.541 (for cm) * yPixelsPerCM (for pixels)
c2ff68d3
JS
1278 // In fact pointSize is 10 * the normal point size so
1279 // divide by 10.
1280
15d5a947 1281 int pixelHeight = (int) ( (((float)pointSize) / 720.0) * 2.541 * (float) yPixelsPerCM) ;
c2ff68d3
JS
1282
1283 // An alternative: assume that the screen is 72 dpi.
0a68bc69
JS
1284 //int pixelHeight = (int) (((float)pointSize / 720.0) * 72.0) ;
1285 //int pixelHeight = (int) ((float)pointSize / 10.0) ;
2b5f62a0 1286
16d865f7
JS
1287 GR_LOGFONT logFont;
1288 logFont.lfHeight = pixelHeight;
1289 logFont.lfWidth = 0;
1290 logFont.lfEscapement = 0;
1291 logFont.lfOrientation = 0;
c2ff68d3 1292 logFont.lfWeight = xweight;
16d865f7
JS
1293 logFont.lfItalic = (style == wxNORMAL ? 0 : 1) ;
1294 logFont.lfUnderline = 0;
1295 logFont.lfStrikeOut = 0;
1296 logFont.lfCharSet = MWLF_CHARSET_DEFAULT; // TODO: select appropriate one
1297 logFont.lfOutPrecision = MWLF_TYPE_DEFAULT;
1298 logFont.lfClipPrecision = 0; // Not used
1299 logFont.lfRoman = (family == wxROMAN ? 1 : 0) ;
1300 logFont.lfSerif = (family == wxSWISS ? 0 : 1) ;
1301 logFont.lfSansSerif = !logFont.lfSerif ;
1302 logFont.lfModern = (family == wxMODERN ? 1 : 0) ;
1303 logFont.lfProportional = (family == wxTELETYPE ? 0 : 1) ;
1304 logFont.lfOblique = 0;
1305 logFont.lfSmallCaps = 0;
1306 logFont.lfPitch = 0; // 0 = default
1307 strcpy(logFont.lfFaceName, facename.c_str());
1308
1309 XFontStruct* fontInfo = (XFontStruct*) malloc(sizeof(XFontStruct));
1310 fontInfo->fid = GrCreateFont((GR_CHAR*) facename.c_str(), pixelHeight, & logFont);
1311 GrGetFontInfo(fontInfo->fid, & fontInfo->info);
1312 return (wxNativeFont) fontInfo;
2b5f62a0 1313
16d865f7 1314#else
7beba2fc 1315 wxString fontSpec;
55034339 1316 if (!facename.empty())
7beba2fc
VZ
1317 {
1318 fontSpec.Printf(wxT("-*-%s-*-*-normal-*-*-*-*-*-*-*-*-*"),
1319 facename.c_str());
1320
1321 if ( wxTestFontSpec(fontSpec) )
1322 {
1323 xfamily = facename;
1324 }
1325 //else: no such family, use default one instead
1326 }
1327
1328 wxString xstyle;
1329 switch (style)
1330 {
f9dbf34f
VZ
1331 case wxSLANT:
1332 fontSpec.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
1333 xfamily.c_str());
1334 if ( wxTestFontSpec(fontSpec) )
1335 {
1336 xstyle = wxT("o");
1337 break;
1338 }
1339 // fall through - try wxITALIC now
1340
1341 case wxITALIC:
1342 fontSpec.Printf(wxT("-*-%s-*-i-*-*-*-*-*-*-*-*-*-*"),
1343 xfamily.c_str());
1344 if ( wxTestFontSpec(fontSpec) )
1345 {
1346 xstyle = wxT("i");
1347 }
1348 else if ( style == wxITALIC ) // and not wxSLANT
1349 {
1350 // try wxSLANT
1351 fontSpec.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
1352 xfamily.c_str());
1353 if ( wxTestFontSpec(fontSpec) )
1354 {
1355 xstyle = wxT("o");
1356 }
1357 else
1358 {
1359 // no italic, no slant - leave default
1360 xstyle = wxT("*");
1361 }
1362 }
1363 break;
1364
1365 default:
9a83f860 1366 wxFAIL_MSG(wxT("unknown font style"));
f9dbf34f
VZ
1367 // fall back to normal
1368
1369 case wxNORMAL:
1370 xstyle = wxT("r");
1371 break;
7beba2fc
VZ
1372 }
1373
1374 wxString xweight;
1375 switch (weight)
1376 {
1377 case wxBOLD:
1378 {
1379 fontSpec.Printf(wxT("-*-%s-bold-*-*-*-*-*-*-*-*-*-*-*"),
1380 xfamily.c_str());
1381 if ( wxTestFontSpec(fontSpec) )
1382 {
1383 xweight = wxT("bold");
1384 break;
1385 }
1386 fontSpec.Printf(wxT("-*-%s-heavy-*-*-*-*-*-*-*-*-*-*-*"),
1387 xfamily.c_str());
1388 if ( wxTestFontSpec(fontSpec) )
1389 {
1390 xweight = wxT("heavy");
1391 break;
1392 }
1393 fontSpec.Printf(wxT("-*-%s-extrabold-*-*-*-*-*-*-*-*-*-*-*"),
1394 xfamily.c_str());
1395 if ( wxTestFontSpec(fontSpec) )
1396 {
1397 xweight = wxT("extrabold");
1398 break;
1399 }
1400 fontSpec.Printf(wxT("-*-%s-demibold-*-*-*-*-*-*-*-*-*-*-*"),
1401 xfamily.c_str());
1402 if ( wxTestFontSpec(fontSpec) )
1403 {
1404 xweight = wxT("demibold");
1405 break;
1406 }
1407 fontSpec.Printf(wxT("-*-%s-black-*-*-*-*-*-*-*-*-*-*-*"),
1408 xfamily.c_str());
1409 if ( wxTestFontSpec(fontSpec) )
1410 {
1411 xweight = wxT("black");
1412 break;
1413 }
1414 fontSpec.Printf(wxT("-*-%s-ultrablack-*-*-*-*-*-*-*-*-*-*-*"),
1415 xfamily.c_str());
1416 if ( wxTestFontSpec(fontSpec) )
1417 {
1418 xweight = wxT("ultrablack");
1419 break;
1420 }
1421 }
1422 break;
1423 case wxLIGHT:
1424 {
1425 fontSpec.Printf(wxT("-*-%s-light-*-*-*-*-*-*-*-*-*-*-*"),
1426 xfamily.c_str());
1427 if ( wxTestFontSpec(fontSpec) )
1428 {
1429 xweight = wxT("light");
1430 break;
1431 }
1432 fontSpec.Printf(wxT("-*-%s-thin-*-*-*-*-*-*-*-*-*-*-*"),
1433 xfamily.c_str());
1434 if ( wxTestFontSpec(fontSpec) )
1435 {
1436 xweight = wxT("thin");
1437 break;
1438 }
1439 }
1440 break;
1441 case wxNORMAL:
1442 {
1443 fontSpec.Printf(wxT("-*-%s-medium-*-*-*-*-*-*-*-*-*-*-*"),
1444 xfamily.c_str());
1445 if ( wxTestFontSpec(fontSpec) )
1446 {
1447 xweight = wxT("medium");
1448 break;
1449 }
1450 fontSpec.Printf(wxT("-*-%s-normal-*-*-*-*-*-*-*-*-*-*-*"),
1451 xfamily.c_str());
1452 if ( wxTestFontSpec(fontSpec) )
1453 {
1454 xweight = wxT("normal");
1455 break;
1456 }
1457 fontSpec.Printf(wxT("-*-%s-regular-*-*-*-*-*-*-*-*-*-*-*"),
1458 xfamily.c_str());
1459 if ( wxTestFontSpec(fontSpec) )
1460 {
1461 xweight = wxT("regular");
1462 break;
1463 }
1464 xweight = wxT("*");
1465 }
1466 break;
1467 default: xweight = wxT("*"); break;
1468 }
1469
f139dfe8
VZ
1470 // if pointSize is -1, don't specify any
1471 wxString sizeSpec;
73b0423d 1472 if ( pointSize == -1 )
f139dfe8 1473 {
9a83f860 1474 sizeSpec = wxT('*');
f139dfe8
VZ
1475 }
1476 else
1477 {
9a83f860 1478 sizeSpec.Printf(wxT("%d"), pointSize);
f139dfe8
VZ
1479 }
1480
7beba2fc 1481 // construct the X font spec from our data
f139dfe8 1482 fontSpec.Printf(wxT("-*-%s-%s-%s-normal-*-*-%s-*-*-*-*-%s-%s"),
7beba2fc 1483 xfamily.c_str(), xweight.c_str(), xstyle.c_str(),
f139dfe8 1484 sizeSpec.c_str(), xregistry.c_str(), xencoding.c_str());
7beba2fc 1485
30764ab5
VZ
1486 if( xFontName )
1487 *xFontName = fontSpec;
1488
7beba2fc 1489 return wxLoadFont(fontSpec);
16d865f7
JS
1490#endif
1491 // wxUSE_NANOX
7beba2fc
VZ
1492}
1493
2e0e025e
RR
1494// ----------------------------------------------------------------------------
1495// wxFontModule
1496// ----------------------------------------------------------------------------
1497
1498class wxFontModule : public wxModule
1499{
1500public:
1501 bool OnInit();
1502 void OnExit();
1503
1504private:
1505 DECLARE_DYNAMIC_CLASS(wxFontModule)
1506};
1507
1508IMPLEMENT_DYNAMIC_CLASS(wxFontModule, wxModule)
1509
1510bool wxFontModule::OnInit()
1511{
1512 g_fontHash = new wxHashTable( wxKEY_STRING );
1513
55034339 1514 return true;
2e0e025e
RR
1515}
1516
1517void wxFontModule::OnExit()
1518{
5276b0a5 1519 wxDELETE(g_fontHash);
2e0e025e 1520}
db16cab4 1521
2b5f62a0 1522#endif // GTK 2.0/1.x