]> git.saurik.com Git - wxWidgets.git/blob - src/unix/fontutil.cpp
Some doc tweaks
[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 #ifdef __X__
35 #ifdef __VMS__
36 #pragma message disable nosimpint
37 #endif
38
39 #include <X11/Xlib.h>
40
41 #ifdef __VMS__
42 #pragma message enable nosimpint
43 #endif
44
45 #include "wx/utils.h" // for wxGetDisplay()
46 #elif defined(__WXGTK__)
47 // we have to declare struct tm to avoid problems with first forward
48 // declaring it in C code (glib.h included from gdk.h does it) and then
49 // defining it when time.h is included from the headers below - this is
50 // known not to work at least with Sun CC 6.01
51 #include <time.h>
52
53 #include <gdk/gdk.h>
54 #endif
55
56 #include "wx/fontutil.h"
57 #include "wx/fontmap.h"
58 #include "wx/tokenzr.h"
59 #include "wx/hash.h"
60 #include "wx/module.h"
61
62 // ----------------------------------------------------------------------------
63 // private data
64 // ----------------------------------------------------------------------------
65
66 static wxHashTable *g_fontHash = (wxHashTable*) NULL;
67
68 // ----------------------------------------------------------------------------
69 // private functions
70 // ----------------------------------------------------------------------------
71
72 // define the functions to create and destroy native fonts for this toolkit
73 #ifdef __X__
74 wxNativeFont wxLoadFont(const wxString& fontSpec)
75 {
76 return XLoadQueryFont((Display *)wxGetDisplay(), fontSpec);
77 }
78
79 inline void wxFreeFont(wxNativeFont font)
80 {
81 XFreeFont((Display *)wxGetDisplay(), (XFontStruct *)font);
82 }
83 #elif defined(__WXGTK__)
84 wxNativeFont wxLoadFont(const wxString& fontSpec)
85 {
86 return gdk_font_load( wxConvertWX2MB(fontSpec) );
87 }
88
89 inline void wxFreeFont(wxNativeFont font)
90 {
91 gdk_font_unref(font);
92 }
93 #else
94 #error "Unknown GUI toolkit"
95 #endif
96
97 static bool wxTestFontSpec(const wxString& fontspec);
98
99 static wxNativeFont wxLoadQueryFont(int pointSize,
100 int family,
101 int style,
102 int weight,
103 bool underlined,
104 const wxString& facename,
105 const wxString& xregistry,
106 const wxString& xencoding,
107 wxString* xFontName);
108
109 // ============================================================================
110 // implementation
111 // ============================================================================
112
113 // ----------------------------------------------------------------------------
114 // wxNativeEncodingInfo
115 // ----------------------------------------------------------------------------
116
117 // convert to/from the string representation: format is
118 // encodingid;registry;encoding[;facename]
119 bool wxNativeEncodingInfo::FromString(const wxString& s)
120 {
121 // use ";", not "-" because it may be part of encoding name
122 wxStringTokenizer tokenizer(s, _T(";"));
123
124 wxString encid = tokenizer.GetNextToken();
125 long enc;
126 if ( !encid.ToLong(&enc) )
127 return FALSE;
128 encoding = (wxFontEncoding)enc;
129
130 xregistry = tokenizer.GetNextToken();
131 if ( !xregistry )
132 return FALSE;
133
134 xencoding = tokenizer.GetNextToken();
135 if ( !xencoding )
136 return FALSE;
137
138 // ok even if empty
139 facename = tokenizer.GetNextToken();
140
141 return TRUE;
142 }
143
144 wxString wxNativeEncodingInfo::ToString() const
145 {
146 wxString s;
147 s << (long)encoding << _T(';') << xregistry << _T(';') << xencoding;
148 if ( !!facename )
149 {
150 s << _T(';') << facename;
151 }
152
153 return s;
154 }
155
156 // ----------------------------------------------------------------------------
157 // wxNativeFontInfo
158 // ----------------------------------------------------------------------------
159
160 void wxNativeFontInfo::Init()
161 {
162 m_isDefault = TRUE;
163 }
164
165 bool wxNativeFontInfo::FromString(const wxString& s)
166 {
167 wxStringTokenizer tokenizer(s, _T(";"));
168
169 // check the version
170 wxString token = tokenizer.GetNextToken();
171 if ( token != _T('0') )
172 return FALSE;
173
174 xFontName = tokenizer.GetNextToken();
175
176 // this should be the end
177 if ( tokenizer.HasMoreTokens() )
178 return FALSE;
179
180 return FromXFontName(xFontName);
181 }
182
183 wxString wxNativeFontInfo::ToString() const
184 {
185 // 0 is the version
186 return wxString::Format(_T("%d;%s"), 0, GetXFontName().c_str());
187 }
188
189 bool wxNativeFontInfo::FromUserString(const wxString& s)
190 {
191 return FromXFontName(s);
192 }
193
194 wxString wxNativeFontInfo::ToUserString() const
195 {
196 return GetXFontName();
197 }
198
199 bool wxNativeFontInfo::HasElements() const
200 {
201 // we suppose that the foundry is never empty, so if it is it means that we
202 // had never parsed the XLFD
203 return !fontElements[0].empty();
204 }
205
206 wxString wxNativeFontInfo::GetXFontComponent(wxXLFDField field) const
207 {
208 wxCHECK_MSG( field < wxXLFD_MAX, _T(""), _T("invalid XLFD field") );
209
210 if ( !HasElements() )
211 {
212 // const_cast
213 if ( !((wxNativeFontInfo *)this)->FromXFontName(xFontName) )
214 return _T("");
215 }
216
217 return fontElements[field];
218 }
219
220 bool wxNativeFontInfo::FromXFontName(const wxString& fontname)
221 {
222 // TODO: we should be able to handle the font aliases here, but how?
223 wxStringTokenizer tokenizer(fontname, _T("-"));
224
225 // skip the leading, usually empty field (font name registry)
226 if ( !tokenizer.HasMoreTokens() )
227 return FALSE;
228
229 (void)tokenizer.GetNextToken();
230
231 for ( size_t n = 0; n < WXSIZEOF(fontElements); n++ )
232 {
233 if ( !tokenizer.HasMoreTokens() )
234 {
235 // not enough elements in the XLFD - or maybe an alias
236 return FALSE;
237 }
238
239 fontElements[n] = tokenizer.GetNextToken();
240 }
241
242 // this should be all
243 return !tokenizer.HasMoreTokens();
244 }
245
246 wxString wxNativeFontInfo::GetXFontName() const
247 {
248 if ( xFontName.empty() )
249 {
250 for ( size_t n = 0; n < WXSIZEOF(fontElements); n++ )
251 {
252 // replace the non specified elements with '*' except for the
253 // additional style which is usually just omitted
254 wxString elt = fontElements[n];
255 if ( elt.empty() && n != wxXLFD_ADDSTYLE )
256 {
257 elt = _T('*');
258 }
259
260 // const_cast
261 ((wxNativeFontInfo *)this)->xFontName << _T('-') << elt;
262 }
263 }
264
265 return xFontName;
266 }
267
268 void
269 wxNativeFontInfo::SetXFontComponent(wxXLFDField field, const wxString& value)
270 {
271 wxCHECK_RET( field < wxXLFD_MAX, _T("invalid XLFD field") );
272
273 // this class should be initialized with a valid font spec first and only
274 // then the fields may be modified!
275 wxASSERT_MSG( !IsDefault(), _T("can't modify an uninitialized XLFD") );
276
277 if ( !HasElements() )
278 {
279 // const_cast
280 if ( !((wxNativeFontInfo *)this)->FromXFontName(xFontName) )
281 {
282 wxFAIL_MSG( _T("can't set font element for invalid XLFD") );
283
284 return;
285 }
286 }
287
288 fontElements[field] = value;
289
290 // invalidate the XFLD, it doesn't correspond to the font elements any more
291 xFontName.clear();
292 }
293
294 void wxNativeFontInfo::SetXFontName(const wxString& xFontName_)
295 {
296 // invalidate the font elements, GetXFontComponent() will reparse the XLFD
297 fontElements[0].clear();
298
299 xFontName = xFontName_;
300
301 m_isDefault = FALSE;
302 }
303
304 // ----------------------------------------------------------------------------
305 // common functions
306 // ----------------------------------------------------------------------------
307
308 bool wxGetNativeFontEncoding(wxFontEncoding encoding,
309 wxNativeEncodingInfo *info)
310 {
311 wxCHECK_MSG( info, FALSE, _T("bad pointer in wxGetNativeFontEncoding") );
312
313 if ( encoding == wxFONTENCODING_DEFAULT )
314 {
315 encoding = wxFont::GetDefaultEncoding();
316 }
317
318 switch ( encoding )
319 {
320 case wxFONTENCODING_ISO8859_1:
321 case wxFONTENCODING_ISO8859_2:
322 case wxFONTENCODING_ISO8859_3:
323 case wxFONTENCODING_ISO8859_4:
324 case wxFONTENCODING_ISO8859_5:
325 case wxFONTENCODING_ISO8859_6:
326 case wxFONTENCODING_ISO8859_7:
327 case wxFONTENCODING_ISO8859_8:
328 case wxFONTENCODING_ISO8859_9:
329 case wxFONTENCODING_ISO8859_10:
330 case wxFONTENCODING_ISO8859_11:
331 case wxFONTENCODING_ISO8859_12:
332 case wxFONTENCODING_ISO8859_13:
333 case wxFONTENCODING_ISO8859_14:
334 case wxFONTENCODING_ISO8859_15:
335 {
336 int cp = encoding - wxFONTENCODING_ISO8859_1 + 1;
337 info->xregistry = wxT("iso8859");
338 info->xencoding.Printf(wxT("%d"), cp);
339 }
340 break;
341
342 case wxFONTENCODING_UTF8:
343 info->xregistry = wxT("iso10646");
344 info->xencoding = wxT("*");
345 break;
346
347 case wxFONTENCODING_KOI8:
348 info->xregistry = wxT("koi8");
349
350 // we don't make distinction between koi8-r, koi8-u and koi8-ru (so far)
351 info->xencoding = wxT("*");
352 break;
353
354 case wxFONTENCODING_CP1250:
355 case wxFONTENCODING_CP1251:
356 case wxFONTENCODING_CP1252:
357 case wxFONTENCODING_CP1253:
358 case wxFONTENCODING_CP1254:
359 case wxFONTENCODING_CP1255:
360 case wxFONTENCODING_CP1256:
361 case wxFONTENCODING_CP1257:
362 {
363 int cp = encoding - wxFONTENCODING_CP1250 + 1250;
364 info->xregistry = wxT("microsoft");
365 info->xencoding.Printf(wxT("cp%d"), cp);
366 }
367 break;
368
369 case wxFONTENCODING_SYSTEM:
370 info->xregistry =
371 info->xencoding = wxT("*");
372 break;
373
374 default:
375 // don't know how to translate this encoding into X fontspec
376 return FALSE;
377 }
378
379 info->encoding = encoding;
380
381 return TRUE;
382 }
383
384 bool wxTestFontEncoding(const wxNativeEncodingInfo& info)
385 {
386 wxString fontspec;
387 fontspec.Printf(_T("-*-%s-*-*-*-*-*-*-*-*-*-*-%s-%s"),
388 !info.facename ? _T("*") : info.facename.c_str(),
389 info.xregistry.c_str(),
390 info.xencoding.c_str());
391
392 return wxTestFontSpec(fontspec);
393 }
394
395 // ----------------------------------------------------------------------------
396 // X-specific functions
397 // ----------------------------------------------------------------------------
398
399 wxNativeFont wxLoadQueryNearestFont(int pointSize,
400 int family,
401 int style,
402 int weight,
403 bool underlined,
404 const wxString &facename,
405 wxFontEncoding encoding,
406 wxString* xFontName)
407 {
408 if ( encoding == wxFONTENCODING_DEFAULT )
409 {
410 encoding = wxFont::GetDefaultEncoding();
411 }
412
413 // first determine the encoding - if the font doesn't exist at all in this
414 // encoding, it's useless to do all other approximations (i.e. size,
415 // family &c don't matter much)
416 wxNativeEncodingInfo info;
417 if ( encoding == wxFONTENCODING_SYSTEM )
418 {
419 // This will always work so we don't test to save time
420 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
421 }
422 else
423 {
424 if ( !wxGetNativeFontEncoding(encoding, &info) ||
425 !wxTestFontEncoding(info) )
426 {
427 #if wxUSE_FONTMAP
428 if ( !wxTheFontMapper->GetAltForEncoding(encoding, &info) )
429 #endif // wxUSE_FONTMAP
430 {
431 // unspported encoding - replace it with the default
432 //
433 // NB: we can't just return 0 from here because wxGTK code doesn't
434 // check for it (i.e. it supposes that we'll always succeed),
435 // so it would provoke a crash
436 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
437 }
438 }
439 }
440
441 // OK, we have the correct xregistry/xencoding in info structure
442 wxNativeFont font = 0;
443
444 // if we already have the X font name, try to use it
445 if( xFontName && !xFontName->IsEmpty() )
446 {
447 //
448 // Make sure point size is correct for scale factor.
449 //
450 wxStringTokenizer tokenizer(*xFontName, _T("-"), wxTOKEN_RET_DELIMS);
451 wxString newFontName;
452
453 for(int i = 0; i < 8; i++)
454 newFontName += tokenizer.NextToken();
455
456 (void) tokenizer.NextToken();
457
458 newFontName += wxString::Format("%d-", pointSize);
459
460 while(tokenizer.HasMoreTokens())
461 newFontName += tokenizer.GetNextToken();
462
463 font = wxLoadFont(newFontName);
464
465 if(font)
466 *xFontName = newFontName;
467 }
468
469 // try to load exactly the font requested first
470 if( !font )
471 {
472 font = wxLoadQueryFont( pointSize, family, style, weight,
473 underlined, facename,
474 info.xregistry, info.xencoding,
475 xFontName );
476 }
477
478 if ( !font )
479 {
480 // search up and down by stepsize 10
481 int max_size = pointSize + 20 * (1 + (pointSize/180));
482 int min_size = pointSize - 20 * (1 + (pointSize/180));
483
484 int i;
485
486 // Search for smaller size (approx.)
487 for ( i = pointSize - 10; !font && i >= 10 && i >= min_size; i -= 10 )
488 {
489 font = wxLoadQueryFont(i, family, style, weight, underlined,
490 facename, info.xregistry, info.xencoding,
491 xFontName);
492 }
493
494 // Search for larger size (approx.)
495 for ( i = pointSize + 10; !font && i <= max_size; i += 10 )
496 {
497 font = wxLoadQueryFont(i, family, style, weight, underlined,
498 facename, info.xregistry, info.xencoding,
499 xFontName);
500 }
501
502 // Try default family
503 if ( !font && family != wxDEFAULT )
504 {
505 font = wxLoadQueryFont(pointSize, wxDEFAULT, style, weight,
506 underlined, facename,
507 info.xregistry, info.xencoding,
508 xFontName );
509 }
510
511 // ignore size, family, style and weight but try to find font with the
512 // given facename and encoding
513 if ( !font )
514 {
515 font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
516 underlined, facename,
517 info.xregistry, info.xencoding,
518 xFontName);
519
520 // ignore family as well
521 if ( !font )
522 {
523 font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
524 underlined, wxEmptyString,
525 info.xregistry, info.xencoding,
526 xFontName);
527
528 // if it still failed, try to get the font of any size but
529 // with the requested encoding: this can happen if the
530 // encoding is only available in one size which happens to be
531 // different from 120
532 if ( !font )
533 {
534 font = wxLoadQueryFont(-1, wxDEFAULT, wxNORMAL, wxNORMAL,
535 FALSE, wxEmptyString,
536 info.xregistry, info.xencoding,
537 xFontName);
538
539 // this should never happen as we had tested for it in the
540 // very beginning, but if it does, do return something non
541 // NULL or we'd crash in wxFont code
542 if ( !font )
543 {
544 wxFAIL_MSG( _T("this encoding should be available!") );
545
546 font = wxLoadQueryFont(-1,
547 wxDEFAULT, wxNORMAL, wxNORMAL,
548 FALSE, wxEmptyString,
549 _T("*"), _T("*"),
550 xFontName);
551 }
552 }
553 }
554 }
555 }
556
557 return font;
558 }
559
560 // ----------------------------------------------------------------------------
561 // private functions
562 // ----------------------------------------------------------------------------
563
564 // returns TRUE if there are any fonts matching this font spec
565 static bool wxTestFontSpec(const wxString& fontspec)
566 {
567 // some X servers will fail to load this font because there are too many
568 // matches so we must test explicitly for this
569 if ( fontspec == _T("-*-*-*-*-*-*-*-*-*-*-*-*-*-*") )
570 {
571 return TRUE;
572 }
573
574 wxNativeFont test = (wxNativeFont) g_fontHash->Get( fontspec );
575 if (test)
576 {
577 return TRUE;
578 }
579
580 test = wxLoadFont(fontspec);
581 g_fontHash->Put( fontspec, (wxObject*) test );
582
583 if ( test )
584 {
585 wxFreeFont(test);
586
587 return TRUE;
588 }
589 else
590 {
591 return FALSE;
592 }
593 }
594
595 static wxNativeFont wxLoadQueryFont(int pointSize,
596 int family,
597 int style,
598 int weight,
599 bool WXUNUSED(underlined),
600 const wxString& facename,
601 const wxString& xregistry,
602 const wxString& xencoding,
603 wxString* xFontName)
604 {
605 wxString xfamily;
606 switch (family)
607 {
608 case wxDECORATIVE: xfamily = wxT("lucida"); break;
609 case wxROMAN: xfamily = wxT("times"); break;
610 case wxMODERN: xfamily = wxT("courier"); break;
611 case wxSWISS: xfamily = wxT("helvetica"); break;
612 case wxTELETYPE: xfamily = wxT("lucidatypewriter"); break;
613 case wxSCRIPT: xfamily = wxT("utopia"); break;
614 default: xfamily = wxT("*");
615 }
616
617 wxString fontSpec;
618 if (!facename.IsEmpty())
619 {
620 fontSpec.Printf(wxT("-*-%s-*-*-normal-*-*-*-*-*-*-*-*-*"),
621 facename.c_str());
622
623 if ( wxTestFontSpec(fontSpec) )
624 {
625 xfamily = facename;
626 }
627 //else: no such family, use default one instead
628 }
629
630 wxString xstyle;
631 switch (style)
632 {
633 case wxSLANT:
634 fontSpec.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
635 xfamily.c_str());
636 if ( wxTestFontSpec(fontSpec) )
637 {
638 xstyle = wxT("o");
639 break;
640 }
641 // fall through - try wxITALIC now
642
643 case wxITALIC:
644 fontSpec.Printf(wxT("-*-%s-*-i-*-*-*-*-*-*-*-*-*-*"),
645 xfamily.c_str());
646 if ( wxTestFontSpec(fontSpec) )
647 {
648 xstyle = wxT("i");
649 }
650 else if ( style == wxITALIC ) // and not wxSLANT
651 {
652 // try wxSLANT
653 fontSpec.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
654 xfamily.c_str());
655 if ( wxTestFontSpec(fontSpec) )
656 {
657 xstyle = wxT("o");
658 }
659 else
660 {
661 // no italic, no slant - leave default
662 xstyle = wxT("*");
663 }
664 }
665 break;
666
667 default:
668 wxFAIL_MSG(_T("unknown font style"));
669 // fall back to normal
670
671 case wxNORMAL:
672 xstyle = wxT("r");
673 break;
674 }
675
676 wxString xweight;
677 switch (weight)
678 {
679 case wxBOLD:
680 {
681 fontSpec.Printf(wxT("-*-%s-bold-*-*-*-*-*-*-*-*-*-*-*"),
682 xfamily.c_str());
683 if ( wxTestFontSpec(fontSpec) )
684 {
685 xweight = wxT("bold");
686 break;
687 }
688 fontSpec.Printf(wxT("-*-%s-heavy-*-*-*-*-*-*-*-*-*-*-*"),
689 xfamily.c_str());
690 if ( wxTestFontSpec(fontSpec) )
691 {
692 xweight = wxT("heavy");
693 break;
694 }
695 fontSpec.Printf(wxT("-*-%s-extrabold-*-*-*-*-*-*-*-*-*-*-*"),
696 xfamily.c_str());
697 if ( wxTestFontSpec(fontSpec) )
698 {
699 xweight = wxT("extrabold");
700 break;
701 }
702 fontSpec.Printf(wxT("-*-%s-demibold-*-*-*-*-*-*-*-*-*-*-*"),
703 xfamily.c_str());
704 if ( wxTestFontSpec(fontSpec) )
705 {
706 xweight = wxT("demibold");
707 break;
708 }
709 fontSpec.Printf(wxT("-*-%s-black-*-*-*-*-*-*-*-*-*-*-*"),
710 xfamily.c_str());
711 if ( wxTestFontSpec(fontSpec) )
712 {
713 xweight = wxT("black");
714 break;
715 }
716 fontSpec.Printf(wxT("-*-%s-ultrablack-*-*-*-*-*-*-*-*-*-*-*"),
717 xfamily.c_str());
718 if ( wxTestFontSpec(fontSpec) )
719 {
720 xweight = wxT("ultrablack");
721 break;
722 }
723 }
724 break;
725 case wxLIGHT:
726 {
727 fontSpec.Printf(wxT("-*-%s-light-*-*-*-*-*-*-*-*-*-*-*"),
728 xfamily.c_str());
729 if ( wxTestFontSpec(fontSpec) )
730 {
731 xweight = wxT("light");
732 break;
733 }
734 fontSpec.Printf(wxT("-*-%s-thin-*-*-*-*-*-*-*-*-*-*-*"),
735 xfamily.c_str());
736 if ( wxTestFontSpec(fontSpec) )
737 {
738 xweight = wxT("thin");
739 break;
740 }
741 }
742 break;
743 case wxNORMAL:
744 {
745 fontSpec.Printf(wxT("-*-%s-medium-*-*-*-*-*-*-*-*-*-*-*"),
746 xfamily.c_str());
747 if ( wxTestFontSpec(fontSpec) )
748 {
749 xweight = wxT("medium");
750 break;
751 }
752 fontSpec.Printf(wxT("-*-%s-normal-*-*-*-*-*-*-*-*-*-*-*"),
753 xfamily.c_str());
754 if ( wxTestFontSpec(fontSpec) )
755 {
756 xweight = wxT("normal");
757 break;
758 }
759 fontSpec.Printf(wxT("-*-%s-regular-*-*-*-*-*-*-*-*-*-*-*"),
760 xfamily.c_str());
761 if ( wxTestFontSpec(fontSpec) )
762 {
763 xweight = wxT("regular");
764 break;
765 }
766 xweight = wxT("*");
767 }
768 break;
769 default: xweight = wxT("*"); break;
770 }
771
772 // if pointSize is -1, don't specify any
773 wxString sizeSpec;
774 if ( fontSpec == -1 )
775 {
776 sizeSpec = _T('*');
777 }
778 else
779 {
780 sizeSpec.Printf(_T("%d"), pointSize);
781 }
782
783 // construct the X font spec from our data
784 fontSpec.Printf(wxT("-*-%s-%s-%s-normal-*-*-%s-*-*-*-*-%s-%s"),
785 xfamily.c_str(), xweight.c_str(), xstyle.c_str(),
786 sizeSpec.c_str(), xregistry.c_str(), xencoding.c_str());
787
788 if( xFontName )
789 *xFontName = fontSpec;
790
791 return wxLoadFont(fontSpec);
792 }
793
794 // ----------------------------------------------------------------------------
795 // wxFontModule
796 // ----------------------------------------------------------------------------
797
798 class wxFontModule : public wxModule
799 {
800 public:
801 bool OnInit();
802 void OnExit();
803
804 private:
805 DECLARE_DYNAMIC_CLASS(wxFontModule)
806 };
807
808 IMPLEMENT_DYNAMIC_CLASS(wxFontModule, wxModule)
809
810 bool wxFontModule::OnInit()
811 {
812 g_fontHash = new wxHashTable( wxKEY_STRING );
813
814 return TRUE;
815 }
816
817 void wxFontModule::OnExit()
818 {
819 delete g_fontHash;
820
821 g_fontHash = (wxHashTable *)NULL;
822 }