]> git.saurik.com Git - wxWidgets.git/blob - src/unix/fontutil.cpp
774dd534bd46e8020038e41848d35e0d6572ea2e
[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 #include <X11/Xlib.h>
36
37 #include "wx/utils.h" // for wxGetDisplay()
38 #elif defined(__WXGTK__)
39 #include "gdk/gdk.h"
40 #endif
41
42 #include "wx/fontutil.h"
43 #include "wx/fontmap.h"
44 #include "wx/tokenzr.h"
45
46 // ----------------------------------------------------------------------------
47 // private functions
48 // ----------------------------------------------------------------------------
49
50 // define the functions to create and destroy native fonts for this toolkit
51 #ifdef __X__
52 static inline wxNativeFont wxLoadFont(const wxString& fontSpec)
53 {
54 return XLoadQueryFont((Display *)wxGetDisplay(), fontSpec);
55 }
56
57 static inline void wxFreeFont(wxNativeFont font)
58 {
59 XFreeFont((Display *)wxGetDisplay(), font);
60 }
61 #elif defined(__WXGTK__)
62 static inline wxNativeFont wxLoadFont(const wxString& fontSpec)
63 {
64 return gdk_font_load( wxConvertWX2MB(fontSpec) );
65 }
66
67 static inline void wxFreeFont(wxNativeFont font)
68 {
69 gdk_font_unref(font);
70 }
71 #else
72 #error "Unknown GUI toolkit"
73 #endif
74
75 static bool wxTestFontSpec(const wxString& fontspec);
76
77 static wxNativeFont wxLoadQueryFont(int pointSize,
78 int family,
79 int style,
80 int weight,
81 bool underlined,
82 const wxString& facename,
83 const wxString& xregistry,
84 const wxString& xencoding);
85
86 // ============================================================================
87 // implementation
88 // ============================================================================
89
90 // ----------------------------------------------------------------------------
91 // wxNativeEncodingInfo
92 // ----------------------------------------------------------------------------
93
94 // convert to/from the string representation: format is
95 // registry-encoding[-facename]
96 bool wxNativeEncodingInfo::FromString(const wxString& s)
97 {
98 wxStringTokenizer tokenizer(s, _T("-"));
99
100 xregistry = tokenizer.GetNextToken();
101 if ( !xregistry )
102 return FALSE;
103
104 xencoding = tokenizer.GetNextToken();
105 if ( !xencoding )
106 return FALSE;
107
108 // ok even if empty
109 facename = tokenizer.GetNextToken();
110
111 return TRUE;
112 }
113
114 wxString wxNativeEncodingInfo::ToString() const
115 {
116 wxString s;
117 s << xregistry << _T('-') << xencoding;
118 if ( !!facename )
119 {
120 s << _T('-') << facename;
121 }
122
123 return s;
124 }
125
126 // ----------------------------------------------------------------------------
127 // common functions
128 // ----------------------------------------------------------------------------
129
130 bool wxGetNativeFontEncoding(wxFontEncoding encoding,
131 wxNativeEncodingInfo *info)
132 {
133 wxCHECK_MSG( info, FALSE, _T("bad pointer in wxGetNativeFontEncoding") );
134
135 if ( encoding == wxFONTENCODING_DEFAULT )
136 {
137 encoding = wxFont::GetDefaultEncoding();
138 }
139
140 switch ( encoding )
141 {
142 case wxFONTENCODING_ISO8859_1:
143 case wxFONTENCODING_ISO8859_2:
144 case wxFONTENCODING_ISO8859_3:
145 case wxFONTENCODING_ISO8859_4:
146 case wxFONTENCODING_ISO8859_5:
147 case wxFONTENCODING_ISO8859_6:
148 case wxFONTENCODING_ISO8859_7:
149 case wxFONTENCODING_ISO8859_8:
150 case wxFONTENCODING_ISO8859_9:
151 case wxFONTENCODING_ISO8859_10:
152 case wxFONTENCODING_ISO8859_11:
153 case wxFONTENCODING_ISO8859_13:
154 case wxFONTENCODING_ISO8859_14:
155 case wxFONTENCODING_ISO8859_15:
156 {
157 int cp = encoding - wxFONTENCODING_ISO8859_1 + 1;
158 info->xregistry = wxT("iso8859");
159 info->xencoding.Printf(wxT("%d"), cp);
160 }
161 break;
162
163 case wxFONTENCODING_KOI8:
164 info->xregistry = wxT("koi8");
165
166 // we don't make distinction between koi8-r and koi8-u (so far)
167 info->xencoding = wxT("*");
168 break;
169
170 case wxFONTENCODING_CP1250:
171 case wxFONTENCODING_CP1251:
172 case wxFONTENCODING_CP1252:
173 case wxFONTENCODING_CP1253:
174 case wxFONTENCODING_CP1254:
175 case wxFONTENCODING_CP1255:
176 case wxFONTENCODING_CP1256:
177 case wxFONTENCODING_CP1257:
178 {
179 int cp = encoding - wxFONTENCODING_CP1250 + 1250;
180 info->xregistry = wxT("microsoft");
181 info->xencoding.Printf(wxT("cp%d"), cp);
182 }
183 break;
184
185 case wxFONTENCODING_SYSTEM:
186 info->xregistry =
187 info->xencoding = wxT('*');
188 break;
189
190 default:
191 // don't know how to translate this encoding into X fontspec
192 return FALSE;
193 }
194
195 return TRUE;
196 }
197
198 bool wxTestFontEncoding(const wxNativeEncodingInfo& info)
199 {
200 wxString fontspec;
201 fontspec.Printf(_T("-*-%s-*-*-*-*-*-*-*-*-*-*-%s-%s"),
202 !info.facename ? _T("*") : info.facename.c_str(),
203 info.xregistry.c_str(),
204 info.xencoding.c_str());
205
206 return wxTestFontSpec(fontspec);
207 }
208
209 // ----------------------------------------------------------------------------
210 // X-specific functions
211 // ----------------------------------------------------------------------------
212
213 wxNativeFont wxLoadQueryNearestFont(int pointSize,
214 int family,
215 int style,
216 int weight,
217 bool underlined,
218 const wxString &facename,
219 wxFontEncoding encoding)
220 {
221 // first determine the encoding - if the font doesn't exist at all in this
222 // encoding, it's useless to do all other approximations (i.e. size,
223 // family &c don't matter much)
224 wxNativeEncodingInfo info;
225 if ( !wxGetNativeFontEncoding(encoding, &info) ||
226 !wxTestFontEncoding(info) )
227 {
228 if ( !wxTheFontMapper->GetAltForEncoding(encoding, &info) )
229 {
230 // unspported encoding - replace it with the default
231 //
232 // NB: we can't just return 0 from here because wxGTK code doesn't
233 // check for it (i.e. it supposes that we'll always succeed),
234 // so it would provoke a crash
235 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
236 }
237 }
238 //else: we have the correct xregistry/xencoding in info structure
239
240 wxNativeFont font = wxLoadQueryFont( pointSize, family, style, weight,
241 underlined, facename,
242 info.xregistry, info.xencoding );
243
244 if ( !font )
245 {
246 // search up and down by stepsize 10
247 int max_size = pointSize + 20 * (1 + (pointSize/180));
248 int min_size = pointSize - 20 * (1 + (pointSize/180));
249
250 int i;
251
252 // Search for smaller size (approx.)
253 for ( i = pointSize - 10; !font && i >= 10 && i >= min_size; i -= 10 )
254 {
255 font = wxLoadQueryFont(i, family, style, weight, underlined,
256 facename, info.xregistry, info.xencoding);
257 }
258
259 // Search for larger size (approx.)
260 for ( i = pointSize + 10; !font && i <= max_size; i += 10 )
261 {
262 font = wxLoadQueryFont(i, family, style, weight, underlined,
263 facename, info.xregistry, info.xencoding);
264 }
265
266 // Try default family
267 if ( !font && family != wxDEFAULT )
268 {
269 font = wxLoadQueryFont(pointSize, wxDEFAULT, style, weight,
270 underlined, facename,
271 info.xregistry, info.xencoding );
272 }
273
274 // Bogus font I
275 if ( !font )
276 {
277 font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
278 underlined, facename,
279 info.xregistry, info.xencoding);
280 }
281
282 // Bogus font II
283 if ( !font )
284 {
285 font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
286 underlined, wxEmptyString,
287 info.xregistry, info.xencoding);
288 }
289 }
290
291 return font;
292 }
293
294 // ----------------------------------------------------------------------------
295 // private functions
296 // ----------------------------------------------------------------------------
297
298 // returns TRUE if there are any fonts matching this font spec
299 static bool wxTestFontSpec(const wxString& fontspec)
300 {
301 wxNativeFont test = wxLoadFont(fontspec);
302 if ( test )
303 {
304 wxFreeFont(test);
305
306 return TRUE;
307 }
308 else
309 {
310 return FALSE;
311 }
312 }
313
314 static wxNativeFont wxLoadQueryFont(int pointSize,
315 int family,
316 int style,
317 int weight,
318 bool WXUNUSED(underlined),
319 const wxString& facename,
320 const wxString& xregistry,
321 const wxString& xencoding)
322 {
323 wxString xfamily;
324 switch (family)
325 {
326 case wxDECORATIVE: xfamily = wxT("lucida"); break;
327 case wxROMAN: xfamily = wxT("times"); break;
328 case wxMODERN: xfamily = wxT("courier"); break;
329 case wxSWISS: xfamily = wxT("helvetica"); break;
330 case wxTELETYPE: xfamily = wxT("lucidatypewriter"); break;
331 case wxSCRIPT: xfamily = wxT("utopia"); break;
332 default: xfamily = wxT("*");
333 }
334
335 wxString fontSpec;
336 if (!facename.IsEmpty())
337 {
338 fontSpec.Printf(wxT("-*-%s-*-*-normal-*-*-*-*-*-*-*-*-*"),
339 facename.c_str());
340
341 if ( wxTestFontSpec(fontSpec) )
342 {
343 xfamily = facename;
344 }
345 //else: no such family, use default one instead
346 }
347
348 wxString xstyle;
349 switch (style)
350 {
351 case wxITALIC: xstyle = wxT("i"); break;
352 case wxSLANT: xstyle = wxT("o"); break;
353 case wxNORMAL: xstyle = wxT("r"); break;
354 default: xstyle = wxT("*"); break;
355 }
356
357 wxString xweight;
358 switch (weight)
359 {
360 case wxBOLD:
361 {
362 fontSpec.Printf(wxT("-*-%s-bold-*-*-*-*-*-*-*-*-*-*-*"),
363 xfamily.c_str());
364 if ( wxTestFontSpec(fontSpec) )
365 {
366 xweight = wxT("bold");
367 break;
368 }
369 fontSpec.Printf(wxT("-*-%s-heavy-*-*-*-*-*-*-*-*-*-*-*"),
370 xfamily.c_str());
371 if ( wxTestFontSpec(fontSpec) )
372 {
373 xweight = wxT("heavy");
374 break;
375 }
376 fontSpec.Printf(wxT("-*-%s-extrabold-*-*-*-*-*-*-*-*-*-*-*"),
377 xfamily.c_str());
378 if ( wxTestFontSpec(fontSpec) )
379 {
380 xweight = wxT("extrabold");
381 break;
382 }
383 fontSpec.Printf(wxT("-*-%s-demibold-*-*-*-*-*-*-*-*-*-*-*"),
384 xfamily.c_str());
385 if ( wxTestFontSpec(fontSpec) )
386 {
387 xweight = wxT("demibold");
388 break;
389 }
390 fontSpec.Printf(wxT("-*-%s-black-*-*-*-*-*-*-*-*-*-*-*"),
391 xfamily.c_str());
392 if ( wxTestFontSpec(fontSpec) )
393 {
394 xweight = wxT("black");
395 break;
396 }
397 fontSpec.Printf(wxT("-*-%s-ultrablack-*-*-*-*-*-*-*-*-*-*-*"),
398 xfamily.c_str());
399 if ( wxTestFontSpec(fontSpec) )
400 {
401 xweight = wxT("ultrablack");
402 break;
403 }
404 }
405 break;
406 case wxLIGHT:
407 {
408 fontSpec.Printf(wxT("-*-%s-light-*-*-*-*-*-*-*-*-*-*-*"),
409 xfamily.c_str());
410 if ( wxTestFontSpec(fontSpec) )
411 {
412 xweight = wxT("light");
413 break;
414 }
415 fontSpec.Printf(wxT("-*-%s-thin-*-*-*-*-*-*-*-*-*-*-*"),
416 xfamily.c_str());
417 if ( wxTestFontSpec(fontSpec) )
418 {
419 xweight = wxT("thin");
420 break;
421 }
422 }
423 break;
424 case wxNORMAL:
425 {
426 fontSpec.Printf(wxT("-*-%s-medium-*-*-*-*-*-*-*-*-*-*-*"),
427 xfamily.c_str());
428 if ( wxTestFontSpec(fontSpec) )
429 {
430 xweight = wxT("medium");
431 break;
432 }
433 fontSpec.Printf(wxT("-*-%s-normal-*-*-*-*-*-*-*-*-*-*-*"),
434 xfamily.c_str());
435 if ( wxTestFontSpec(fontSpec) )
436 {
437 xweight = wxT("normal");
438 break;
439 }
440 fontSpec.Printf(wxT("-*-%s-regular-*-*-*-*-*-*-*-*-*-*-*"),
441 xfamily.c_str());
442 if ( wxTestFontSpec(fontSpec) )
443 {
444 xweight = wxT("regular");
445 break;
446 }
447 xweight = wxT("*");
448 }
449 break;
450 default: xweight = wxT("*"); break;
451 }
452
453 // construct the X font spec from our data
454 fontSpec.Printf(wxT("-*-%s-%s-%s-normal-*-*-%d-*-*-*-*-%s-%s"),
455 xfamily.c_str(), xweight.c_str(), xstyle.c_str(),
456 pointSize, xregistry.c_str(), xencoding.c_str());
457
458 return wxLoadFont(fontSpec);
459 }
460