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