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