]> git.saurik.com Git - wxWidgets.git/blob - src/unix/fontutil.cpp
08a6f769c332dd80471b2d53f2bfca41dc1d4d12
[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 return !tokenizer.HasMoreTokens();
389 }
390
391 wxString wxNativeFontInfo::GetXFontName() const
392 {
393 if ( xFontName.empty() )
394 {
395 for ( size_t n = 0; n < WXSIZEOF(fontElements); n++ )
396 {
397 // replace the non specified elements with '*' except for the
398 // additional style which is usually just omitted
399 wxString elt = fontElements[n];
400 if ( elt.empty() && n != wxXLFD_ADDSTYLE )
401 {
402 elt = _T('*');
403 }
404
405 // const_cast
406 ((wxNativeFontInfo *)this)->xFontName << _T('-') << elt;
407 }
408 }
409
410 return xFontName;
411 }
412
413 void
414 wxNativeFontInfo::SetXFontComponent(wxXLFDField field, const wxString& value)
415 {
416 wxCHECK_RET( field < wxXLFD_MAX, _T("invalid XLFD field") );
417
418 // this class should be initialized with a valid font spec first and only
419 // then the fields may be modified!
420 wxASSERT_MSG( !IsDefault(), _T("can't modify an uninitialized XLFD") );
421
422 if ( !HasElements() )
423 {
424 // const_cast
425 if ( !((wxNativeFontInfo *)this)->FromXFontName(xFontName) )
426 {
427 wxFAIL_MSG( _T("can't set font element for invalid XLFD") );
428
429 return;
430 }
431 }
432
433 fontElements[field] = value;
434
435 // invalidate the XFLD, it doesn't correspond to the font elements any more
436 xFontName.clear();
437 }
438
439 void wxNativeFontInfo::SetXFontName(const wxString& xFontName_)
440 {
441 // invalidate the font elements, GetXFontComponent() will reparse the XLFD
442 fontElements[0].clear();
443
444 xFontName = xFontName_;
445
446 m_isDefault = FALSE;
447 }
448
449 // ----------------------------------------------------------------------------
450 // common functions
451 // ----------------------------------------------------------------------------
452
453 bool wxGetNativeFontEncoding(wxFontEncoding encoding,
454 wxNativeEncodingInfo *info)
455 {
456 wxCHECK_MSG( info, FALSE, _T("bad pointer in wxGetNativeFontEncoding") );
457
458 if ( encoding == wxFONTENCODING_DEFAULT )
459 {
460 encoding = wxFont::GetDefaultEncoding();
461 }
462
463 switch ( encoding )
464 {
465 case wxFONTENCODING_ISO8859_1:
466 case wxFONTENCODING_ISO8859_2:
467 case wxFONTENCODING_ISO8859_3:
468 case wxFONTENCODING_ISO8859_4:
469 case wxFONTENCODING_ISO8859_5:
470 case wxFONTENCODING_ISO8859_6:
471 case wxFONTENCODING_ISO8859_7:
472 case wxFONTENCODING_ISO8859_8:
473 case wxFONTENCODING_ISO8859_9:
474 case wxFONTENCODING_ISO8859_10:
475 case wxFONTENCODING_ISO8859_11:
476 case wxFONTENCODING_ISO8859_12:
477 case wxFONTENCODING_ISO8859_13:
478 case wxFONTENCODING_ISO8859_14:
479 case wxFONTENCODING_ISO8859_15:
480 {
481 int cp = encoding - wxFONTENCODING_ISO8859_1 + 1;
482 info->xregistry = wxT("iso8859");
483 info->xencoding.Printf(wxT("%d"), cp);
484 }
485 break;
486
487 case wxFONTENCODING_UTF8:
488 info->xregistry = wxT("iso10646");
489 info->xencoding = wxT("*");
490 break;
491
492 case wxFONTENCODING_KOI8:
493 info->xregistry = wxT("koi8");
494
495 // we don't make distinction between koi8-r, koi8-u and koi8-ru (so far)
496 info->xencoding = wxT("*");
497 break;
498
499 case wxFONTENCODING_CP1250:
500 case wxFONTENCODING_CP1251:
501 case wxFONTENCODING_CP1252:
502 case wxFONTENCODING_CP1253:
503 case wxFONTENCODING_CP1254:
504 case wxFONTENCODING_CP1255:
505 case wxFONTENCODING_CP1256:
506 case wxFONTENCODING_CP1257:
507 {
508 int cp = encoding - wxFONTENCODING_CP1250 + 1250;
509 info->xregistry = wxT("microsoft");
510 info->xencoding.Printf(wxT("cp%d"), cp);
511 }
512 break;
513
514 case wxFONTENCODING_SYSTEM:
515 info->xregistry =
516 info->xencoding = wxT("*");
517 break;
518
519 default:
520 // don't know how to translate this encoding into X fontspec
521 return FALSE;
522 }
523
524 info->encoding = encoding;
525
526 return TRUE;
527 }
528
529 bool wxTestFontEncoding(const wxNativeEncodingInfo& info)
530 {
531 wxString fontspec;
532 fontspec.Printf(_T("-*-%s-*-*-*-*-*-*-*-*-*-*-%s-%s"),
533 !info.facename ? _T("*") : info.facename.c_str(),
534 info.xregistry.c_str(),
535 info.xencoding.c_str());
536
537 return wxTestFontSpec(fontspec);
538 }
539
540 // ----------------------------------------------------------------------------
541 // X-specific functions
542 // ----------------------------------------------------------------------------
543
544 wxNativeFont wxLoadQueryNearestFont(int pointSize,
545 int family,
546 int style,
547 int weight,
548 bool underlined,
549 const wxString &facename,
550 wxFontEncoding encoding,
551 wxString* xFontName)
552 {
553 if ( encoding == wxFONTENCODING_DEFAULT )
554 {
555 encoding = wxFont::GetDefaultEncoding();
556 }
557
558 // first determine the encoding - if the font doesn't exist at all in this
559 // encoding, it's useless to do all other approximations (i.e. size,
560 // family &c don't matter much)
561 wxNativeEncodingInfo info;
562 if ( encoding == wxFONTENCODING_SYSTEM )
563 {
564 // This will always work so we don't test to save time
565 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
566 }
567 else
568 {
569 if ( !wxGetNativeFontEncoding(encoding, &info) ||
570 !wxTestFontEncoding(info) )
571 {
572 #if wxUSE_FONTMAP
573 if ( !wxFontMapper::Get()->GetAltForEncoding(encoding, &info) )
574 #endif // wxUSE_FONTMAP
575 {
576 // unspported encoding - replace it with the default
577 //
578 // NB: we can't just return 0 from here because wxGTK code doesn't
579 // check for it (i.e. it supposes that we'll always succeed),
580 // so it would provoke a crash
581 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
582 }
583 }
584 }
585
586 // OK, we have the correct xregistry/xencoding in info structure
587 wxNativeFont font = 0;
588
589 // if we already have the X font name, try to use it
590 if( xFontName && !xFontName->IsEmpty() )
591 {
592 //
593 // Make sure point size is correct for scale factor.
594 //
595 wxStringTokenizer tokenizer(*xFontName, _T("-"), wxTOKEN_RET_DELIMS);
596 wxString newFontName;
597
598 for(int i = 0; i < 8; i++)
599 newFontName += tokenizer.NextToken();
600
601 (void) tokenizer.NextToken();
602
603 newFontName += wxString::Format(wxT("%d-"), pointSize);
604
605 while(tokenizer.HasMoreTokens())
606 newFontName += tokenizer.GetNextToken();
607
608 font = wxLoadFont(newFontName);
609
610 if(font)
611 *xFontName = newFontName;
612 }
613
614 // try to load exactly the font requested first
615 if( !font )
616 {
617 font = wxLoadQueryFont( pointSize, family, style, weight,
618 underlined, facename,
619 info.xregistry, info.xencoding,
620 xFontName );
621 }
622
623 if ( !font )
624 {
625 // search up and down by stepsize 10
626 int max_size = pointSize + 20 * (1 + (pointSize/180));
627 int min_size = pointSize - 20 * (1 + (pointSize/180));
628
629 int i;
630
631 // Search for smaller size (approx.)
632 for ( i = pointSize - 10; !font && i >= 10 && i >= min_size; i -= 10 )
633 {
634 font = wxLoadQueryFont(i, family, style, weight, underlined,
635 facename, info.xregistry, info.xencoding,
636 xFontName);
637 }
638
639 // Search for larger size (approx.)
640 for ( i = pointSize + 10; !font && i <= max_size; i += 10 )
641 {
642 font = wxLoadQueryFont(i, family, style, weight, underlined,
643 facename, info.xregistry, info.xencoding,
644 xFontName);
645 }
646
647 // Try default family
648 if ( !font && family != wxDEFAULT )
649 {
650 font = wxLoadQueryFont(pointSize, wxDEFAULT, style, weight,
651 underlined, facename,
652 info.xregistry, info.xencoding,
653 xFontName );
654 }
655
656 // ignore size, family, style and weight but try to find font with the
657 // given facename and encoding
658 if ( !font )
659 {
660 font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
661 underlined, facename,
662 info.xregistry, info.xencoding,
663 xFontName);
664
665 // ignore family as well
666 if ( !font )
667 {
668 font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
669 underlined, wxEmptyString,
670 info.xregistry, info.xencoding,
671 xFontName);
672
673 // if it still failed, try to get the font of any size but
674 // with the requested encoding: this can happen if the
675 // encoding is only available in one size which happens to be
676 // different from 120
677 if ( !font )
678 {
679 font = wxLoadQueryFont(-1, wxDEFAULT, wxNORMAL, wxNORMAL,
680 FALSE, wxEmptyString,
681 info.xregistry, info.xencoding,
682 xFontName);
683
684 // this should never happen as we had tested for it in the
685 // very beginning, but if it does, do return something non
686 // NULL or we'd crash in wxFont code
687 if ( !font )
688 {
689 wxFAIL_MSG( _T("this encoding should be available!") );
690
691 font = wxLoadQueryFont(-1,
692 wxDEFAULT, wxNORMAL, wxNORMAL,
693 FALSE, wxEmptyString,
694 _T("*"), _T("*"),
695 xFontName);
696 }
697 }
698 }
699 }
700 }
701
702 return font;
703 }
704
705 // ----------------------------------------------------------------------------
706 // private functions
707 // ----------------------------------------------------------------------------
708
709 // returns TRUE if there are any fonts matching this font spec
710 static bool wxTestFontSpec(const wxString& fontspec)
711 {
712 // some X servers will fail to load this font because there are too many
713 // matches so we must test explicitly for this
714 if ( fontspec == _T("-*-*-*-*-*-*-*-*-*-*-*-*-*-*") )
715 {
716 return TRUE;
717 }
718
719 wxNativeFont test = (wxNativeFont) g_fontHash->Get( fontspec );
720 if (test)
721 {
722 return TRUE;
723 }
724
725 test = wxLoadFont(fontspec);
726 g_fontHash->Put( fontspec, (wxObject*) test );
727
728 if ( test )
729 {
730 wxFreeFont(test);
731
732 return TRUE;
733 }
734 else
735 {
736 return FALSE;
737 }
738 }
739
740 static wxNativeFont wxLoadQueryFont(int pointSize,
741 int family,
742 int style,
743 int weight,
744 bool WXUNUSED(underlined),
745 const wxString& facename,
746 const wxString& xregistry,
747 const wxString& xencoding,
748 wxString* xFontName)
749 {
750 wxString xfamily;
751 switch (family)
752 {
753 case wxDECORATIVE: xfamily = wxT("lucida"); break;
754 case wxROMAN: xfamily = wxT("times"); break;
755 case wxMODERN: xfamily = wxT("courier"); break;
756 case wxSWISS: xfamily = wxT("helvetica"); break;
757 case wxTELETYPE: xfamily = wxT("lucidatypewriter"); break;
758 case wxSCRIPT: xfamily = wxT("utopia"); break;
759 default: xfamily = wxT("*");
760 }
761 #if wxUSE_NANOX
762 int xweight;
763 switch (weight)
764 {
765 case wxBOLD:
766 {
767 xweight = MWLF_WEIGHT_BOLD;
768 break;
769 }
770 case wxLIGHT:
771 {
772 xweight = MWLF_WEIGHT_LIGHT;
773 break;
774 }
775 case wxNORMAL:
776 {
777 xweight = MWLF_WEIGHT_NORMAL;
778 break;
779 }
780
781 default:
782 {
783 xweight = MWLF_WEIGHT_DEFAULT;
784 break;
785 }
786 }
787 GR_SCREEN_INFO screenInfo;
788 GrGetScreenInfo(& screenInfo);
789
790 int yPixelsPerCM = screenInfo.ydpcm;
791
792 // A point is 1/72 of an inch.
793 // An inch is 2.541 cm.
794 // So pixelHeight = (pointSize / 72) (inches) * 2.541 (for cm) * yPixelsPerCM (for pixels)
795 // In fact pointSize is 10 * the normal point size so
796 // divide by 10.
797
798 int pixelHeight = (int) ( (((float)pointSize) / 720.0) * 2.541 * (float) yPixelsPerCM) ;
799
800 // An alternative: assume that the screen is 72 dpi.
801 //int pixelHeight = (int) (((float)pointSize / 720.0) * 72.0) ;
802 //int pixelHeight = (int) ((float)pointSize / 10.0) ;
803
804 GR_LOGFONT logFont;
805 logFont.lfHeight = pixelHeight;
806 logFont.lfWidth = 0;
807 logFont.lfEscapement = 0;
808 logFont.lfOrientation = 0;
809 logFont.lfWeight = xweight;
810 logFont.lfItalic = (style == wxNORMAL ? 0 : 1) ;
811 logFont.lfUnderline = 0;
812 logFont.lfStrikeOut = 0;
813 logFont.lfCharSet = MWLF_CHARSET_DEFAULT; // TODO: select appropriate one
814 logFont.lfOutPrecision = MWLF_TYPE_DEFAULT;
815 logFont.lfClipPrecision = 0; // Not used
816 logFont.lfRoman = (family == wxROMAN ? 1 : 0) ;
817 logFont.lfSerif = (family == wxSWISS ? 0 : 1) ;
818 logFont.lfSansSerif = !logFont.lfSerif ;
819 logFont.lfModern = (family == wxMODERN ? 1 : 0) ;
820 logFont.lfProportional = (family == wxTELETYPE ? 0 : 1) ;
821 logFont.lfOblique = 0;
822 logFont.lfSmallCaps = 0;
823 logFont.lfPitch = 0; // 0 = default
824 strcpy(logFont.lfFaceName, facename.c_str());
825
826 XFontStruct* fontInfo = (XFontStruct*) malloc(sizeof(XFontStruct));
827 fontInfo->fid = GrCreateFont((GR_CHAR*) facename.c_str(), pixelHeight, & logFont);
828 GrGetFontInfo(fontInfo->fid, & fontInfo->info);
829 return (wxNativeFont) fontInfo;
830
831 #else
832 wxString fontSpec;
833 if (!facename.IsEmpty())
834 {
835 fontSpec.Printf(wxT("-*-%s-*-*-normal-*-*-*-*-*-*-*-*-*"),
836 facename.c_str());
837
838 if ( wxTestFontSpec(fontSpec) )
839 {
840 xfamily = facename;
841 }
842 //else: no such family, use default one instead
843 }
844
845 wxString xstyle;
846 switch (style)
847 {
848 case wxSLANT:
849 fontSpec.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
850 xfamily.c_str());
851 if ( wxTestFontSpec(fontSpec) )
852 {
853 xstyle = wxT("o");
854 break;
855 }
856 // fall through - try wxITALIC now
857
858 case wxITALIC:
859 fontSpec.Printf(wxT("-*-%s-*-i-*-*-*-*-*-*-*-*-*-*"),
860 xfamily.c_str());
861 if ( wxTestFontSpec(fontSpec) )
862 {
863 xstyle = wxT("i");
864 }
865 else if ( style == wxITALIC ) // and not wxSLANT
866 {
867 // try wxSLANT
868 fontSpec.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
869 xfamily.c_str());
870 if ( wxTestFontSpec(fontSpec) )
871 {
872 xstyle = wxT("o");
873 }
874 else
875 {
876 // no italic, no slant - leave default
877 xstyle = wxT("*");
878 }
879 }
880 break;
881
882 default:
883 wxFAIL_MSG(_T("unknown font style"));
884 // fall back to normal
885
886 case wxNORMAL:
887 xstyle = wxT("r");
888 break;
889 }
890
891 wxString xweight;
892 switch (weight)
893 {
894 case wxBOLD:
895 {
896 fontSpec.Printf(wxT("-*-%s-bold-*-*-*-*-*-*-*-*-*-*-*"),
897 xfamily.c_str());
898 if ( wxTestFontSpec(fontSpec) )
899 {
900 xweight = wxT("bold");
901 break;
902 }
903 fontSpec.Printf(wxT("-*-%s-heavy-*-*-*-*-*-*-*-*-*-*-*"),
904 xfamily.c_str());
905 if ( wxTestFontSpec(fontSpec) )
906 {
907 xweight = wxT("heavy");
908 break;
909 }
910 fontSpec.Printf(wxT("-*-%s-extrabold-*-*-*-*-*-*-*-*-*-*-*"),
911 xfamily.c_str());
912 if ( wxTestFontSpec(fontSpec) )
913 {
914 xweight = wxT("extrabold");
915 break;
916 }
917 fontSpec.Printf(wxT("-*-%s-demibold-*-*-*-*-*-*-*-*-*-*-*"),
918 xfamily.c_str());
919 if ( wxTestFontSpec(fontSpec) )
920 {
921 xweight = wxT("demibold");
922 break;
923 }
924 fontSpec.Printf(wxT("-*-%s-black-*-*-*-*-*-*-*-*-*-*-*"),
925 xfamily.c_str());
926 if ( wxTestFontSpec(fontSpec) )
927 {
928 xweight = wxT("black");
929 break;
930 }
931 fontSpec.Printf(wxT("-*-%s-ultrablack-*-*-*-*-*-*-*-*-*-*-*"),
932 xfamily.c_str());
933 if ( wxTestFontSpec(fontSpec) )
934 {
935 xweight = wxT("ultrablack");
936 break;
937 }
938 }
939 break;
940 case wxLIGHT:
941 {
942 fontSpec.Printf(wxT("-*-%s-light-*-*-*-*-*-*-*-*-*-*-*"),
943 xfamily.c_str());
944 if ( wxTestFontSpec(fontSpec) )
945 {
946 xweight = wxT("light");
947 break;
948 }
949 fontSpec.Printf(wxT("-*-%s-thin-*-*-*-*-*-*-*-*-*-*-*"),
950 xfamily.c_str());
951 if ( wxTestFontSpec(fontSpec) )
952 {
953 xweight = wxT("thin");
954 break;
955 }
956 }
957 break;
958 case wxNORMAL:
959 {
960 fontSpec.Printf(wxT("-*-%s-medium-*-*-*-*-*-*-*-*-*-*-*"),
961 xfamily.c_str());
962 if ( wxTestFontSpec(fontSpec) )
963 {
964 xweight = wxT("medium");
965 break;
966 }
967 fontSpec.Printf(wxT("-*-%s-normal-*-*-*-*-*-*-*-*-*-*-*"),
968 xfamily.c_str());
969 if ( wxTestFontSpec(fontSpec) )
970 {
971 xweight = wxT("normal");
972 break;
973 }
974 fontSpec.Printf(wxT("-*-%s-regular-*-*-*-*-*-*-*-*-*-*-*"),
975 xfamily.c_str());
976 if ( wxTestFontSpec(fontSpec) )
977 {
978 xweight = wxT("regular");
979 break;
980 }
981 xweight = wxT("*");
982 }
983 break;
984 default: xweight = wxT("*"); break;
985 }
986
987 // if pointSize is -1, don't specify any
988 wxString sizeSpec;
989 if ( pointSize == -1 )
990 {
991 sizeSpec = _T('*');
992 }
993 else
994 {
995 sizeSpec.Printf(_T("%d"), pointSize);
996 }
997
998 // construct the X font spec from our data
999 fontSpec.Printf(wxT("-*-%s-%s-%s-normal-*-*-%s-*-*-*-*-%s-%s"),
1000 xfamily.c_str(), xweight.c_str(), xstyle.c_str(),
1001 sizeSpec.c_str(), xregistry.c_str(), xencoding.c_str());
1002
1003 if( xFontName )
1004 *xFontName = fontSpec;
1005
1006 return wxLoadFont(fontSpec);
1007 #endif
1008 // wxUSE_NANOX
1009 }
1010
1011 // ----------------------------------------------------------------------------
1012 // wxFontModule
1013 // ----------------------------------------------------------------------------
1014
1015 class wxFontModule : public wxModule
1016 {
1017 public:
1018 bool OnInit();
1019 void OnExit();
1020
1021 private:
1022 DECLARE_DYNAMIC_CLASS(wxFontModule)
1023 };
1024
1025 IMPLEMENT_DYNAMIC_CLASS(wxFontModule, wxModule)
1026
1027 bool wxFontModule::OnInit()
1028 {
1029 g_fontHash = new wxHashTable( wxKEY_STRING );
1030
1031 return TRUE;
1032 }
1033
1034 void wxFontModule::OnExit()
1035 {
1036 delete g_fontHash;
1037
1038 g_fontHash = (wxHashTable *)NULL;
1039 }
1040
1041 #endif
1042 // not GTK 2.0
1043