]> git.saurik.com Git - wxWidgets.git/blob - src/unix/fontutil.cpp
OS/2 PM Fixeups for fonts, validators, and html
[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 (encoding == wxFONTENCODING_SYSTEM)
226 {
227 // This will always work so we don't test to save time
228 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
229 }
230 else
231 {
232 if ( !wxGetNativeFontEncoding(encoding, &info) ||
233 !wxTestFontEncoding(info) )
234 {
235 if ( !wxTheFontMapper->GetAltForEncoding(encoding, &info) )
236 {
237 // unspported encoding - replace it with the default
238 //
239 // NB: we can't just return 0 from here because wxGTK code doesn't
240 // check for it (i.e. it supposes that we'll always succeed),
241 // so it would provoke a crash
242 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
243 }
244 }
245 }
246
247 // OK, we have the correct xregistry/xencoding in info structure
248
249 wxNativeFont font = wxLoadQueryFont( pointSize, family, style, weight,
250 underlined, facename,
251 info.xregistry, info.xencoding );
252
253 if ( !font )
254 {
255 // search up and down by stepsize 10
256 int max_size = pointSize + 20 * (1 + (pointSize/180));
257 int min_size = pointSize - 20 * (1 + (pointSize/180));
258
259 int i;
260
261 // Search for smaller size (approx.)
262 for ( i = pointSize - 10; !font && i >= 10 && i >= min_size; i -= 10 )
263 {
264 font = wxLoadQueryFont(i, family, style, weight, underlined,
265 facename, info.xregistry, info.xencoding);
266 }
267
268 // Search for larger size (approx.)
269 for ( i = pointSize + 10; !font && i <= max_size; i += 10 )
270 {
271 font = wxLoadQueryFont(i, family, style, weight, underlined,
272 facename, info.xregistry, info.xencoding);
273 }
274
275 // Try default family
276 if ( !font && family != wxDEFAULT )
277 {
278 font = wxLoadQueryFont(pointSize, wxDEFAULT, style, weight,
279 underlined, facename,
280 info.xregistry, info.xencoding );
281 }
282
283 // Bogus font I
284 if ( !font )
285 {
286 font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
287 underlined, facename,
288 info.xregistry, info.xencoding);
289 }
290
291 // Bogus font II
292 if ( !font )
293 {
294 font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
295 underlined, wxEmptyString,
296 info.xregistry, info.xencoding);
297 }
298 }
299
300 return font;
301 }
302
303 // ----------------------------------------------------------------------------
304 // private functions
305 // ----------------------------------------------------------------------------
306
307 // returns TRUE if there are any fonts matching this font spec
308 static bool wxTestFontSpec(const wxString& fontspec)
309 {
310 wxNativeFont test = wxLoadFont(fontspec);
311 if ( test )
312 {
313 wxFreeFont(test);
314
315 return TRUE;
316 }
317 else
318 {
319 return FALSE;
320 }
321 }
322
323 static wxNativeFont wxLoadQueryFont(int pointSize,
324 int family,
325 int style,
326 int weight,
327 bool WXUNUSED(underlined),
328 const wxString& facename,
329 const wxString& xregistry,
330 const wxString& xencoding)
331 {
332 wxString xfamily;
333 switch (family)
334 {
335 case wxDECORATIVE: xfamily = wxT("lucida"); break;
336 case wxROMAN: xfamily = wxT("times"); break;
337 case wxMODERN: xfamily = wxT("courier"); break;
338 case wxSWISS: xfamily = wxT("helvetica"); break;
339 case wxTELETYPE: xfamily = wxT("lucidatypewriter"); break;
340 case wxSCRIPT: xfamily = wxT("utopia"); break;
341 default: xfamily = wxT("*");
342 }
343
344 wxString fontSpec;
345 if (!facename.IsEmpty())
346 {
347 fontSpec.Printf(wxT("-*-%s-*-*-normal-*-*-*-*-*-*-*-*-*"),
348 facename.c_str());
349
350 if ( wxTestFontSpec(fontSpec) )
351 {
352 xfamily = facename;
353 }
354 //else: no such family, use default one instead
355 }
356
357 wxString xstyle;
358 switch (style)
359 {
360 case wxITALIC: xstyle = wxT("i"); break;
361 case wxSLANT: xstyle = wxT("o"); break;
362 case wxNORMAL: xstyle = wxT("r"); break;
363 default: xstyle = wxT("*"); break;
364 }
365
366 wxString xweight;
367 switch (weight)
368 {
369 case wxBOLD:
370 {
371 fontSpec.Printf(wxT("-*-%s-bold-*-*-*-*-*-*-*-*-*-*-*"),
372 xfamily.c_str());
373 if ( wxTestFontSpec(fontSpec) )
374 {
375 xweight = wxT("bold");
376 break;
377 }
378 fontSpec.Printf(wxT("-*-%s-heavy-*-*-*-*-*-*-*-*-*-*-*"),
379 xfamily.c_str());
380 if ( wxTestFontSpec(fontSpec) )
381 {
382 xweight = wxT("heavy");
383 break;
384 }
385 fontSpec.Printf(wxT("-*-%s-extrabold-*-*-*-*-*-*-*-*-*-*-*"),
386 xfamily.c_str());
387 if ( wxTestFontSpec(fontSpec) )
388 {
389 xweight = wxT("extrabold");
390 break;
391 }
392 fontSpec.Printf(wxT("-*-%s-demibold-*-*-*-*-*-*-*-*-*-*-*"),
393 xfamily.c_str());
394 if ( wxTestFontSpec(fontSpec) )
395 {
396 xweight = wxT("demibold");
397 break;
398 }
399 fontSpec.Printf(wxT("-*-%s-black-*-*-*-*-*-*-*-*-*-*-*"),
400 xfamily.c_str());
401 if ( wxTestFontSpec(fontSpec) )
402 {
403 xweight = wxT("black");
404 break;
405 }
406 fontSpec.Printf(wxT("-*-%s-ultrablack-*-*-*-*-*-*-*-*-*-*-*"),
407 xfamily.c_str());
408 if ( wxTestFontSpec(fontSpec) )
409 {
410 xweight = wxT("ultrablack");
411 break;
412 }
413 }
414 break;
415 case wxLIGHT:
416 {
417 fontSpec.Printf(wxT("-*-%s-light-*-*-*-*-*-*-*-*-*-*-*"),
418 xfamily.c_str());
419 if ( wxTestFontSpec(fontSpec) )
420 {
421 xweight = wxT("light");
422 break;
423 }
424 fontSpec.Printf(wxT("-*-%s-thin-*-*-*-*-*-*-*-*-*-*-*"),
425 xfamily.c_str());
426 if ( wxTestFontSpec(fontSpec) )
427 {
428 xweight = wxT("thin");
429 break;
430 }
431 }
432 break;
433 case wxNORMAL:
434 {
435 fontSpec.Printf(wxT("-*-%s-medium-*-*-*-*-*-*-*-*-*-*-*"),
436 xfamily.c_str());
437 if ( wxTestFontSpec(fontSpec) )
438 {
439 xweight = wxT("medium");
440 break;
441 }
442 fontSpec.Printf(wxT("-*-%s-normal-*-*-*-*-*-*-*-*-*-*-*"),
443 xfamily.c_str());
444 if ( wxTestFontSpec(fontSpec) )
445 {
446 xweight = wxT("normal");
447 break;
448 }
449 fontSpec.Printf(wxT("-*-%s-regular-*-*-*-*-*-*-*-*-*-*-*"),
450 xfamily.c_str());
451 if ( wxTestFontSpec(fontSpec) )
452 {
453 xweight = wxT("regular");
454 break;
455 }
456 xweight = wxT("*");
457 }
458 break;
459 default: xweight = wxT("*"); break;
460 }
461
462 // construct the X font spec from our data
463 fontSpec.Printf(wxT("-*-%s-%s-%s-normal-*-*-%d-*-*-*-*-%s-%s"),
464 xfamily.c_str(), xweight.c_str(), xstyle.c_str(),
465 pointSize, xregistry.c_str(), xencoding.c_str());
466
467 return wxLoadFont(fontSpec);
468 }
469