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