fixed restoring fonts from the native font info data which was completely broken...
[wxWidgets.git] / src / unix / fontutil.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: unix/fontutil.cpp
3 // Purpose: Font helper functions for X11 (GDK/X)
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 05.11.99
7 // RCS-ID: $Id$
8 // Copyright: (c) Vadim Zeitlin
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "fontutil.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #ifndef WX_PRECOMP
32 #endif // PCH
33
34 #include "wx/fontutil.h"
35 #include "wx/fontmap.h"
36 #include "wx/tokenzr.h"
37 #include "wx/hash.h"
38 #include "wx/module.h"
39
40 #ifdef __WXGTK20__
41
42 #include "wx/gtk/private.h"
43
44 // ----------------------------------------------------------------------------
45 // wxNativeFontInfo
46 // ----------------------------------------------------------------------------
47
48 void wxNativeFontInfo::Init()
49 {
50 description = NULL;
51 }
52
53 int wxNativeFontInfo::GetPointSize() const
54 {
55 return pango_font_description_get_size( description ) / PANGO_SCALE;
56 }
57
58 wxFontStyle wxNativeFontInfo::GetStyle() const
59 {
60 wxFontStyle m_style = wxFONTSTYLE_NORMAL;
61
62 switch (pango_font_description_get_style( description ))
63 {
64 case PANGO_STYLE_NORMAL:
65 m_style = wxFONTSTYLE_NORMAL;
66 break;
67 case PANGO_STYLE_ITALIC:
68 m_style = wxFONTSTYLE_ITALIC;
69 break;
70 case PANGO_STYLE_OBLIQUE:
71 m_style = wxFONTSTYLE_SLANT;
72 break;
73 }
74
75 return m_style;
76 }
77
78 wxFontWeight wxNativeFontInfo::GetWeight() const
79 {
80 wxFontWeight m_weight = wxFONTWEIGHT_NORMAL;
81
82 switch (pango_font_description_get_weight( description ))
83 {
84 case PANGO_WEIGHT_ULTRALIGHT:
85 m_weight = wxFONTWEIGHT_LIGHT;
86 break;
87 case PANGO_WEIGHT_LIGHT:
88 m_weight = wxFONTWEIGHT_LIGHT;
89 break;
90 case PANGO_WEIGHT_NORMAL:
91 m_weight = wxFONTWEIGHT_NORMAL;
92 break;
93 case PANGO_WEIGHT_BOLD:
94 m_weight = wxFONTWEIGHT_BOLD;
95 break;
96 case PANGO_WEIGHT_ULTRABOLD:
97 m_weight = wxFONTWEIGHT_BOLD;
98 break;
99 case PANGO_WEIGHT_HEAVY:
100 m_weight = wxFONTWEIGHT_BOLD;
101 break;
102 }
103
104 return m_weight;
105 }
106
107 bool wxNativeFontInfo::GetUnderlined() const
108 {
109 return FALSE;
110 }
111
112 wxString wxNativeFontInfo::GetFaceName() const
113 {
114 wxString tmp = wxGTK_CONV_BACK( pango_font_description_get_family( description ) );
115
116 return tmp;
117 }
118
119 wxFontFamily wxNativeFontInfo::GetFamily() const
120 {
121 return wxFONTFAMILY_SWISS;
122 }
123
124 wxFontEncoding wxNativeFontInfo::GetEncoding() const
125 {
126 return wxFONTENCODING_SYSTEM;
127 }
128
129 bool wxNativeFontInfo::FromString(const wxString& s)
130 {
131 if (description)
132 pango_font_description_free( description );
133
134 description = pango_font_description_from_string( wxGTK_CONV( s ) );
135
136 return TRUE;
137 }
138
139 wxString wxNativeFontInfo::ToString() const
140 {
141 wxString tmp = wxGTK_CONV_BACK( pango_font_description_to_string( description ) );
142
143 return tmp;
144 }
145
146 bool wxNativeFontInfo::FromUserString(const wxString& s)
147 {
148 return FromString( s );
149 }
150
151 wxString wxNativeFontInfo::ToUserString() const
152 {
153 return ToString();
154 }
155
156 // ----------------------------------------------------------------------------
157 // wxNativeEncodingInfo
158 // ----------------------------------------------------------------------------
159
160 bool wxNativeEncodingInfo::FromString(const wxString& s)
161 {
162 return FALSE;
163 }
164
165 wxString wxNativeEncodingInfo::ToString() const
166 {
167 return wxEmptyString;
168 }
169
170 bool wxTestFontEncoding(const wxNativeEncodingInfo& info)
171 {
172 return TRUE;
173 }
174
175 bool wxGetNativeFontEncoding(wxFontEncoding encoding,
176 wxNativeEncodingInfo *info)
177 {
178 return FALSE;
179 }
180
181 #else
182 // __WXGTK20__
183
184 #ifdef __X__
185 #ifdef __VMS__
186 #pragma message disable nosimpint
187 #endif
188
189 #include <X11/Xlib.h>
190
191 #ifdef __VMS__
192 #pragma message enable nosimpint
193 #endif
194
195 #include "wx/utils.h" // for wxGetDisplay()
196 #elif defined(__WXGTK__)
197 // we have to declare struct tm to avoid problems with first forward
198 // declaring it in C code (glib.h included from gdk.h does it) and then
199 // defining it when time.h is included from the headers below - this is
200 // known not to work at least with Sun CC 6.01
201 #include <time.h>
202
203 #include <gdk/gdk.h>
204 #endif
205
206
207 // ----------------------------------------------------------------------------
208 // private data
209 // ----------------------------------------------------------------------------
210
211 static wxHashTable *g_fontHash = (wxHashTable*) NULL;
212
213 // ----------------------------------------------------------------------------
214 // private functions
215 // ----------------------------------------------------------------------------
216
217 // define the functions to create and destroy native fonts for this toolkit
218 #ifdef __X__
219 wxNativeFont wxLoadFont(const wxString& fontSpec)
220 {
221 return XLoadQueryFont((Display *)wxGetDisplay(), fontSpec);
222 }
223
224 inline void wxFreeFont(wxNativeFont font)
225 {
226 XFreeFont((Display *)wxGetDisplay(), (XFontStruct *)font);
227 }
228 #elif defined(__WXGTK__)
229 wxNativeFont wxLoadFont(const wxString& fontSpec)
230 {
231 return gdk_font_load( wxConvertWX2MB(fontSpec) );
232 }
233
234 inline void wxFreeFont(wxNativeFont font)
235 {
236 gdk_font_unref(font);
237 }
238 #else
239 #error "Unknown GUI toolkit"
240 #endif
241
242 static bool wxTestFontSpec(const wxString& fontspec);
243
244 static wxNativeFont wxLoadQueryFont(int pointSize,
245 int family,
246 int style,
247 int weight,
248 bool underlined,
249 const wxString& facename,
250 const wxString& xregistry,
251 const wxString& xencoding,
252 wxString* xFontName);
253
254 // ============================================================================
255 // implementation
256 // ============================================================================
257
258 // ----------------------------------------------------------------------------
259 // wxNativeEncodingInfo
260 // ----------------------------------------------------------------------------
261
262 // convert to/from the string representation: format is
263 // encodingid;registry;encoding[;facename]
264 bool wxNativeEncodingInfo::FromString(const wxString& s)
265 {
266 // use ";", not "-" because it may be part of encoding name
267 wxStringTokenizer tokenizer(s, _T(";"));
268
269 wxString encid = tokenizer.GetNextToken();
270 long enc;
271 if ( !encid.ToLong(&enc) )
272 return FALSE;
273 encoding = (wxFontEncoding)enc;
274
275 xregistry = tokenizer.GetNextToken();
276 if ( !xregistry )
277 return FALSE;
278
279 xencoding = tokenizer.GetNextToken();
280 if ( !xencoding )
281 return FALSE;
282
283 // ok even if empty
284 facename = tokenizer.GetNextToken();
285
286 return TRUE;
287 }
288
289 wxString wxNativeEncodingInfo::ToString() const
290 {
291 wxString s;
292 s << (long)encoding << _T(';') << xregistry << _T(';') << xencoding;
293 if ( !!facename )
294 {
295 s << _T(';') << facename;
296 }
297
298 return s;
299 }
300
301 // ----------------------------------------------------------------------------
302 // wxNativeFontInfo
303 // ----------------------------------------------------------------------------
304
305 void wxNativeFontInfo::Init()
306 {
307 m_isDefault = TRUE;
308 }
309
310 bool wxNativeFontInfo::FromString(const wxString& s)
311 {
312 wxStringTokenizer tokenizer(s, _T(";"));
313
314 // check the version
315 wxString token = tokenizer.GetNextToken();
316 if ( token != _T('0') )
317 return FALSE;
318
319 xFontName = tokenizer.GetNextToken();
320
321 // this should be the end
322 if ( tokenizer.HasMoreTokens() )
323 return FALSE;
324
325 return FromXFontName(xFontName);
326 }
327
328 wxString wxNativeFontInfo::ToString() const
329 {
330 // 0 is the version
331 return wxString::Format(_T("%d;%s"), 0, GetXFontName().c_str());
332 }
333
334 bool wxNativeFontInfo::FromUserString(const wxString& s)
335 {
336 return FromXFontName(s);
337 }
338
339 wxString wxNativeFontInfo::ToUserString() const
340 {
341 return GetXFontName();
342 }
343
344 bool wxNativeFontInfo::HasElements() const
345 {
346 // we suppose that the foundry is never empty, so if it is it means that we
347 // had never parsed the XLFD
348 return !fontElements[0].empty();
349 }
350
351 wxString wxNativeFontInfo::GetXFontComponent(wxXLFDField field) const
352 {
353 wxCHECK_MSG( field < wxXLFD_MAX, _T(""), _T("invalid XLFD field") );
354
355 if ( !HasElements() )
356 {
357 // const_cast
358 if ( !((wxNativeFontInfo *)this)->FromXFontName(xFontName) )
359 return _T("");
360 }
361
362 return fontElements[field];
363 }
364
365 bool wxNativeFontInfo::FromXFontName(const wxString& fontname)
366 {
367 // TODO: we should be able to handle the font aliases here, but how?
368 wxStringTokenizer tokenizer(fontname, _T("-"));
369
370 // skip the leading, usually empty field (font name registry)
371 if ( !tokenizer.HasMoreTokens() )
372 return FALSE;
373
374 (void)tokenizer.GetNextToken();
375
376 for ( size_t n = 0; n < WXSIZEOF(fontElements); n++ )
377 {
378 if ( !tokenizer.HasMoreTokens() )
379 {
380 // not enough elements in the XLFD - or maybe an alias
381 return FALSE;
382 }
383
384 fontElements[n] = tokenizer.GetNextToken();
385 }
386
387 // this should be all
388 if ( tokenizer.HasMoreTokens() )
389 return FALSE;
390
391 // we're initialized now
392 m_isDefault = FALSE;
393
394 return TRUE;
395 }
396
397 wxString wxNativeFontInfo::GetXFontName() const
398 {
399 if ( xFontName.empty() )
400 {
401 for ( size_t n = 0; n < WXSIZEOF(fontElements); n++ )
402 {
403 // replace the non specified elements with '*' except for the
404 // additional style which is usually just omitted
405 wxString elt = fontElements[n];
406 if ( elt.empty() && n != wxXLFD_ADDSTYLE )
407 {
408 elt = _T('*');
409 }
410
411 // const_cast
412 ((wxNativeFontInfo *)this)->xFontName << _T('-') << elt;
413 }
414 }
415
416 return xFontName;
417 }
418
419 void
420 wxNativeFontInfo::SetXFontComponent(wxXLFDField field, const wxString& value)
421 {
422 wxCHECK_RET( field < wxXLFD_MAX, _T("invalid XLFD field") );
423
424 // this class should be initialized with a valid font spec first and only
425 // then the fields may be modified!
426 wxASSERT_MSG( !IsDefault(), _T("can't modify an uninitialized XLFD") );
427
428 if ( !HasElements() )
429 {
430 // const_cast
431 if ( !((wxNativeFontInfo *)this)->FromXFontName(xFontName) )
432 {
433 wxFAIL_MSG( _T("can't set font element for invalid XLFD") );
434
435 return;
436 }
437 }
438
439 fontElements[field] = value;
440
441 // invalidate the XFLD, it doesn't correspond to the font elements any more
442 xFontName.clear();
443 }
444
445 void wxNativeFontInfo::SetXFontName(const wxString& xFontName_)
446 {
447 // invalidate the font elements, GetXFontComponent() will reparse the XLFD
448 fontElements[0].clear();
449
450 xFontName = xFontName_;
451
452 m_isDefault = FALSE;
453 }
454
455 // ----------------------------------------------------------------------------
456 // common functions
457 // ----------------------------------------------------------------------------
458
459 bool wxGetNativeFontEncoding(wxFontEncoding encoding,
460 wxNativeEncodingInfo *info)
461 {
462 wxCHECK_MSG( info, FALSE, _T("bad pointer in wxGetNativeFontEncoding") );
463
464 if ( encoding == wxFONTENCODING_DEFAULT )
465 {
466 encoding = wxFont::GetDefaultEncoding();
467 }
468
469 switch ( encoding )
470 {
471 case wxFONTENCODING_ISO8859_1:
472 case wxFONTENCODING_ISO8859_2:
473 case wxFONTENCODING_ISO8859_3:
474 case wxFONTENCODING_ISO8859_4:
475 case wxFONTENCODING_ISO8859_5:
476 case wxFONTENCODING_ISO8859_6:
477 case wxFONTENCODING_ISO8859_7:
478 case wxFONTENCODING_ISO8859_8:
479 case wxFONTENCODING_ISO8859_9:
480 case wxFONTENCODING_ISO8859_10:
481 case wxFONTENCODING_ISO8859_11:
482 case wxFONTENCODING_ISO8859_12:
483 case wxFONTENCODING_ISO8859_13:
484 case wxFONTENCODING_ISO8859_14:
485 case wxFONTENCODING_ISO8859_15:
486 {
487 int cp = encoding - wxFONTENCODING_ISO8859_1 + 1;
488 info->xregistry = wxT("iso8859");
489 info->xencoding.Printf(wxT("%d"), cp);
490 }
491 break;
492
493 case wxFONTENCODING_UTF8:
494 info->xregistry = wxT("iso10646");
495 info->xencoding = wxT("*");
496 break;
497
498 case wxFONTENCODING_KOI8:
499 info->xregistry = wxT("koi8");
500
501 // we don't make distinction between koi8-r, koi8-u and koi8-ru (so far)
502 info->xencoding = wxT("*");
503 break;
504
505 case wxFONTENCODING_CP1250:
506 case wxFONTENCODING_CP1251:
507 case wxFONTENCODING_CP1252:
508 case wxFONTENCODING_CP1253:
509 case wxFONTENCODING_CP1254:
510 case wxFONTENCODING_CP1255:
511 case wxFONTENCODING_CP1256:
512 case wxFONTENCODING_CP1257:
513 {
514 int cp = encoding - wxFONTENCODING_CP1250 + 1250;
515 info->xregistry = wxT("microsoft");
516 info->xencoding.Printf(wxT("cp%d"), cp);
517 }
518 break;
519
520 case wxFONTENCODING_SYSTEM:
521 info->xregistry =
522 info->xencoding = wxT("*");
523 break;
524
525 default:
526 // don't know how to translate this encoding into X fontspec
527 return FALSE;
528 }
529
530 info->encoding = encoding;
531
532 return TRUE;
533 }
534
535 bool wxTestFontEncoding(const wxNativeEncodingInfo& info)
536 {
537 wxString fontspec;
538 fontspec.Printf(_T("-*-%s-*-*-*-*-*-*-*-*-*-*-%s-%s"),
539 !info.facename ? _T("*") : info.facename.c_str(),
540 info.xregistry.c_str(),
541 info.xencoding.c_str());
542
543 return wxTestFontSpec(fontspec);
544 }
545
546 // ----------------------------------------------------------------------------
547 // X-specific functions
548 // ----------------------------------------------------------------------------
549
550 wxNativeFont wxLoadQueryNearestFont(int pointSize,
551 int family,
552 int style,
553 int weight,
554 bool underlined,
555 const wxString &facename,
556 wxFontEncoding encoding,
557 wxString* xFontName)
558 {
559 if ( encoding == wxFONTENCODING_DEFAULT )
560 {
561 encoding = wxFont::GetDefaultEncoding();
562 }
563
564 // first determine the encoding - if the font doesn't exist at all in this
565 // encoding, it's useless to do all other approximations (i.e. size,
566 // family &c don't matter much)
567 wxNativeEncodingInfo info;
568 if ( encoding == wxFONTENCODING_SYSTEM )
569 {
570 // This will always work so we don't test to save time
571 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
572 }
573 else
574 {
575 if ( !wxGetNativeFontEncoding(encoding, &info) ||
576 !wxTestFontEncoding(info) )
577 {
578 #if wxUSE_FONTMAP
579 if ( !wxFontMapper::Get()->GetAltForEncoding(encoding, &info) )
580 #endif // wxUSE_FONTMAP
581 {
582 // unspported encoding - replace it with the default
583 //
584 // NB: we can't just return 0 from here because wxGTK code doesn't
585 // check for it (i.e. it supposes that we'll always succeed),
586 // so it would provoke a crash
587 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
588 }
589 }
590 }
591
592 // OK, we have the correct xregistry/xencoding in info structure
593 wxNativeFont font = 0;
594
595 // if we already have the X font name, try to use it
596 if( xFontName && !xFontName->IsEmpty() )
597 {
598 //
599 // Make sure point size is correct for scale factor.
600 //
601 wxStringTokenizer tokenizer(*xFontName, _T("-"), wxTOKEN_RET_DELIMS);
602 wxString newFontName;
603
604 for(int i = 0; i < 8; i++)
605 newFontName += tokenizer.NextToken();
606
607 (void) tokenizer.NextToken();
608
609 newFontName += wxString::Format(wxT("%d-"), pointSize);
610
611 while(tokenizer.HasMoreTokens())
612 newFontName += tokenizer.GetNextToken();
613
614 font = wxLoadFont(newFontName);
615
616 if(font)
617 *xFontName = newFontName;
618 }
619
620 // try to load exactly the font requested first
621 if( !font )
622 {
623 font = wxLoadQueryFont( pointSize, family, style, weight,
624 underlined, facename,
625 info.xregistry, info.xencoding,
626 xFontName );
627 }
628
629 if ( !font )
630 {
631 // search up and down by stepsize 10
632 int max_size = pointSize + 20 * (1 + (pointSize/180));
633 int min_size = pointSize - 20 * (1 + (pointSize/180));
634
635 int i;
636
637 // Search for smaller size (approx.)
638 for ( i = pointSize - 10; !font && i >= 10 && i >= min_size; i -= 10 )
639 {
640 font = wxLoadQueryFont(i, family, style, weight, underlined,
641 facename, info.xregistry, info.xencoding,
642 xFontName);
643 }
644
645 // Search for larger size (approx.)
646 for ( i = pointSize + 10; !font && i <= max_size; i += 10 )
647 {
648 font = wxLoadQueryFont(i, family, style, weight, underlined,
649 facename, info.xregistry, info.xencoding,
650 xFontName);
651 }
652
653 // Try default family
654 if ( !font && family != wxDEFAULT )
655 {
656 font = wxLoadQueryFont(pointSize, wxDEFAULT, style, weight,
657 underlined, facename,
658 info.xregistry, info.xencoding,
659 xFontName );
660 }
661
662 // ignore size, family, style and weight but try to find font with the
663 // given facename and encoding
664 if ( !font )
665 {
666 font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
667 underlined, facename,
668 info.xregistry, info.xencoding,
669 xFontName);
670
671 // ignore family as well
672 if ( !font )
673 {
674 font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
675 underlined, wxEmptyString,
676 info.xregistry, info.xencoding,
677 xFontName);
678
679 // if it still failed, try to get the font of any size but
680 // with the requested encoding: this can happen if the
681 // encoding is only available in one size which happens to be
682 // different from 120
683 if ( !font )
684 {
685 font = wxLoadQueryFont(-1, wxDEFAULT, wxNORMAL, wxNORMAL,
686 FALSE, wxEmptyString,
687 info.xregistry, info.xencoding,
688 xFontName);
689
690 // this should never happen as we had tested for it in the
691 // very beginning, but if it does, do return something non
692 // NULL or we'd crash in wxFont code
693 if ( !font )
694 {
695 wxFAIL_MSG( _T("this encoding should be available!") );
696
697 font = wxLoadQueryFont(-1,
698 wxDEFAULT, wxNORMAL, wxNORMAL,
699 FALSE, wxEmptyString,
700 _T("*"), _T("*"),
701 xFontName);
702 }
703 }
704 }
705 }
706 }
707
708 return font;
709 }
710
711 // ----------------------------------------------------------------------------
712 // private functions
713 // ----------------------------------------------------------------------------
714
715 // returns TRUE if there are any fonts matching this font spec
716 static bool wxTestFontSpec(const wxString& fontspec)
717 {
718 // some X servers will fail to load this font because there are too many
719 // matches so we must test explicitly for this
720 if ( fontspec == _T("-*-*-*-*-*-*-*-*-*-*-*-*-*-*") )
721 {
722 return TRUE;
723 }
724
725 wxNativeFont test = (wxNativeFont) g_fontHash->Get( fontspec );
726 if (test)
727 {
728 return TRUE;
729 }
730
731 test = wxLoadFont(fontspec);
732 g_fontHash->Put( fontspec, (wxObject*) test );
733
734 if ( test )
735 {
736 wxFreeFont(test);
737
738 return TRUE;
739 }
740 else
741 {
742 return FALSE;
743 }
744 }
745
746 static wxNativeFont wxLoadQueryFont(int pointSize,
747 int family,
748 int style,
749 int weight,
750 bool WXUNUSED(underlined),
751 const wxString& facename,
752 const wxString& xregistry,
753 const wxString& xencoding,
754 wxString* xFontName)
755 {
756 wxString xfamily;
757 switch (family)
758 {
759 case wxDECORATIVE: xfamily = wxT("lucida"); break;
760 case wxROMAN: xfamily = wxT("times"); break;
761 case wxMODERN: xfamily = wxT("courier"); break;
762 case wxSWISS: xfamily = wxT("helvetica"); break;
763 case wxTELETYPE: xfamily = wxT("lucidatypewriter"); break;
764 case wxSCRIPT: xfamily = wxT("utopia"); break;
765 default: xfamily = wxT("*");
766 }
767 #if wxUSE_NANOX
768 int xweight;
769 switch (weight)
770 {
771 case wxBOLD:
772 {
773 xweight = MWLF_WEIGHT_BOLD;
774 break;
775 }
776 case wxLIGHT:
777 {
778 xweight = MWLF_WEIGHT_LIGHT;
779 break;
780 }
781 case wxNORMAL:
782 {
783 xweight = MWLF_WEIGHT_NORMAL;
784 break;
785 }
786
787 default:
788 {
789 xweight = MWLF_WEIGHT_DEFAULT;
790 break;
791 }
792 }
793 GR_SCREEN_INFO screenInfo;
794 GrGetScreenInfo(& screenInfo);
795
796 int yPixelsPerCM = screenInfo.ydpcm;
797
798 // A point is 1/72 of an inch.
799 // An inch is 2.541 cm.
800 // So pixelHeight = (pointSize / 72) (inches) * 2.541 (for cm) * yPixelsPerCM (for pixels)
801 // In fact pointSize is 10 * the normal point size so
802 // divide by 10.
803
804 int pixelHeight = (int) ( (((float)pointSize) / 720.0) * 2.541 * (float) yPixelsPerCM) ;
805
806 // An alternative: assume that the screen is 72 dpi.
807 //int pixelHeight = (int) (((float)pointSize / 720.0) * 72.0) ;
808 //int pixelHeight = (int) ((float)pointSize / 10.0) ;
809
810 GR_LOGFONT logFont;
811 logFont.lfHeight = pixelHeight;
812 logFont.lfWidth = 0;
813 logFont.lfEscapement = 0;
814 logFont.lfOrientation = 0;
815 logFont.lfWeight = xweight;
816 logFont.lfItalic = (style == wxNORMAL ? 0 : 1) ;
817 logFont.lfUnderline = 0;
818 logFont.lfStrikeOut = 0;
819 logFont.lfCharSet = MWLF_CHARSET_DEFAULT; // TODO: select appropriate one
820 logFont.lfOutPrecision = MWLF_TYPE_DEFAULT;
821 logFont.lfClipPrecision = 0; // Not used
822 logFont.lfRoman = (family == wxROMAN ? 1 : 0) ;
823 logFont.lfSerif = (family == wxSWISS ? 0 : 1) ;
824 logFont.lfSansSerif = !logFont.lfSerif ;
825 logFont.lfModern = (family == wxMODERN ? 1 : 0) ;
826 logFont.lfProportional = (family == wxTELETYPE ? 0 : 1) ;
827 logFont.lfOblique = 0;
828 logFont.lfSmallCaps = 0;
829 logFont.lfPitch = 0; // 0 = default
830 strcpy(logFont.lfFaceName, facename.c_str());
831
832 XFontStruct* fontInfo = (XFontStruct*) malloc(sizeof(XFontStruct));
833 fontInfo->fid = GrCreateFont((GR_CHAR*) facename.c_str(), pixelHeight, & logFont);
834 GrGetFontInfo(fontInfo->fid, & fontInfo->info);
835 return (wxNativeFont) fontInfo;
836
837 #else
838 wxString fontSpec;
839 if (!facename.IsEmpty())
840 {
841 fontSpec.Printf(wxT("-*-%s-*-*-normal-*-*-*-*-*-*-*-*-*"),
842 facename.c_str());
843
844 if ( wxTestFontSpec(fontSpec) )
845 {
846 xfamily = facename;
847 }
848 //else: no such family, use default one instead
849 }
850
851 wxString xstyle;
852 switch (style)
853 {
854 case wxSLANT:
855 fontSpec.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
856 xfamily.c_str());
857 if ( wxTestFontSpec(fontSpec) )
858 {
859 xstyle = wxT("o");
860 break;
861 }
862 // fall through - try wxITALIC now
863
864 case wxITALIC:
865 fontSpec.Printf(wxT("-*-%s-*-i-*-*-*-*-*-*-*-*-*-*"),
866 xfamily.c_str());
867 if ( wxTestFontSpec(fontSpec) )
868 {
869 xstyle = wxT("i");
870 }
871 else if ( style == wxITALIC ) // and not wxSLANT
872 {
873 // try wxSLANT
874 fontSpec.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
875 xfamily.c_str());
876 if ( wxTestFontSpec(fontSpec) )
877 {
878 xstyle = wxT("o");
879 }
880 else
881 {
882 // no italic, no slant - leave default
883 xstyle = wxT("*");
884 }
885 }
886 break;
887
888 default:
889 wxFAIL_MSG(_T("unknown font style"));
890 // fall back to normal
891
892 case wxNORMAL:
893 xstyle = wxT("r");
894 break;
895 }
896
897 wxString xweight;
898 switch (weight)
899 {
900 case wxBOLD:
901 {
902 fontSpec.Printf(wxT("-*-%s-bold-*-*-*-*-*-*-*-*-*-*-*"),
903 xfamily.c_str());
904 if ( wxTestFontSpec(fontSpec) )
905 {
906 xweight = wxT("bold");
907 break;
908 }
909 fontSpec.Printf(wxT("-*-%s-heavy-*-*-*-*-*-*-*-*-*-*-*"),
910 xfamily.c_str());
911 if ( wxTestFontSpec(fontSpec) )
912 {
913 xweight = wxT("heavy");
914 break;
915 }
916 fontSpec.Printf(wxT("-*-%s-extrabold-*-*-*-*-*-*-*-*-*-*-*"),
917 xfamily.c_str());
918 if ( wxTestFontSpec(fontSpec) )
919 {
920 xweight = wxT("extrabold");
921 break;
922 }
923 fontSpec.Printf(wxT("-*-%s-demibold-*-*-*-*-*-*-*-*-*-*-*"),
924 xfamily.c_str());
925 if ( wxTestFontSpec(fontSpec) )
926 {
927 xweight = wxT("demibold");
928 break;
929 }
930 fontSpec.Printf(wxT("-*-%s-black-*-*-*-*-*-*-*-*-*-*-*"),
931 xfamily.c_str());
932 if ( wxTestFontSpec(fontSpec) )
933 {
934 xweight = wxT("black");
935 break;
936 }
937 fontSpec.Printf(wxT("-*-%s-ultrablack-*-*-*-*-*-*-*-*-*-*-*"),
938 xfamily.c_str());
939 if ( wxTestFontSpec(fontSpec) )
940 {
941 xweight = wxT("ultrablack");
942 break;
943 }
944 }
945 break;
946 case wxLIGHT:
947 {
948 fontSpec.Printf(wxT("-*-%s-light-*-*-*-*-*-*-*-*-*-*-*"),
949 xfamily.c_str());
950 if ( wxTestFontSpec(fontSpec) )
951 {
952 xweight = wxT("light");
953 break;
954 }
955 fontSpec.Printf(wxT("-*-%s-thin-*-*-*-*-*-*-*-*-*-*-*"),
956 xfamily.c_str());
957 if ( wxTestFontSpec(fontSpec) )
958 {
959 xweight = wxT("thin");
960 break;
961 }
962 }
963 break;
964 case wxNORMAL:
965 {
966 fontSpec.Printf(wxT("-*-%s-medium-*-*-*-*-*-*-*-*-*-*-*"),
967 xfamily.c_str());
968 if ( wxTestFontSpec(fontSpec) )
969 {
970 xweight = wxT("medium");
971 break;
972 }
973 fontSpec.Printf(wxT("-*-%s-normal-*-*-*-*-*-*-*-*-*-*-*"),
974 xfamily.c_str());
975 if ( wxTestFontSpec(fontSpec) )
976 {
977 xweight = wxT("normal");
978 break;
979 }
980 fontSpec.Printf(wxT("-*-%s-regular-*-*-*-*-*-*-*-*-*-*-*"),
981 xfamily.c_str());
982 if ( wxTestFontSpec(fontSpec) )
983 {
984 xweight = wxT("regular");
985 break;
986 }
987 xweight = wxT("*");
988 }
989 break;
990 default: xweight = wxT("*"); break;
991 }
992
993 // if pointSize is -1, don't specify any
994 wxString sizeSpec;
995 if ( pointSize == -1 )
996 {
997 sizeSpec = _T('*');
998 }
999 else
1000 {
1001 sizeSpec.Printf(_T("%d"), pointSize);
1002 }
1003
1004 // construct the X font spec from our data
1005 fontSpec.Printf(wxT("-*-%s-%s-%s-normal-*-*-%s-*-*-*-*-%s-%s"),
1006 xfamily.c_str(), xweight.c_str(), xstyle.c_str(),
1007 sizeSpec.c_str(), xregistry.c_str(), xencoding.c_str());
1008
1009 if( xFontName )
1010 *xFontName = fontSpec;
1011
1012 return wxLoadFont(fontSpec);
1013 #endif
1014 // wxUSE_NANOX
1015 }
1016
1017 // ----------------------------------------------------------------------------
1018 // wxFontModule
1019 // ----------------------------------------------------------------------------
1020
1021 class wxFontModule : public wxModule
1022 {
1023 public:
1024 bool OnInit();
1025 void OnExit();
1026
1027 private:
1028 DECLARE_DYNAMIC_CLASS(wxFontModule)
1029 };
1030
1031 IMPLEMENT_DYNAMIC_CLASS(wxFontModule, wxModule)
1032
1033 bool wxFontModule::OnInit()
1034 {
1035 g_fontHash = new wxHashTable( wxKEY_STRING );
1036
1037 return TRUE;
1038 }
1039
1040 void wxFontModule::OnExit()
1041 {
1042 delete g_fontHash;
1043
1044 g_fontHash = (wxHashTable *)NULL;
1045 }
1046
1047 #endif
1048 // not GTK 2.0