]> git.saurik.com Git - wxWidgets.git/blame - src/unix/fontutil.cpp
compilation fix for non-threaded compilation (threads are still broken
[wxWidgets.git] / src / unix / fontutil.cpp
CommitLineData
7beba2fc
VZ
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
79e4b627 34#ifdef __X__
338dd992
JJ
35#ifdef __VMS__
36#pragma message disable nosimpint
37#endif
38#include <X11/Xlib.h>
39#ifdef __VMS__
40#pragma message enable nosimpint
41#endif
79e4b627
VZ
42
43 #include "wx/utils.h" // for wxGetDisplay()
44#elif defined(__WXGTK__)
45 #include "gdk/gdk.h"
46#endif
47
7beba2fc
VZ
48#include "wx/fontutil.h"
49#include "wx/fontmap.h"
50#include "wx/tokenzr.h"
2e0e025e
RR
51#include "wx/hash.h"
52#include "wx/module.h"
53
54// ----------------------------------------------------------------------------
55// private data
56// ----------------------------------------------------------------------------
57
58static wxHashTable *g_fontHash = (wxHashTable*) NULL;
7beba2fc
VZ
59
60// ----------------------------------------------------------------------------
61// private functions
62// ----------------------------------------------------------------------------
63
64// define the functions to create and destroy native fonts for this toolkit
65#ifdef __X__
66 static inline wxNativeFont wxLoadFont(const wxString& fontSpec)
67 {
68 return XLoadQueryFont((Display *)wxGetDisplay(), fontSpec);
69 }
70
71 static inline void wxFreeFont(wxNativeFont font)
72 {
a5fc62a1 73 XFreeFont((Display *)wxGetDisplay(), (XFontStruct *)font);
7beba2fc
VZ
74 }
75#elif defined(__WXGTK__)
7beba2fc
VZ
76 static inline wxNativeFont wxLoadFont(const wxString& fontSpec)
77 {
97d3f0ee 78 return gdk_font_load( wxConvertWX2MB(fontSpec) );
7beba2fc
VZ
79 }
80
81 static inline void wxFreeFont(wxNativeFont font)
82 {
83 gdk_font_unref(font);
84 }
85#else
86 #error "Unknown GUI toolkit"
87#endif
88
89static bool wxTestFontSpec(const wxString& fontspec);
90
91static wxNativeFont wxLoadQueryFont(int pointSize,
92 int family,
93 int style,
94 int weight,
95 bool underlined,
96 const wxString& facename,
97 const wxString& xregistry,
98 const wxString& xencoding);
99
100// ============================================================================
101// implementation
102// ============================================================================
103
104// ----------------------------------------------------------------------------
105// wxNativeEncodingInfo
106// ----------------------------------------------------------------------------
107
108// convert to/from the string representation: format is
109// registry-encoding[-facename]
110bool wxNativeEncodingInfo::FromString(const wxString& s)
111{
112 wxStringTokenizer tokenizer(s, _T("-"));
113
114 xregistry = tokenizer.GetNextToken();
115 if ( !xregistry )
116 return FALSE;
117
118 xencoding = tokenizer.GetNextToken();
119 if ( !xencoding )
120 return FALSE;
121
122 // ok even if empty
123 facename = tokenizer.GetNextToken();
124
125 return TRUE;
126}
127
128wxString wxNativeEncodingInfo::ToString() const
129{
130 wxString s;
131 s << xregistry << _T('-') << xencoding;
132 if ( !!facename )
133 {
134 s << _T('-') << facename;
135 }
136
137 return s;
138}
139
140// ----------------------------------------------------------------------------
141// common functions
142// ----------------------------------------------------------------------------
143
144bool wxGetNativeFontEncoding(wxFontEncoding encoding,
145 wxNativeEncodingInfo *info)
146{
147 wxCHECK_MSG( info, FALSE, _T("bad pointer in wxGetNativeFontEncoding") );
148
149 if ( encoding == wxFONTENCODING_DEFAULT )
150 {
151 encoding = wxFont::GetDefaultEncoding();
152 }
153
154 switch ( encoding )
155 {
156 case wxFONTENCODING_ISO8859_1:
157 case wxFONTENCODING_ISO8859_2:
158 case wxFONTENCODING_ISO8859_3:
159 case wxFONTENCODING_ISO8859_4:
160 case wxFONTENCODING_ISO8859_5:
161 case wxFONTENCODING_ISO8859_6:
162 case wxFONTENCODING_ISO8859_7:
163 case wxFONTENCODING_ISO8859_8:
164 case wxFONTENCODING_ISO8859_9:
165 case wxFONTENCODING_ISO8859_10:
166 case wxFONTENCODING_ISO8859_11:
167 case wxFONTENCODING_ISO8859_13:
168 case wxFONTENCODING_ISO8859_14:
169 case wxFONTENCODING_ISO8859_15:
170 {
171 int cp = encoding - wxFONTENCODING_ISO8859_1 + 1;
172 info->xregistry = wxT("iso8859");
173 info->xencoding.Printf(wxT("%d"), cp);
174 }
175 break;
176
177 case wxFONTENCODING_KOI8:
178 info->xregistry = wxT("koi8");
179
180 // we don't make distinction between koi8-r and koi8-u (so far)
181 info->xencoding = wxT("*");
182 break;
183
184 case wxFONTENCODING_CP1250:
185 case wxFONTENCODING_CP1251:
186 case wxFONTENCODING_CP1252:
187 case wxFONTENCODING_CP1253:
188 case wxFONTENCODING_CP1254:
189 case wxFONTENCODING_CP1255:
190 case wxFONTENCODING_CP1256:
191 case wxFONTENCODING_CP1257:
192 {
193 int cp = encoding - wxFONTENCODING_CP1250 + 1250;
194 info->xregistry = wxT("microsoft");
195 info->xencoding.Printf(wxT("cp%d"), cp);
196 }
197 break;
198
199 case wxFONTENCODING_SYSTEM:
200 info->xregistry =
81c67e27 201 info->xencoding = wxT("*");
7beba2fc
VZ
202 break;
203
204 default:
205 // don't know how to translate this encoding into X fontspec
206 return FALSE;
207 }
208
6b0eebc5
VS
209 info->encoding = encoding;
210
7beba2fc
VZ
211 return TRUE;
212}
213
214bool wxTestFontEncoding(const wxNativeEncodingInfo& info)
215{
216 wxString fontspec;
217 fontspec.Printf(_T("-*-%s-*-*-*-*-*-*-*-*-*-*-%s-%s"),
218 !info.facename ? _T("*") : info.facename.c_str(),
219 info.xregistry.c_str(),
220 info.xencoding.c_str());
221
222 return wxTestFontSpec(fontspec);
223}
224
225// ----------------------------------------------------------------------------
226// X-specific functions
227// ----------------------------------------------------------------------------
228
229wxNativeFont wxLoadQueryNearestFont(int pointSize,
230 int family,
231 int style,
232 int weight,
233 bool underlined,
234 const wxString &facename,
235 wxFontEncoding encoding)
236{
97d3f0ee
VZ
237 if ( encoding == wxFONTENCODING_DEFAULT )
238 {
239 encoding = wxFont::GetDefaultEncoding();
240 }
241
7beba2fc
VZ
242 // first determine the encoding - if the font doesn't exist at all in this
243 // encoding, it's useless to do all other approximations (i.e. size,
244 // family &c don't matter much)
245 wxNativeEncodingInfo info;
97d3f0ee 246 if ( encoding == wxFONTENCODING_SYSTEM )
81c67e27
RR
247 {
248 // This will always work so we don't test to save time
249 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
250 }
251 else
7beba2fc 252 {
81c67e27
RR
253 if ( !wxGetNativeFontEncoding(encoding, &info) ||
254 !wxTestFontEncoding(info) )
7beba2fc 255 {
81c67e27
RR
256 if ( !wxTheFontMapper->GetAltForEncoding(encoding, &info) )
257 {
258 // unspported encoding - replace it with the default
259 //
260 // NB: we can't just return 0 from here because wxGTK code doesn't
261 // check for it (i.e. it supposes that we'll always succeed),
262 // so it would provoke a crash
263 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
264 }
97d3f0ee 265 }
7beba2fc 266 }
81c67e27
RR
267
268 // OK, we have the correct xregistry/xencoding in info structure
7beba2fc
VZ
269 wxNativeFont font = wxLoadQueryFont( pointSize, family, style, weight,
270 underlined, facename,
271 info.xregistry, info.xencoding );
272
273 if ( !font )
274 {
275 // search up and down by stepsize 10
276 int max_size = pointSize + 20 * (1 + (pointSize/180));
277 int min_size = pointSize - 20 * (1 + (pointSize/180));
278
279 int i;
280
281 // Search for smaller size (approx.)
282 for ( i = pointSize - 10; !font && i >= 10 && i >= min_size; i -= 10 )
283 {
284 font = wxLoadQueryFont(i, family, style, weight, underlined,
285 facename, info.xregistry, info.xencoding);
286 }
287
288 // Search for larger size (approx.)
289 for ( i = pointSize + 10; !font && i <= max_size; i += 10 )
290 {
291 font = wxLoadQueryFont(i, family, style, weight, underlined,
292 facename, info.xregistry, info.xencoding);
293 }
294
295 // Try default family
296 if ( !font && family != wxDEFAULT )
297 {
298 font = wxLoadQueryFont(pointSize, wxDEFAULT, style, weight,
299 underlined, facename,
300 info.xregistry, info.xencoding );
301 }
302
303 // Bogus font I
304 if ( !font )
305 {
306 font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
307 underlined, facename,
308 info.xregistry, info.xencoding);
309 }
310
311 // Bogus font II
312 if ( !font )
313 {
314 font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
315 underlined, wxEmptyString,
316 info.xregistry, info.xencoding);
317 }
318 }
319
320 return font;
321}
322
323// ----------------------------------------------------------------------------
324// private functions
325// ----------------------------------------------------------------------------
326
327// returns TRUE if there are any fonts matching this font spec
328static bool wxTestFontSpec(const wxString& fontspec)
329{
97d3f0ee
VZ
330 // some X servers will fail to load this font because there are too many
331 // matches so we must test explicitly for this
332 if ( fontspec == _T("-*-*-*-*-*-*-*-*-*-*-*-*-*-*") )
333 {
334 return TRUE;
335 }
336
2e0e025e
RR
337 wxNativeFont test = (wxNativeFont) g_fontHash->Get( fontspec );
338 if (test)
339 {
340// printf( "speed up\n" );
341 return TRUE;
342 }
343
344 test = wxLoadFont(fontspec);
345 g_fontHash->Put( fontspec, (wxObject*) test );
346
7beba2fc
VZ
347 if ( test )
348 {
349 wxFreeFont(test);
350
351 return TRUE;
352 }
353 else
354 {
355 return FALSE;
356 }
357}
358
359static wxNativeFont wxLoadQueryFont(int pointSize,
360 int family,
361 int style,
362 int weight,
363 bool WXUNUSED(underlined),
364 const wxString& facename,
365 const wxString& xregistry,
366 const wxString& xencoding)
367{
368 wxString xfamily;
369 switch (family)
370 {
371 case wxDECORATIVE: xfamily = wxT("lucida"); break;
372 case wxROMAN: xfamily = wxT("times"); break;
373 case wxMODERN: xfamily = wxT("courier"); break;
374 case wxSWISS: xfamily = wxT("helvetica"); break;
375 case wxTELETYPE: xfamily = wxT("lucidatypewriter"); break;
376 case wxSCRIPT: xfamily = wxT("utopia"); break;
377 default: xfamily = wxT("*");
378 }
379
380 wxString fontSpec;
381 if (!facename.IsEmpty())
382 {
383 fontSpec.Printf(wxT("-*-%s-*-*-normal-*-*-*-*-*-*-*-*-*"),
384 facename.c_str());
385
386 if ( wxTestFontSpec(fontSpec) )
387 {
388 xfamily = facename;
389 }
390 //else: no such family, use default one instead
391 }
392
393 wxString xstyle;
394 switch (style)
395 {
f9dbf34f
VZ
396 case wxSLANT:
397 fontSpec.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
398 xfamily.c_str());
399 if ( wxTestFontSpec(fontSpec) )
400 {
401 xstyle = wxT("o");
402 break;
403 }
404 // fall through - try wxITALIC now
405
406 case wxITALIC:
407 fontSpec.Printf(wxT("-*-%s-*-i-*-*-*-*-*-*-*-*-*-*"),
408 xfamily.c_str());
409 if ( wxTestFontSpec(fontSpec) )
410 {
411 xstyle = wxT("i");
412 }
413 else if ( style == wxITALIC ) // and not wxSLANT
414 {
415 // try wxSLANT
416 fontSpec.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
417 xfamily.c_str());
418 if ( wxTestFontSpec(fontSpec) )
419 {
420 xstyle = wxT("o");
421 }
422 else
423 {
424 // no italic, no slant - leave default
425 xstyle = wxT("*");
426 }
427 }
428 break;
429
430 default:
431 wxFAIL_MSG(_T("unknown font style"));
432 // fall back to normal
433
434 case wxNORMAL:
435 xstyle = wxT("r");
436 break;
7beba2fc
VZ
437 }
438
439 wxString xweight;
440 switch (weight)
441 {
442 case wxBOLD:
443 {
444 fontSpec.Printf(wxT("-*-%s-bold-*-*-*-*-*-*-*-*-*-*-*"),
445 xfamily.c_str());
446 if ( wxTestFontSpec(fontSpec) )
447 {
448 xweight = wxT("bold");
449 break;
450 }
451 fontSpec.Printf(wxT("-*-%s-heavy-*-*-*-*-*-*-*-*-*-*-*"),
452 xfamily.c_str());
453 if ( wxTestFontSpec(fontSpec) )
454 {
455 xweight = wxT("heavy");
456 break;
457 }
458 fontSpec.Printf(wxT("-*-%s-extrabold-*-*-*-*-*-*-*-*-*-*-*"),
459 xfamily.c_str());
460 if ( wxTestFontSpec(fontSpec) )
461 {
462 xweight = wxT("extrabold");
463 break;
464 }
465 fontSpec.Printf(wxT("-*-%s-demibold-*-*-*-*-*-*-*-*-*-*-*"),
466 xfamily.c_str());
467 if ( wxTestFontSpec(fontSpec) )
468 {
469 xweight = wxT("demibold");
470 break;
471 }
472 fontSpec.Printf(wxT("-*-%s-black-*-*-*-*-*-*-*-*-*-*-*"),
473 xfamily.c_str());
474 if ( wxTestFontSpec(fontSpec) )
475 {
476 xweight = wxT("black");
477 break;
478 }
479 fontSpec.Printf(wxT("-*-%s-ultrablack-*-*-*-*-*-*-*-*-*-*-*"),
480 xfamily.c_str());
481 if ( wxTestFontSpec(fontSpec) )
482 {
483 xweight = wxT("ultrablack");
484 break;
485 }
486 }
487 break;
488 case wxLIGHT:
489 {
490 fontSpec.Printf(wxT("-*-%s-light-*-*-*-*-*-*-*-*-*-*-*"),
491 xfamily.c_str());
492 if ( wxTestFontSpec(fontSpec) )
493 {
494 xweight = wxT("light");
495 break;
496 }
497 fontSpec.Printf(wxT("-*-%s-thin-*-*-*-*-*-*-*-*-*-*-*"),
498 xfamily.c_str());
499 if ( wxTestFontSpec(fontSpec) )
500 {
501 xweight = wxT("thin");
502 break;
503 }
504 }
505 break;
506 case wxNORMAL:
507 {
508 fontSpec.Printf(wxT("-*-%s-medium-*-*-*-*-*-*-*-*-*-*-*"),
509 xfamily.c_str());
510 if ( wxTestFontSpec(fontSpec) )
511 {
512 xweight = wxT("medium");
513 break;
514 }
515 fontSpec.Printf(wxT("-*-%s-normal-*-*-*-*-*-*-*-*-*-*-*"),
516 xfamily.c_str());
517 if ( wxTestFontSpec(fontSpec) )
518 {
519 xweight = wxT("normal");
520 break;
521 }
522 fontSpec.Printf(wxT("-*-%s-regular-*-*-*-*-*-*-*-*-*-*-*"),
523 xfamily.c_str());
524 if ( wxTestFontSpec(fontSpec) )
525 {
526 xweight = wxT("regular");
527 break;
528 }
529 xweight = wxT("*");
530 }
531 break;
532 default: xweight = wxT("*"); break;
533 }
534
535 // construct the X font spec from our data
536 fontSpec.Printf(wxT("-*-%s-%s-%s-normal-*-*-%d-*-*-*-*-%s-%s"),
537 xfamily.c_str(), xweight.c_str(), xstyle.c_str(),
538 pointSize, xregistry.c_str(), xencoding.c_str());
539
540 return wxLoadFont(fontSpec);
541}
542
2e0e025e
RR
543// ----------------------------------------------------------------------------
544// wxFontModule
545// ----------------------------------------------------------------------------
546
547class wxFontModule : public wxModule
548{
549public:
550 bool OnInit();
551 void OnExit();
552
553private:
554 DECLARE_DYNAMIC_CLASS(wxFontModule)
555};
556
557IMPLEMENT_DYNAMIC_CLASS(wxFontModule, wxModule)
558
559bool wxFontModule::OnInit()
560{
561 g_fontHash = new wxHashTable( wxKEY_STRING );
562
563 return TRUE;
564}
565
566void wxFontModule::OnExit()
567{
568 delete g_fontHash;
569
570 g_fontHash = (wxHashTable *)NULL;
571}