]> git.saurik.com Git - wxWidgets.git/blame - src/unix/fontutil.cpp
1. wxBase compiles under BeOS
[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
209 return TRUE;
210}
211
212bool wxTestFontEncoding(const wxNativeEncodingInfo& info)
213{
214 wxString fontspec;
215 fontspec.Printf(_T("-*-%s-*-*-*-*-*-*-*-*-*-*-%s-%s"),
216 !info.facename ? _T("*") : info.facename.c_str(),
217 info.xregistry.c_str(),
218 info.xencoding.c_str());
219
220 return wxTestFontSpec(fontspec);
221}
222
223// ----------------------------------------------------------------------------
224// X-specific functions
225// ----------------------------------------------------------------------------
226
227wxNativeFont wxLoadQueryNearestFont(int pointSize,
228 int family,
229 int style,
230 int weight,
231 bool underlined,
232 const wxString &facename,
233 wxFontEncoding encoding)
234{
97d3f0ee
VZ
235 if ( encoding == wxFONTENCODING_DEFAULT )
236 {
237 encoding = wxFont::GetDefaultEncoding();
238 }
239
7beba2fc
VZ
240 // first determine the encoding - if the font doesn't exist at all in this
241 // encoding, it's useless to do all other approximations (i.e. size,
242 // family &c don't matter much)
243 wxNativeEncodingInfo info;
97d3f0ee 244 if ( encoding == wxFONTENCODING_SYSTEM )
81c67e27
RR
245 {
246 // This will always work so we don't test to save time
247 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
248 }
249 else
7beba2fc 250 {
81c67e27
RR
251 if ( !wxGetNativeFontEncoding(encoding, &info) ||
252 !wxTestFontEncoding(info) )
7beba2fc 253 {
81c67e27
RR
254 if ( !wxTheFontMapper->GetAltForEncoding(encoding, &info) )
255 {
256 // unspported encoding - replace it with the default
257 //
258 // NB: we can't just return 0 from here because wxGTK code doesn't
259 // check for it (i.e. it supposes that we'll always succeed),
260 // so it would provoke a crash
261 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
262 }
97d3f0ee 263 }
7beba2fc 264 }
81c67e27
RR
265
266 // OK, we have the correct xregistry/xencoding in info structure
7beba2fc
VZ
267 wxNativeFont font = wxLoadQueryFont( pointSize, family, style, weight,
268 underlined, facename,
269 info.xregistry, info.xencoding );
270
271 if ( !font )
272 {
273 // search up and down by stepsize 10
274 int max_size = pointSize + 20 * (1 + (pointSize/180));
275 int min_size = pointSize - 20 * (1 + (pointSize/180));
276
277 int i;
278
279 // Search for smaller size (approx.)
280 for ( i = pointSize - 10; !font && i >= 10 && i >= min_size; i -= 10 )
281 {
282 font = wxLoadQueryFont(i, family, style, weight, underlined,
283 facename, info.xregistry, info.xencoding);
284 }
285
286 // Search for larger size (approx.)
287 for ( i = pointSize + 10; !font && i <= max_size; i += 10 )
288 {
289 font = wxLoadQueryFont(i, family, style, weight, underlined,
290 facename, info.xregistry, info.xencoding);
291 }
292
293 // Try default family
294 if ( !font && family != wxDEFAULT )
295 {
296 font = wxLoadQueryFont(pointSize, wxDEFAULT, style, weight,
297 underlined, facename,
298 info.xregistry, info.xencoding );
299 }
300
301 // Bogus font I
302 if ( !font )
303 {
304 font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
305 underlined, facename,
306 info.xregistry, info.xencoding);
307 }
308
309 // Bogus font II
310 if ( !font )
311 {
312 font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
313 underlined, wxEmptyString,
314 info.xregistry, info.xencoding);
315 }
316 }
317
318 return font;
319}
320
321// ----------------------------------------------------------------------------
322// private functions
323// ----------------------------------------------------------------------------
324
325// returns TRUE if there are any fonts matching this font spec
326static bool wxTestFontSpec(const wxString& fontspec)
327{
97d3f0ee
VZ
328 // some X servers will fail to load this font because there are too many
329 // matches so we must test explicitly for this
330 if ( fontspec == _T("-*-*-*-*-*-*-*-*-*-*-*-*-*-*") )
331 {
332 return TRUE;
333 }
334
2e0e025e
RR
335 wxNativeFont test = (wxNativeFont) g_fontHash->Get( fontspec );
336 if (test)
337 {
338// printf( "speed up\n" );
339 return TRUE;
340 }
341
342 test = wxLoadFont(fontspec);
343 g_fontHash->Put( fontspec, (wxObject*) test );
344
7beba2fc
VZ
345 if ( test )
346 {
347 wxFreeFont(test);
348
349 return TRUE;
350 }
351 else
352 {
353 return FALSE;
354 }
355}
356
357static wxNativeFont wxLoadQueryFont(int pointSize,
358 int family,
359 int style,
360 int weight,
361 bool WXUNUSED(underlined),
362 const wxString& facename,
363 const wxString& xregistry,
364 const wxString& xencoding)
365{
366 wxString xfamily;
367 switch (family)
368 {
369 case wxDECORATIVE: xfamily = wxT("lucida"); break;
370 case wxROMAN: xfamily = wxT("times"); break;
371 case wxMODERN: xfamily = wxT("courier"); break;
372 case wxSWISS: xfamily = wxT("helvetica"); break;
373 case wxTELETYPE: xfamily = wxT("lucidatypewriter"); break;
374 case wxSCRIPT: xfamily = wxT("utopia"); break;
375 default: xfamily = wxT("*");
376 }
377
378 wxString fontSpec;
379 if (!facename.IsEmpty())
380 {
381 fontSpec.Printf(wxT("-*-%s-*-*-normal-*-*-*-*-*-*-*-*-*"),
382 facename.c_str());
383
384 if ( wxTestFontSpec(fontSpec) )
385 {
386 xfamily = facename;
387 }
388 //else: no such family, use default one instead
389 }
390
391 wxString xstyle;
392 switch (style)
393 {
f9dbf34f
VZ
394 case wxSLANT:
395 fontSpec.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
396 xfamily.c_str());
397 if ( wxTestFontSpec(fontSpec) )
398 {
399 xstyle = wxT("o");
400 break;
401 }
402 // fall through - try wxITALIC now
403
404 case wxITALIC:
405 fontSpec.Printf(wxT("-*-%s-*-i-*-*-*-*-*-*-*-*-*-*"),
406 xfamily.c_str());
407 if ( wxTestFontSpec(fontSpec) )
408 {
409 xstyle = wxT("i");
410 }
411 else if ( style == wxITALIC ) // and not wxSLANT
412 {
413 // try wxSLANT
414 fontSpec.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
415 xfamily.c_str());
416 if ( wxTestFontSpec(fontSpec) )
417 {
418 xstyle = wxT("o");
419 }
420 else
421 {
422 // no italic, no slant - leave default
423 xstyle = wxT("*");
424 }
425 }
426 break;
427
428 default:
429 wxFAIL_MSG(_T("unknown font style"));
430 // fall back to normal
431
432 case wxNORMAL:
433 xstyle = wxT("r");
434 break;
7beba2fc
VZ
435 }
436
437 wxString xweight;
438 switch (weight)
439 {
440 case wxBOLD:
441 {
442 fontSpec.Printf(wxT("-*-%s-bold-*-*-*-*-*-*-*-*-*-*-*"),
443 xfamily.c_str());
444 if ( wxTestFontSpec(fontSpec) )
445 {
446 xweight = wxT("bold");
447 break;
448 }
449 fontSpec.Printf(wxT("-*-%s-heavy-*-*-*-*-*-*-*-*-*-*-*"),
450 xfamily.c_str());
451 if ( wxTestFontSpec(fontSpec) )
452 {
453 xweight = wxT("heavy");
454 break;
455 }
456 fontSpec.Printf(wxT("-*-%s-extrabold-*-*-*-*-*-*-*-*-*-*-*"),
457 xfamily.c_str());
458 if ( wxTestFontSpec(fontSpec) )
459 {
460 xweight = wxT("extrabold");
461 break;
462 }
463 fontSpec.Printf(wxT("-*-%s-demibold-*-*-*-*-*-*-*-*-*-*-*"),
464 xfamily.c_str());
465 if ( wxTestFontSpec(fontSpec) )
466 {
467 xweight = wxT("demibold");
468 break;
469 }
470 fontSpec.Printf(wxT("-*-%s-black-*-*-*-*-*-*-*-*-*-*-*"),
471 xfamily.c_str());
472 if ( wxTestFontSpec(fontSpec) )
473 {
474 xweight = wxT("black");
475 break;
476 }
477 fontSpec.Printf(wxT("-*-%s-ultrablack-*-*-*-*-*-*-*-*-*-*-*"),
478 xfamily.c_str());
479 if ( wxTestFontSpec(fontSpec) )
480 {
481 xweight = wxT("ultrablack");
482 break;
483 }
484 }
485 break;
486 case wxLIGHT:
487 {
488 fontSpec.Printf(wxT("-*-%s-light-*-*-*-*-*-*-*-*-*-*-*"),
489 xfamily.c_str());
490 if ( wxTestFontSpec(fontSpec) )
491 {
492 xweight = wxT("light");
493 break;
494 }
495 fontSpec.Printf(wxT("-*-%s-thin-*-*-*-*-*-*-*-*-*-*-*"),
496 xfamily.c_str());
497 if ( wxTestFontSpec(fontSpec) )
498 {
499 xweight = wxT("thin");
500 break;
501 }
502 }
503 break;
504 case wxNORMAL:
505 {
506 fontSpec.Printf(wxT("-*-%s-medium-*-*-*-*-*-*-*-*-*-*-*"),
507 xfamily.c_str());
508 if ( wxTestFontSpec(fontSpec) )
509 {
510 xweight = wxT("medium");
511 break;
512 }
513 fontSpec.Printf(wxT("-*-%s-normal-*-*-*-*-*-*-*-*-*-*-*"),
514 xfamily.c_str());
515 if ( wxTestFontSpec(fontSpec) )
516 {
517 xweight = wxT("normal");
518 break;
519 }
520 fontSpec.Printf(wxT("-*-%s-regular-*-*-*-*-*-*-*-*-*-*-*"),
521 xfamily.c_str());
522 if ( wxTestFontSpec(fontSpec) )
523 {
524 xweight = wxT("regular");
525 break;
526 }
527 xweight = wxT("*");
528 }
529 break;
530 default: xweight = wxT("*"); break;
531 }
532
533 // construct the X font spec from our data
534 fontSpec.Printf(wxT("-*-%s-%s-%s-normal-*-*-%d-*-*-*-*-%s-%s"),
535 xfamily.c_str(), xweight.c_str(), xstyle.c_str(),
536 pointSize, xregistry.c_str(), xencoding.c_str());
537
538 return wxLoadFont(fontSpec);
539}
540
2e0e025e
RR
541// ----------------------------------------------------------------------------
542// wxFontModule
543// ----------------------------------------------------------------------------
544
545class wxFontModule : public wxModule
546{
547public:
548 bool OnInit();
549 void OnExit();
550
551private:
552 DECLARE_DYNAMIC_CLASS(wxFontModule)
553};
554
555IMPLEMENT_DYNAMIC_CLASS(wxFontModule, wxModule)
556
557bool wxFontModule::OnInit()
558{
559 g_fontHash = new wxHashTable( wxKEY_STRING );
560
561 return TRUE;
562}
563
564void wxFontModule::OnExit()
565{
566 delete g_fontHash;
567
568 g_fontHash = (wxHashTable *)NULL;
569}