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