~brian-sidebotham/wxwidgets-cmake/wxpython-2.9.4

« back to all changes in this revision

Viewing changes to src/unix/fontutil.cpp

  • Committer: Brian Sidebotham
  • Date: 2013-08-03 14:30:08 UTC
  • Revision ID: brian.sidebotham@gmail.com-20130803143008-c7806tkych1tp6fc
Initial import into Bazaar

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/////////////////////////////////////////////////////////////////////////////
 
2
// Name:        src/unix/fontutil.cpp
 
3
// Purpose:     Font helper functions for wxX11, wxGTK, wxMotif
 
4
// Author:      Vadim Zeitlin
 
5
// Modified by:
 
6
// Created:     05.11.99
 
7
// RCS-ID:      $Id: fontutil.cpp 71382 2012-05-09 14:24:03Z VZ $
 
8
// Copyright:   (c) Vadim Zeitlin
 
9
// Licence:     wxWindows licence
 
10
/////////////////////////////////////////////////////////////////////////////
 
11
 
 
12
// ============================================================================
 
13
// declarations
 
14
// ============================================================================
 
15
 
 
16
// ----------------------------------------------------------------------------
 
17
// headers
 
18
// ----------------------------------------------------------------------------
 
19
 
 
20
// For compilers that support precompilation, includes "wx.h".
 
21
#include "wx/wxprec.h"
 
22
 
 
23
#ifdef __BORLANDC__
 
24
    #pragma hdrstop
 
25
#endif
 
26
 
 
27
#include "wx/fontutil.h"
 
28
 
 
29
#ifndef WX_PRECOMP
 
30
    #include "wx/app.h"
 
31
    #include "wx/font.h" // wxFont enums
 
32
    #include "wx/encinfo.h"
 
33
    #include "wx/hash.h"
 
34
    #include "wx/utils.h"       // for wxGetDisplay()
 
35
    #include "wx/module.h"
 
36
#endif // PCH
 
37
 
 
38
#include "wx/fontmap.h"
 
39
#include "wx/tokenzr.h"
 
40
#include "wx/fontenum.h"
 
41
 
 
42
#if wxUSE_PANGO
 
43
 
 
44
#include "pango/pango.h"
 
45
 
 
46
#ifdef __WXGTK20__
 
47
    #include "wx/gtk/private.h"
 
48
    extern GtkWidget *wxGetRootWindow();
 
49
 
 
50
    #define wxPANGO_CONV wxGTK_CONV_SYS
 
51
    #define wxPANGO_CONV_BACK wxGTK_CONV_BACK_SYS
 
52
#else
 
53
    #include "wx/x11/private.h"
 
54
    #include "wx/gtk/private/string.h"
 
55
 
 
56
    #define wxPANGO_CONV(s) s.utf8_str()
 
57
    #define wxPANGO_CONV_BACK(s) wxString::FromUTF8Unchecked(s)
 
58
#endif
 
59
 
 
60
// ----------------------------------------------------------------------------
 
61
// wxNativeFontInfo
 
62
// ----------------------------------------------------------------------------
 
63
 
 
64
void wxNativeFontInfo::Init()
 
65
{
 
66
    description = NULL;
 
67
}
 
68
 
 
69
void wxNativeFontInfo::Init(const wxNativeFontInfo& info)
 
70
{
 
71
    if (info.description)
 
72
        description = pango_font_description_copy(info.description);
 
73
    else
 
74
        description = NULL;
 
75
}
 
76
 
 
77
void wxNativeFontInfo::Free()
 
78
{
 
79
    if (description)
 
80
        pango_font_description_free(description);
 
81
}
 
82
 
 
83
int wxNativeFontInfo::GetPointSize() const
 
84
{
 
85
    return pango_font_description_get_size( description ) / PANGO_SCALE;
 
86
}
 
87
 
 
88
wxFontStyle wxNativeFontInfo::GetStyle() const
 
89
{
 
90
    wxFontStyle m_style = wxFONTSTYLE_NORMAL;
 
91
 
 
92
    switch (pango_font_description_get_style( description ))
 
93
    {
 
94
        case PANGO_STYLE_NORMAL:
 
95
            m_style = wxFONTSTYLE_NORMAL;
 
96
            break;
 
97
        case PANGO_STYLE_ITALIC:
 
98
            m_style = wxFONTSTYLE_ITALIC;
 
99
            break;
 
100
        case PANGO_STYLE_OBLIQUE:
 
101
            m_style = wxFONTSTYLE_SLANT;
 
102
            break;
 
103
    }
 
104
 
 
105
    return m_style;
 
106
}
 
107
 
 
108
wxFontWeight wxNativeFontInfo::GetWeight() const
 
109
{
 
110
    // We seem to currently initialize only by string.
 
111
    // In that case PANGO_FONT_MASK_WEIGHT is always set.
 
112
    // if (!(pango_font_description_get_set_fields(description) & PANGO_FONT_MASK_WEIGHT))
 
113
    //    return wxFONTWEIGHT_NORMAL;
 
114
 
 
115
    PangoWeight pango_weight = pango_font_description_get_weight( description );
 
116
 
 
117
    // Until the API can be changed the following ranges of weight values are used:
 
118
    // wxFONTWEIGHT_LIGHT:  100 .. 349 - range of 250
 
119
    // wxFONTWEIGHT_NORMAL: 350 .. 599 - range of 250
 
120
    // wxFONTWEIGHT_BOLD:   600 .. 900 - range of 301 (600 is "semibold" already)
 
121
 
 
122
    if (pango_weight >= 600)
 
123
        return wxFONTWEIGHT_BOLD;
 
124
 
 
125
    if (pango_weight < 350)
 
126
        return wxFONTWEIGHT_LIGHT;
 
127
 
 
128
    return wxFONTWEIGHT_NORMAL;
 
129
}
 
130
 
 
131
bool wxNativeFontInfo::GetUnderlined() const
 
132
{
 
133
    return false;
 
134
}
 
135
 
 
136
bool wxNativeFontInfo::GetStrikethrough() const
 
137
{
 
138
    return false;
 
139
}
 
140
 
 
141
wxString wxNativeFontInfo::GetFaceName() const
 
142
{
 
143
    // the Pango "family" is the wx "face name"
 
144
    return wxPANGO_CONV_BACK(pango_font_description_get_family(description));
 
145
}
 
146
 
 
147
wxFontFamily wxNativeFontInfo::GetFamily() const
 
148
{
 
149
    wxFontFamily ret = wxFONTFAMILY_UNKNOWN;
 
150
 
 
151
    const char *family_name = pango_font_description_get_family( description );
 
152
 
 
153
    // note: not passing -1 as the 2nd parameter to g_ascii_strdown to work
 
154
    // around a bug in the 64-bit glib shipped with solaris 10, -1 causes it
 
155
    // to try to allocate 2^32 bytes.
 
156
    if ( !family_name )
 
157
        return ret;
 
158
    wxGtkString family_text(g_ascii_strdown(family_name, strlen(family_name)));
 
159
 
 
160
    // Check for some common fonts, to salvage what we can from the current
 
161
    // win32 centric wxFont API:
 
162
    if (wxStrnicmp( family_text, "monospace", 9 ) == 0)
 
163
        ret = wxFONTFAMILY_TELETYPE;    // begins with "Monospace"
 
164
    else if (wxStrnicmp( family_text, "courier", 7 ) == 0)
 
165
        ret = wxFONTFAMILY_TELETYPE;    // begins with "Courier"
 
166
#if defined(__WXGTK20__) || defined(HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE)
 
167
    else
 
168
    {
 
169
        PangoFontFamily **families;
 
170
        PangoFontFamily  *family = NULL;
 
171
        int n_families;
 
172
        pango_context_list_families(
 
173
#ifdef __WXGTK20__
 
174
                gtk_widget_get_pango_context( wxGetRootWindow() ),
 
175
#else
 
176
                wxTheApp->GetPangoContext(),
 
177
#endif
 
178
                &families, &n_families);
 
179
 
 
180
        for (int i = 0; i < n_families; ++i)
 
181
        {
 
182
            if (g_ascii_strcasecmp(pango_font_family_get_name( families[i] ),
 
183
                                   pango_font_description_get_family( description )) == 0 )
 
184
            {
 
185
                family = families[i];
 
186
                break;
 
187
            }
 
188
        }
 
189
 
 
190
        g_free(families);
 
191
 
 
192
        // Some gtk+ systems might query for a non-existing font from
 
193
        // wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) on initialization,
 
194
        // don't assert until wxSystemSettings::GetFont is checked for this - MR
 
195
        // wxASSERT_MSG( family, "No appropriate PangoFontFamily found for ::description" );
 
196
 
 
197
        if (family != NULL && pango_font_family_is_monospace( family ))
 
198
            ret = wxFONTFAMILY_TELETYPE; // is deemed a monospace font by pango
 
199
    }
 
200
#endif // GTK+ 2 || HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE
 
201
 
 
202
    if (ret == wxFONTFAMILY_UNKNOWN)
 
203
    {
 
204
        if (strstr( family_text, "sans" ) != NULL || strstr( family_text, "Sans" ) != NULL)
 
205
            // checked before serif, so that "* Sans Serif" fonts are detected correctly
 
206
            ret = wxFONTFAMILY_SWISS;       // contains "Sans"
 
207
        else if (strstr( family_text, "serif" ) != NULL || strstr( family_text, "Serif" ) != NULL)
 
208
            ret = wxFONTFAMILY_ROMAN;       // contains "Serif"
 
209
        else if (wxStrnicmp( family_text, "times", 5 ) == 0)
 
210
            ret = wxFONTFAMILY_ROMAN;       // begins with "Times"
 
211
        else if (wxStrnicmp( family_text, "old", 3 ) == 0)
 
212
            ret = wxFONTFAMILY_DECORATIVE;  // begins with "Old" - "Old English", "Old Town"
 
213
    }
 
214
 
 
215
    return ret;
 
216
}
 
217
 
 
218
wxFontEncoding wxNativeFontInfo::GetEncoding() const
 
219
{
 
220
    return wxFONTENCODING_SYSTEM;
 
221
}
 
222
 
 
223
void wxNativeFontInfo::SetPointSize(int pointsize)
 
224
{
 
225
    pango_font_description_set_size( description, pointsize * PANGO_SCALE );
 
226
}
 
227
 
 
228
void wxNativeFontInfo::SetStyle(wxFontStyle style)
 
229
{
 
230
    switch (style)
 
231
    {
 
232
        case wxFONTSTYLE_ITALIC:
 
233
            pango_font_description_set_style( description, PANGO_STYLE_ITALIC );
 
234
            break;
 
235
        case wxFONTSTYLE_SLANT:
 
236
            pango_font_description_set_style( description, PANGO_STYLE_OBLIQUE );
 
237
            break;
 
238
        default:
 
239
            wxFAIL_MSG( "unknown font style" );
 
240
            // fall through
 
241
        case wxFONTSTYLE_NORMAL:
 
242
            pango_font_description_set_style( description, PANGO_STYLE_NORMAL );
 
243
            break;
 
244
    }
 
245
}
 
246
 
 
247
void wxNativeFontInfo::SetWeight(wxFontWeight weight)
 
248
{
 
249
    switch (weight)
 
250
    {
 
251
        case wxFONTWEIGHT_BOLD:
 
252
            pango_font_description_set_weight(description, PANGO_WEIGHT_BOLD);
 
253
            break;
 
254
        case wxFONTWEIGHT_LIGHT:
 
255
            pango_font_description_set_weight(description, PANGO_WEIGHT_LIGHT);
 
256
            break;
 
257
        default:
 
258
            wxFAIL_MSG( "unknown font weight" );
 
259
            // fall through
 
260
        case wxFONTWEIGHT_NORMAL:
 
261
            pango_font_description_set_weight(description, PANGO_WEIGHT_NORMAL);
 
262
    }
 
263
}
 
264
 
 
265
void wxNativeFontInfo::SetUnderlined(bool WXUNUSED(underlined))
 
266
{
 
267
    // wxWindowDCImpl::DoDrawText will take care of rendering font with
 
268
    // the underline attribute!
 
269
    wxFAIL_MSG( "not implemented" );
 
270
}
 
271
 
 
272
void wxNativeFontInfo::SetStrikethrough(bool WXUNUSED(strikethrough))
 
273
{
 
274
    wxFAIL_MSG( "not implemented" );
 
275
}
 
276
 
 
277
bool wxNativeFontInfo::SetFaceName(const wxString& facename)
 
278
{
 
279
    pango_font_description_set_family(description, wxPANGO_CONV(facename));
 
280
 
 
281
    // we return true because Pango doesn't tell us if the call failed or not;
 
282
    // instead on wxGTK wxFont::SetFaceName() will call wxFontBase::SetFaceName()
 
283
    // which does the check
 
284
    return true;
 
285
}
 
286
 
 
287
void wxNativeFontInfo::SetFamily(wxFontFamily family)
 
288
{
 
289
    wxArrayString facename;
 
290
 
 
291
    // the list of fonts associated with a family was partially
 
292
    // taken from http://www.codestyle.org/css/font-family
 
293
 
 
294
    switch ( family )
 
295
    {
 
296
        case wxFONTFAMILY_SCRIPT:
 
297
            // corresponds to the cursive font family in the page linked above
 
298
            facename.Add(wxS("URW Chancery L"));
 
299
            facename.Add(wxS("Comic Sans MS"));
 
300
            break;
 
301
 
 
302
        case wxFONTFAMILY_DECORATIVE:
 
303
            // corresponds to the fantasy font family in the page linked above
 
304
            facename.Add(wxS("Impact"));
 
305
            break;
 
306
 
 
307
        case wxFONTFAMILY_ROMAN:
 
308
            // corresponds to the serif font family in the page linked above
 
309
            facename.Add(wxS("Serif"));
 
310
            facename.Add(wxS("DejaVu Serif"));
 
311
            facename.Add(wxS("DejaVu LGC Serif"));
 
312
            facename.Add(wxS("Bitstream Vera Serif"));
 
313
            facename.Add(wxS("Liberation Serif"));
 
314
            facename.Add(wxS("FreeSerif"));
 
315
            facename.Add(wxS("Luxi Serif"));
 
316
            facename.Add(wxS("Times New Roman"));
 
317
            facename.Add(wxS("Century Schoolbook L"));
 
318
            facename.Add(wxS("URW Bookman L"));
 
319
            facename.Add(wxS("URW Palladio L"));
 
320
            facename.Add(wxS("Times"));
 
321
            break;
 
322
 
 
323
        case wxFONTFAMILY_TELETYPE:
 
324
        case wxFONTFAMILY_MODERN:
 
325
            // corresponds to the monospace font family in the page linked above
 
326
            facename.Add(wxS("Monospace"));
 
327
            facename.Add(wxS("DejaVu Sans Mono"));
 
328
            facename.Add(wxS("DejaVu LGC Sans Mono"));
 
329
            facename.Add(wxS("Bitstream Vera Sans Mono"));
 
330
            facename.Add(wxS("Liberation Mono"));
 
331
            facename.Add(wxS("FreeMono"));
 
332
            facename.Add(wxS("Luxi Mono"));
 
333
            facename.Add(wxS("Courier New"));
 
334
            facename.Add(wxS("Lucida Sans Typewriter"));
 
335
            facename.Add(wxS("Nimbus Mono L"));
 
336
            facename.Add(wxS("Andale Mono"));
 
337
            facename.Add(wxS("Courier"));
 
338
            break;
 
339
 
 
340
        case wxFONTFAMILY_SWISS:
 
341
        case wxFONTFAMILY_DEFAULT:
 
342
        default:
 
343
            // corresponds to the sans-serif font family in the page linked above
 
344
            facename.Add(wxS("Sans"));
 
345
            facename.Add(wxS("DejaVu Sans"));
 
346
            facename.Add(wxS("DejaVu LGC Sans"));
 
347
            facename.Add(wxS("Bitstream Vera Sans"));
 
348
            facename.Add(wxS("Liberation Sans"));
 
349
            facename.Add(wxS("FreeSans"));
 
350
            facename.Add(wxS("Luxi Sans"));
 
351
            facename.Add(wxS("Arial"));
 
352
            facename.Add(wxS("Lucida Sans"));
 
353
            facename.Add(wxS("Nimbus Sans L"));
 
354
            facename.Add(wxS("URW Gothic L"));
 
355
            break;
 
356
    }
 
357
 
 
358
    SetFaceName(facename);
 
359
}
 
360
 
 
361
void wxNativeFontInfo::SetEncoding(wxFontEncoding WXUNUSED(encoding))
 
362
{
 
363
    wxFAIL_MSG( "not implemented: Pango encoding is always UTF8" );
 
364
}
 
365
 
 
366
bool wxNativeFontInfo::FromString(const wxString& s)
 
367
{
 
368
    if (description)
 
369
        pango_font_description_free( description );
 
370
 
 
371
    // there is a bug in at least pango <= 1.13 which makes it (or its backends)
 
372
    // segfault for very big point sizes and for negative point sizes.
 
373
    // To workaround that bug for pango <= 1.13
 
374
    // (see http://bugzilla.gnome.org/show_bug.cgi?id=340229)
 
375
    // we do the check on the size here using same (arbitrary) limits used by
 
376
    // pango > 1.13. Note that the segfault could happen also for pointsize
 
377
    // smaller than this limit !!
 
378
    wxString str(s);
 
379
    const size_t pos = str.find_last_of(wxS(" "));
 
380
    double size;
 
381
    if ( pos != wxString::npos && wxString(str, pos + 1).ToDouble(&size) )
 
382
    {
 
383
        wxString sizeStr;
 
384
        if ( size < 1 )
 
385
            sizeStr = wxS("1");
 
386
        else if ( size >= 1E6 )
 
387
            sizeStr = wxS("1E6");
 
388
 
 
389
        if ( !sizeStr.empty() )
 
390
        {
 
391
            // replace the old size with the adjusted one
 
392
            str = wxString(s, 0, pos) + sizeStr;
 
393
        }
 
394
    }
 
395
 
 
396
    description = pango_font_description_from_string(wxPANGO_CONV(str));
 
397
 
 
398
#if wxUSE_FONTENUM
 
399
    // ensure a valid facename is selected
 
400
    if (!wxFontEnumerator::IsValidFacename(GetFaceName()))
 
401
        SetFaceName(wxNORMAL_FONT->GetFaceName());
 
402
#endif // wxUSE_FONTENUM
 
403
 
 
404
    return true;
 
405
}
 
406
 
 
407
wxString wxNativeFontInfo::ToString() const
 
408
{
 
409
    wxGtkString str(pango_font_description_to_string( description ));
 
410
 
 
411
    return wxPANGO_CONV_BACK(str);
 
412
}
 
413
 
 
414
bool wxNativeFontInfo::FromUserString(const wxString& s)
 
415
{
 
416
    return FromString( s );
 
417
}
 
418
 
 
419
wxString wxNativeFontInfo::ToUserString() const
 
420
{
 
421
    return ToString();
 
422
}
 
423
 
 
424
#else // GTK+ 1.x
 
425
 
 
426
#ifdef __X__
 
427
    #ifdef __VMS__
 
428
        #pragma message disable nosimpint
 
429
    #endif
 
430
 
 
431
    #include <X11/Xlib.h>
 
432
 
 
433
    #ifdef __VMS__
 
434
        #pragma message enable nosimpint
 
435
    #endif
 
436
 
 
437
#elif defined(__WXGTK__)
 
438
    // we have to declare struct tm to avoid problems with first forward
 
439
    // declaring it in C code (glib.h included from gdk.h does it) and then
 
440
    // defining it when time.h is included from the headers below - this is
 
441
    // known not to work at least with Sun CC 6.01
 
442
    #include <time.h>
 
443
 
 
444
    #include <gdk/gdk.h>
 
445
#endif
 
446
 
 
447
 
 
448
// ----------------------------------------------------------------------------
 
449
// private data
 
450
// ----------------------------------------------------------------------------
 
451
 
 
452
static wxHashTable *g_fontHash = NULL;
 
453
 
 
454
// ----------------------------------------------------------------------------
 
455
// private functions
 
456
// ----------------------------------------------------------------------------
 
457
 
 
458
// define the functions to create and destroy native fonts for this toolkit
 
459
#ifdef __X__
 
460
    wxNativeFont wxLoadFont(const wxString& fontSpec)
 
461
    {
 
462
        return XLoadQueryFont((Display *)wxGetDisplay(), fontSpec);
 
463
    }
 
464
 
 
465
    inline void wxFreeFont(wxNativeFont font)
 
466
    {
 
467
        XFreeFont((Display *)wxGetDisplay(), (XFontStruct *)font);
 
468
    }
 
469
#elif defined(__WXGTK__)
 
470
    wxNativeFont wxLoadFont(const wxString& fontSpec)
 
471
    {
 
472
        // VZ: we should use gdk_fontset_load() instead of gdk_font_load()
 
473
        //     here to be able to display Japanese fonts correctly (at least
 
474
        //     this is what people report) but unfortunately doing it results
 
475
        //     in tons of warnings when using GTK with "normal" European
 
476
        //     languages and so we can't always do it and I don't know enough
 
477
        //     to determine when should this be done... (FIXME)
 
478
        return gdk_font_load( wxConvertWX2MB(fontSpec) );
 
479
    }
 
480
 
 
481
    inline void wxFreeFont(wxNativeFont font)
 
482
    {
 
483
        gdk_font_unref(font);
 
484
    }
 
485
#else
 
486
    #error "Unknown GUI toolkit"
 
487
#endif
 
488
 
 
489
static bool wxTestFontSpec(const wxString& fontspec);
 
490
 
 
491
static wxNativeFont wxLoadQueryFont(int pointSize,
 
492
                                    int family,
 
493
                                    int style,
 
494
                                    int weight,
 
495
                                    bool underlined,
 
496
                                    const wxString& facename,
 
497
                                    const wxString& xregistry,
 
498
                                    const wxString& xencoding,
 
499
                                    wxString* xFontName);
 
500
 
 
501
// ============================================================================
 
502
// implementation
 
503
// ============================================================================
 
504
 
 
505
// ----------------------------------------------------------------------------
 
506
// wxNativeEncodingInfo
 
507
// ----------------------------------------------------------------------------
 
508
 
 
509
// convert to/from the string representation: format is
 
510
//      encodingid;registry;encoding[;facename]
 
511
bool wxNativeEncodingInfo::FromString(const wxString& s)
 
512
{
 
513
    // use ";", not "-" because it may be part of encoding name
 
514
    wxStringTokenizer tokenizer(s, wxT(";"));
 
515
 
 
516
    wxString encid = tokenizer.GetNextToken();
 
517
    long enc;
 
518
    if ( !encid.ToLong(&enc) )
 
519
        return false;
 
520
    encoding = (wxFontEncoding)enc;
 
521
 
 
522
    xregistry = tokenizer.GetNextToken();
 
523
    if ( !xregistry )
 
524
        return false;
 
525
 
 
526
    xencoding = tokenizer.GetNextToken();
 
527
    if ( !xencoding )
 
528
        return false;
 
529
 
 
530
    // ok even if empty
 
531
    facename = tokenizer.GetNextToken();
 
532
 
 
533
    return true;
 
534
}
 
535
 
 
536
wxString wxNativeEncodingInfo::ToString() const
 
537
{
 
538
    wxString s;
 
539
    s << (long)encoding << wxT(';') << xregistry << wxT(';') << xencoding;
 
540
    if ( !facename.empty() )
 
541
    {
 
542
        s << wxT(';') << facename;
 
543
    }
 
544
 
 
545
    return s;
 
546
}
 
547
 
 
548
// ----------------------------------------------------------------------------
 
549
// wxNativeFontInfo
 
550
// ----------------------------------------------------------------------------
 
551
 
 
552
void wxNativeFontInfo::Init()
 
553
{
 
554
    m_isDefault = true;
 
555
}
 
556
 
 
557
bool wxNativeFontInfo::FromString(const wxString& s)
 
558
{
 
559
    wxStringTokenizer tokenizer(s, wxT(";"));
 
560
 
 
561
    // check the version
 
562
    wxString token = tokenizer.GetNextToken();
 
563
    if ( token != wxT('0') )
 
564
        return false;
 
565
 
 
566
    xFontName = tokenizer.GetNextToken();
 
567
 
 
568
    // this should be the end
 
569
    if ( tokenizer.HasMoreTokens() )
 
570
        return false;
 
571
 
 
572
    return FromXFontName(xFontName);
 
573
}
 
574
 
 
575
wxString wxNativeFontInfo::ToString() const
 
576
{
 
577
    // 0 is the version
 
578
    return wxString::Format(wxT("%d;%s"), 0, GetXFontName().c_str());
 
579
}
 
580
 
 
581
bool wxNativeFontInfo::FromUserString(const wxString& s)
 
582
{
 
583
    return FromXFontName(s);
 
584
}
 
585
 
 
586
wxString wxNativeFontInfo::ToUserString() const
 
587
{
 
588
    return GetXFontName();
 
589
}
 
590
 
 
591
bool wxNativeFontInfo::HasElements() const
 
592
{
 
593
    // we suppose that the foundry is never empty, so if it is it means that we
 
594
    // had never parsed the XLFD
 
595
    return !fontElements[0].empty();
 
596
}
 
597
 
 
598
wxString wxNativeFontInfo::GetXFontComponent(wxXLFDField field) const
 
599
{
 
600
    wxCHECK_MSG( field < wxXLFD_MAX, wxEmptyString, wxT("invalid XLFD field") );
 
601
 
 
602
    if ( !HasElements() )
 
603
    {
 
604
        if ( !const_cast<wxNativeFontInfo *>(this)->FromXFontName(xFontName) )
 
605
            return wxEmptyString;
 
606
    }
 
607
 
 
608
    return fontElements[field];
 
609
}
 
610
 
 
611
bool wxNativeFontInfo::FromXFontName(const wxString& fontname)
 
612
{
 
613
    // TODO: we should be able to handle the font aliases here, but how?
 
614
    wxStringTokenizer tokenizer(fontname, wxT("-"));
 
615
 
 
616
    // skip the leading, usually empty field (font name registry)
 
617
    if ( !tokenizer.HasMoreTokens() )
 
618
        return false;
 
619
 
 
620
    (void)tokenizer.GetNextToken();
 
621
 
 
622
    for ( size_t n = 0; n < WXSIZEOF(fontElements); n++ )
 
623
    {
 
624
        if ( !tokenizer.HasMoreTokens() )
 
625
        {
 
626
            // not enough elements in the XLFD - or maybe an alias
 
627
            return false;
 
628
        }
 
629
 
 
630
        wxString field = tokenizer.GetNextToken();
 
631
        if ( !field.empty() && field != wxT('*') )
 
632
        {
 
633
            // we're really initialized now
 
634
            m_isDefault = false;
 
635
        }
 
636
 
 
637
        fontElements[n] = field;
 
638
    }
 
639
 
 
640
    // this should be all
 
641
    if ( tokenizer.HasMoreTokens() )
 
642
        return false;
 
643
 
 
644
    return true;
 
645
}
 
646
 
 
647
wxString wxNativeFontInfo::GetXFontName() const
 
648
{
 
649
    if ( xFontName.empty() )
 
650
    {
 
651
        for ( size_t n = 0; n < WXSIZEOF(fontElements); n++ )
 
652
        {
 
653
            // replace the non specified elements with '*' except for the
 
654
            // additional style which is usually just omitted
 
655
            wxString elt = fontElements[n];
 
656
            if ( elt.empty() && n != wxXLFD_ADDSTYLE )
 
657
            {
 
658
                elt = wxT('*');
 
659
            }
 
660
 
 
661
            const_cast<wxNativeFontInfo *>(this)->xFontName << wxT('-') << elt;
 
662
        }
 
663
    }
 
664
 
 
665
    return xFontName;
 
666
}
 
667
 
 
668
void
 
669
wxNativeFontInfo::SetXFontComponent(wxXLFDField field, const wxString& value)
 
670
{
 
671
    wxCHECK_RET( field < wxXLFD_MAX, wxT("invalid XLFD field") );
 
672
 
 
673
    // this class should be initialized with a valid font spec first and only
 
674
    // then the fields may be modified!
 
675
    wxASSERT_MSG( !IsDefault(), wxT("can't modify an uninitialized XLFD") );
 
676
 
 
677
    if ( !HasElements() )
 
678
    {
 
679
        if ( !const_cast<wxNativeFontInfo *>(this)->FromXFontName(xFontName) )
 
680
        {
 
681
            wxFAIL_MSG( wxT("can't set font element for invalid XLFD") );
 
682
 
 
683
            return;
 
684
        }
 
685
    }
 
686
 
 
687
    fontElements[field] = value;
 
688
 
 
689
    // invalidate the XFLD, it doesn't correspond to the font elements any more
 
690
    xFontName.clear();
 
691
}
 
692
 
 
693
void wxNativeFontInfo::SetXFontName(const wxString& xFontName_)
 
694
{
 
695
    // invalidate the font elements, GetXFontComponent() will reparse the XLFD
 
696
    fontElements[0].clear();
 
697
 
 
698
    xFontName = xFontName_;
 
699
 
 
700
    m_isDefault = false;
 
701
}
 
702
 
 
703
int wxNativeFontInfo::GetPointSize() const
 
704
{
 
705
    const wxString s = GetXFontComponent(wxXLFD_POINTSIZE);
 
706
 
 
707
    // return -1 to indicate that the size is unknown
 
708
    long l;
 
709
    return s.ToLong(&l) ? l : -1;
 
710
}
 
711
 
 
712
wxFontStyle wxNativeFontInfo::GetStyle() const
 
713
{
 
714
    const wxString s = GetXFontComponent(wxXLFD_SLANT);
 
715
 
 
716
    if ( s.length() != 1 )
 
717
    {
 
718
        // it is really unknown but we don't have any way to return it from
 
719
        // here
 
720
        return wxFONTSTYLE_NORMAL;
 
721
    }
 
722
 
 
723
    switch ( s[0].GetValue() )
 
724
    {
 
725
        default:
 
726
            // again, unknown but consider normal by default
 
727
 
 
728
        case wxT('r'):
 
729
            return wxFONTSTYLE_NORMAL;
 
730
 
 
731
        case wxT('i'):
 
732
            return wxFONTSTYLE_ITALIC;
 
733
 
 
734
        case wxT('o'):
 
735
            return wxFONTSTYLE_SLANT;
 
736
    }
 
737
}
 
738
 
 
739
wxFontWeight wxNativeFontInfo::GetWeight() const
 
740
{
 
741
    const wxString s = GetXFontComponent(wxXLFD_WEIGHT).MakeLower();
 
742
    if ( s.find(wxT("bold")) != wxString::npos || s == wxT("black") )
 
743
        return wxFONTWEIGHT_BOLD;
 
744
    else if ( s == wxT("light") )
 
745
        return wxFONTWEIGHT_LIGHT;
 
746
 
 
747
    return wxFONTWEIGHT_NORMAL;
 
748
}
 
749
 
 
750
bool wxNativeFontInfo::GetUnderlined() const
 
751
{
 
752
    // X fonts are never underlined
 
753
    return false;
 
754
}
 
755
 
 
756
wxString wxNativeFontInfo::GetFaceName() const
 
757
{
 
758
    // wxWidgets facename probably more accurately corresponds to X family
 
759
    return GetXFontComponent(wxXLFD_FAMILY);
 
760
}
 
761
 
 
762
wxFontFamily wxNativeFontInfo::GetFamily() const
 
763
{
 
764
    // and wxWidgets family -- to X foundry, but we have to translate it to
 
765
    // wxFontFamily somehow...
 
766
    wxFAIL_MSG(wxT("not implemented")); // GetXFontComponent(wxXLFD_FOUNDRY);
 
767
 
 
768
    return wxFONTFAMILY_DEFAULT;
 
769
}
 
770
 
 
771
wxFontEncoding wxNativeFontInfo::GetEncoding() const
 
772
{
 
773
    // we already have the code for this but need to refactor it first
 
774
    wxFAIL_MSG( wxT("not implemented") );
 
775
 
 
776
    return wxFONTENCODING_MAX;
 
777
}
 
778
 
 
779
void wxNativeFontInfo::SetPointSize(int pointsize)
 
780
{
 
781
    SetXFontComponent(wxXLFD_POINTSIZE, wxString::Format(wxT("%d"), pointsize));
 
782
}
 
783
 
 
784
void wxNativeFontInfo::SetStyle(wxFontStyle style)
 
785
{
 
786
    wxString s;
 
787
    switch ( style )
 
788
    {
 
789
        case wxFONTSTYLE_ITALIC:
 
790
            s = wxT('i');
 
791
            break;
 
792
 
 
793
        case wxFONTSTYLE_SLANT:
 
794
            s = wxT('o');
 
795
            break;
 
796
 
 
797
        case wxFONTSTYLE_NORMAL:
 
798
            s = wxT('r');
 
799
 
 
800
        default:
 
801
            wxFAIL_MSG( wxT("unknown wxFontStyle in wxNativeFontInfo::SetStyle") );
 
802
            return;
 
803
    }
 
804
 
 
805
    SetXFontComponent(wxXLFD_SLANT, s);
 
806
}
 
807
 
 
808
void wxNativeFontInfo::SetWeight(wxFontWeight weight)
 
809
{
 
810
    wxString s;
 
811
    switch ( weight )
 
812
    {
 
813
        case wxFONTWEIGHT_BOLD:
 
814
            s = wxT("bold");
 
815
            break;
 
816
 
 
817
        case wxFONTWEIGHT_LIGHT:
 
818
            s = wxT("light");
 
819
            break;
 
820
 
 
821
        case wxFONTWEIGHT_NORMAL:
 
822
            s = wxT("medium");
 
823
            break;
 
824
 
 
825
        default:
 
826
            wxFAIL_MSG( wxT("unknown wxFontWeight in wxNativeFontInfo::SetWeight") );
 
827
            return;
 
828
    }
 
829
 
 
830
    SetXFontComponent(wxXLFD_WEIGHT, s);
 
831
}
 
832
 
 
833
void wxNativeFontInfo::SetUnderlined(bool WXUNUSED(underlined))
 
834
{
 
835
    // can't do this under X
 
836
}
 
837
 
 
838
void wxNativeFontInfo::SetStrikethrough(bool WXUNUSED(strikethrough))
 
839
{
 
840
    // this is not supported by Pango fonts neither
 
841
}
 
842
 
 
843
bool wxNativeFontInfo::SetFaceName(const wxString& facename)
 
844
{
 
845
    SetXFontComponent(wxXLFD_FAMILY, facename);
 
846
    return true;
 
847
}
 
848
 
 
849
void wxNativeFontInfo::SetFamily(wxFontFamily WXUNUSED(family))
 
850
{
 
851
    // wxFontFamily -> X foundry, anyone?
 
852
    wxFAIL_MSG( wxT("not implemented") );
 
853
 
 
854
    // SetXFontComponent(wxXLFD_FOUNDRY, ...);
 
855
}
 
856
 
 
857
void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding)
 
858
{
 
859
    wxNativeEncodingInfo info;
 
860
    if ( wxGetNativeFontEncoding(encoding, &info) )
 
861
    {
 
862
        SetXFontComponent(wxXLFD_ENCODING, info.xencoding);
 
863
        SetXFontComponent(wxXLFD_REGISTRY, info.xregistry);
 
864
    }
 
865
}
 
866
 
 
867
// ----------------------------------------------------------------------------
 
868
// common functions
 
869
// ----------------------------------------------------------------------------
 
870
 
 
871
bool wxGetNativeFontEncoding(wxFontEncoding encoding,
 
872
                             wxNativeEncodingInfo *info)
 
873
{
 
874
    wxCHECK_MSG( info, false, wxT("bad pointer in wxGetNativeFontEncoding") );
 
875
 
 
876
    if ( encoding == wxFONTENCODING_DEFAULT )
 
877
    {
 
878
        encoding = wxFont::GetDefaultEncoding();
 
879
    }
 
880
 
 
881
    switch ( encoding )
 
882
    {
 
883
        case wxFONTENCODING_ISO8859_1:
 
884
        case wxFONTENCODING_ISO8859_2:
 
885
        case wxFONTENCODING_ISO8859_3:
 
886
        case wxFONTENCODING_ISO8859_4:
 
887
        case wxFONTENCODING_ISO8859_5:
 
888
        case wxFONTENCODING_ISO8859_6:
 
889
        case wxFONTENCODING_ISO8859_7:
 
890
        case wxFONTENCODING_ISO8859_8:
 
891
        case wxFONTENCODING_ISO8859_9:
 
892
        case wxFONTENCODING_ISO8859_10:
 
893
        case wxFONTENCODING_ISO8859_11:
 
894
        case wxFONTENCODING_ISO8859_12:
 
895
        case wxFONTENCODING_ISO8859_13:
 
896
        case wxFONTENCODING_ISO8859_14:
 
897
        case wxFONTENCODING_ISO8859_15:
 
898
            {
 
899
                int cp = encoding - wxFONTENCODING_ISO8859_1 + 1;
 
900
                info->xregistry = wxT("iso8859");
 
901
                info->xencoding.Printf(wxT("%d"), cp);
 
902
            }
 
903
            break;
 
904
 
 
905
        case wxFONTENCODING_UTF8:
 
906
            info->xregistry = wxT("iso10646");
 
907
            info->xencoding = wxT("*");
 
908
            break;
 
909
 
 
910
        case wxFONTENCODING_GB2312:
 
911
            info->xregistry = wxT("GB2312");   // or the otherway round?
 
912
            info->xencoding = wxT("*");
 
913
            break;
 
914
 
 
915
        case wxFONTENCODING_KOI8:
 
916
        case wxFONTENCODING_KOI8_U:
 
917
            info->xregistry = wxT("koi8");
 
918
 
 
919
            // we don't make distinction between koi8-r, koi8-u and koi8-ru (so far)
 
920
            info->xencoding = wxT("*");
 
921
            break;
 
922
 
 
923
        case wxFONTENCODING_CP1250:
 
924
        case wxFONTENCODING_CP1251:
 
925
        case wxFONTENCODING_CP1252:
 
926
        case wxFONTENCODING_CP1253:
 
927
        case wxFONTENCODING_CP1254:
 
928
        case wxFONTENCODING_CP1255:
 
929
        case wxFONTENCODING_CP1256:
 
930
        case wxFONTENCODING_CP1257:
 
931
            {
 
932
                int cp = encoding - wxFONTENCODING_CP1250 + 1250;
 
933
                info->xregistry = wxT("microsoft");
 
934
                info->xencoding.Printf(wxT("cp%d"), cp);
 
935
            }
 
936
            break;
 
937
 
 
938
        case wxFONTENCODING_EUC_JP:
 
939
        case wxFONTENCODING_SHIFT_JIS:
 
940
            info->xregistry = "jis*";
 
941
            info->xencoding = "*";
 
942
            break;
 
943
 
 
944
        case wxFONTENCODING_SYSTEM:
 
945
            info->xregistry =
 
946
            info->xencoding = wxT("*");
 
947
            break;
 
948
 
 
949
        default:
 
950
            // don't know how to translate this encoding into X fontspec
 
951
            return false;
 
952
    }
 
953
 
 
954
    info->encoding = encoding;
 
955
 
 
956
    return true;
 
957
}
 
958
 
 
959
bool wxTestFontEncoding(const wxNativeEncodingInfo& info)
 
960
{
 
961
    wxString fontspec;
 
962
    fontspec.Printf(wxT("-*-%s-*-*-*-*-*-*-*-*-*-*-%s-%s"),
 
963
                    !info.facename ? wxT("*") : info.facename.c_str(),
 
964
                    info.xregistry.c_str(),
 
965
                    info.xencoding.c_str());
 
966
 
 
967
    return wxTestFontSpec(fontspec);
 
968
}
 
969
 
 
970
// ----------------------------------------------------------------------------
 
971
// X-specific functions
 
972
// ----------------------------------------------------------------------------
 
973
 
 
974
wxNativeFont wxLoadQueryNearestFont(int pointSize,
 
975
                                    int family,
 
976
                                    int style,
 
977
                                    int weight,
 
978
                                    bool underlined,
 
979
                                    const wxString &facename,
 
980
                                    wxFontEncoding encoding,
 
981
                                    wxString* xFontName)
 
982
{
 
983
    if ( encoding == wxFONTENCODING_DEFAULT )
 
984
    {
 
985
        encoding = wxFont::GetDefaultEncoding();
 
986
    }
 
987
 
 
988
    // first determine the encoding - if the font doesn't exist at all in this
 
989
    // encoding, it's useless to do all other approximations (i.e. size,
 
990
    // family &c don't matter much)
 
991
    wxNativeEncodingInfo info;
 
992
    if ( encoding == wxFONTENCODING_SYSTEM )
 
993
    {
 
994
        // This will always work so we don't test to save time
 
995
        wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
 
996
    }
 
997
    else
 
998
    {
 
999
        if ( !wxGetNativeFontEncoding(encoding, &info) ||
 
1000
             !wxTestFontEncoding(info) )
 
1001
        {
 
1002
#if wxUSE_FONTMAP
 
1003
            if ( !wxFontMapper::Get()->GetAltForEncoding(encoding, &info) )
 
1004
#endif // wxUSE_FONTMAP
 
1005
            {
 
1006
                // unspported encoding - replace it with the default
 
1007
                //
 
1008
                // NB: we can't just return 0 from here because wxGTK code doesn't
 
1009
                //     check for it (i.e. it supposes that we'll always succeed),
 
1010
                //     so it would provoke a crash
 
1011
                wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
 
1012
            }
 
1013
        }
 
1014
    }
 
1015
 
 
1016
    // OK, we have the correct xregistry/xencoding in info structure
 
1017
    wxNativeFont font = 0;
 
1018
 
 
1019
    // if we already have the X font name, try to use it
 
1020
    if( xFontName && !xFontName->empty() )
 
1021
    {
 
1022
        //
 
1023
        //  Make sure point size is correct for scale factor.
 
1024
        //
 
1025
        wxStringTokenizer tokenizer(*xFontName, wxT("-"), wxTOKEN_RET_DELIMS);
 
1026
        wxString newFontName;
 
1027
 
 
1028
        for(int i = 0; i < 8; i++)
 
1029
          newFontName += tokenizer.NextToken();
 
1030
 
 
1031
        (void) tokenizer.NextToken();
 
1032
 
 
1033
        newFontName += wxString::Format(wxT("%d-"), pointSize);
 
1034
 
 
1035
        while(tokenizer.HasMoreTokens())
 
1036
          newFontName += tokenizer.GetNextToken();
 
1037
 
 
1038
        font = wxLoadFont(newFontName);
 
1039
 
 
1040
        if(font)
 
1041
          *xFontName = newFontName;
 
1042
    }
 
1043
 
 
1044
    if ( !font )
 
1045
    {
 
1046
        // search up and down by stepsize 10
 
1047
        int max_size = pointSize + 20 * (1 + (pointSize/180));
 
1048
        int min_size = pointSize - 20 * (1 + (pointSize/180));
 
1049
 
 
1050
        int i, round; // counters
 
1051
 
 
1052
        // first round: search for equal, then for smaller and for larger size
 
1053
        // with the given weight and style
 
1054
        int testweight = weight;
 
1055
        int teststyle = style;
 
1056
 
 
1057
        for ( round = 0; round < 3; round++ )
 
1058
        {
 
1059
            // second round: use normal weight
 
1060
            if ( round == 1 )
 
1061
            {
 
1062
                if ( testweight != wxNORMAL )
 
1063
                {
 
1064
                    testweight = wxNORMAL;
 
1065
                }
 
1066
                else
 
1067
                {
 
1068
                    ++round; // fall through to third round
 
1069
                }
 
1070
            }
 
1071
 
 
1072
            // third round: ... and use normal style
 
1073
            if ( round == 2 )
 
1074
            {
 
1075
                if ( teststyle != wxNORMAL )
 
1076
                {
 
1077
                    teststyle = wxNORMAL;
 
1078
                }
 
1079
                else
 
1080
                {
 
1081
                    break;
 
1082
                }
 
1083
            }
 
1084
            // Search for equal or smaller size (approx.)
 
1085
            for ( i = pointSize; !font && i >= 10 && i >= min_size; i -= 10 )
 
1086
            {
 
1087
                font = wxLoadQueryFont(i, family, teststyle, testweight, underlined,
 
1088
                                   facename, info.xregistry, info.xencoding,
 
1089
                                   xFontName);
 
1090
            }
 
1091
 
 
1092
            // Search for larger size (approx.)
 
1093
            for ( i = pointSize + 10; !font && i <= max_size; i += 10 )
 
1094
            {
 
1095
                font = wxLoadQueryFont(i, family, teststyle, testweight, underlined,
 
1096
                                   facename, info.xregistry, info.xencoding,
 
1097
                                   xFontName);
 
1098
            }
 
1099
        }
 
1100
 
 
1101
        // Try default family
 
1102
        if ( !font && family != wxDEFAULT )
 
1103
        {
 
1104
            font = wxLoadQueryFont(pointSize, wxDEFAULT, style, weight,
 
1105
                                   underlined, facename,
 
1106
                                   info.xregistry, info.xencoding,
 
1107
                                   xFontName );
 
1108
        }
 
1109
 
 
1110
        // ignore size, family, style and weight but try to find font with the
 
1111
        // given facename and encoding
 
1112
        if ( !font )
 
1113
        {
 
1114
            font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
 
1115
                                   underlined, facename,
 
1116
                                   info.xregistry, info.xencoding,
 
1117
                                   xFontName);
 
1118
 
 
1119
            // ignore family as well
 
1120
            if ( !font )
 
1121
            {
 
1122
                font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
 
1123
                                       underlined, wxEmptyString,
 
1124
                                       info.xregistry, info.xencoding,
 
1125
                                       xFontName);
 
1126
 
 
1127
                // if it still failed, try to get the font of any size but
 
1128
                // with the requested encoding: this can happen if the
 
1129
                // encoding is only available in one size which happens to be
 
1130
                // different from 120
 
1131
                if ( !font )
 
1132
                {
 
1133
                    font = wxLoadQueryFont(-1, wxDEFAULT, wxNORMAL, wxNORMAL,
 
1134
                                           false, wxEmptyString,
 
1135
                                           info.xregistry, info.xencoding,
 
1136
                                           xFontName);
 
1137
 
 
1138
                    // this should never happen as we had tested for it in the
 
1139
                    // very beginning, but if it does, do return something non
 
1140
                    // NULL or we'd crash in wxFont code
 
1141
                    if ( !font )
 
1142
                    {
 
1143
                        wxFAIL_MSG( wxT("this encoding should be available!") );
 
1144
 
 
1145
                        font = wxLoadQueryFont(-1,
 
1146
                                               wxDEFAULT, wxNORMAL, wxNORMAL,
 
1147
                                               false, wxEmptyString,
 
1148
                                               wxT("*"), wxT("*"),
 
1149
                                               xFontName);
 
1150
                    }
 
1151
                }
 
1152
            }
 
1153
        }
 
1154
    }
 
1155
 
 
1156
    return font;
 
1157
}
 
1158
 
 
1159
// ----------------------------------------------------------------------------
 
1160
// private functions
 
1161
// ----------------------------------------------------------------------------
 
1162
 
 
1163
// returns true if there are any fonts matching this font spec
 
1164
static bool wxTestFontSpec(const wxString& fontspec)
 
1165
{
 
1166
    // some X servers will fail to load this font because there are too many
 
1167
    // matches so we must test explicitly for this
 
1168
    if ( fontspec == wxT("-*-*-*-*-*-*-*-*-*-*-*-*-*-*") )
 
1169
    {
 
1170
        return true;
 
1171
    }
 
1172
 
 
1173
    wxNativeFont test = (wxNativeFont) g_fontHash->Get( fontspec );
 
1174
    if (test)
 
1175
    {
 
1176
        return true;
 
1177
    }
 
1178
 
 
1179
    test = wxLoadFont(fontspec);
 
1180
    g_fontHash->Put( fontspec, (wxObject*) test );
 
1181
 
 
1182
    if ( test )
 
1183
    {
 
1184
        wxFreeFont(test);
 
1185
 
 
1186
        return true;
 
1187
    }
 
1188
    else
 
1189
    {
 
1190
        return false;
 
1191
    }
 
1192
}
 
1193
 
 
1194
static wxNativeFont wxLoadQueryFont(int pointSize,
 
1195
                                    int family,
 
1196
                                    int style,
 
1197
                                    int weight,
 
1198
                                    bool WXUNUSED(underlined),
 
1199
                                    const wxString& facename,
 
1200
                                    const wxString& xregistry,
 
1201
                                    const wxString& xencoding,
 
1202
                                    wxString* xFontName)
 
1203
{
 
1204
    wxString xfamily;
 
1205
    switch (family)
 
1206
    {
 
1207
        case wxDECORATIVE: xfamily = wxT("lucida"); break;
 
1208
        case wxROMAN:      xfamily = wxT("times");  break;
 
1209
        case wxMODERN:     xfamily = wxT("courier"); break;
 
1210
        case wxSWISS:      xfamily = wxT("helvetica"); break;
 
1211
        case wxTELETYPE:   xfamily = wxT("lucidatypewriter"); break;
 
1212
        case wxSCRIPT:     xfamily = wxT("utopia"); break;
 
1213
        default:           xfamily = wxT("*");
 
1214
    }
 
1215
#if wxUSE_NANOX
 
1216
    int xweight;
 
1217
    switch (weight)
 
1218
    {
 
1219
         case wxBOLD:
 
1220
             {
 
1221
                 xweight = MWLF_WEIGHT_BOLD;
 
1222
                 break;
 
1223
             }
 
1224
        case wxLIGHT:
 
1225
             {
 
1226
                 xweight = MWLF_WEIGHT_LIGHT;
 
1227
                 break;
 
1228
             }
 
1229
         case wxNORMAL:
 
1230
             {
 
1231
                 xweight = MWLF_WEIGHT_NORMAL;
 
1232
                 break;
 
1233
             }
 
1234
 
 
1235
     default:
 
1236
             {
 
1237
                 xweight = MWLF_WEIGHT_DEFAULT;
 
1238
                 break;
 
1239
             }
 
1240
    }
 
1241
    GR_SCREEN_INFO screenInfo;
 
1242
    GrGetScreenInfo(& screenInfo);
 
1243
 
 
1244
    int yPixelsPerCM = screenInfo.ydpcm;
 
1245
 
 
1246
    // A point is 1/72 of an inch.
 
1247
    // An inch is 2.541 cm.
 
1248
    // So pixelHeight = (pointSize / 72) (inches) * 2.541 (for cm) * yPixelsPerCM (for pixels)
 
1249
    // In fact pointSize is 10 * the normal point size so
 
1250
    // divide by 10.
 
1251
 
 
1252
    int pixelHeight = (int) ( (((float)pointSize) / 720.0) * 2.541 * (float) yPixelsPerCM) ;
 
1253
 
 
1254
    // An alternative: assume that the screen is 72 dpi.
 
1255
    //int pixelHeight = (int) (((float)pointSize / 720.0) * 72.0) ;
 
1256
    //int pixelHeight = (int) ((float)pointSize / 10.0) ;
 
1257
 
 
1258
    GR_LOGFONT logFont;
 
1259
    logFont.lfHeight = pixelHeight;
 
1260
    logFont.lfWidth = 0;
 
1261
    logFont.lfEscapement = 0;
 
1262
    logFont.lfOrientation = 0;
 
1263
    logFont.lfWeight = xweight;
 
1264
    logFont.lfItalic = (style == wxNORMAL ? 0 : 1) ;
 
1265
    logFont.lfUnderline = 0;
 
1266
    logFont.lfStrikeOut = 0;
 
1267
    logFont.lfCharSet = MWLF_CHARSET_DEFAULT; // TODO: select appropriate one
 
1268
    logFont.lfOutPrecision = MWLF_TYPE_DEFAULT;
 
1269
    logFont.lfClipPrecision = 0; // Not used
 
1270
    logFont.lfRoman = (family == wxROMAN ? 1 : 0) ;
 
1271
    logFont.lfSerif = (family == wxSWISS ? 0 : 1) ;
 
1272
    logFont.lfSansSerif = !logFont.lfSerif ;
 
1273
    logFont.lfModern = (family == wxMODERN ? 1 : 0) ;
 
1274
    logFont.lfProportional = (family == wxTELETYPE ? 0 : 1) ;
 
1275
    logFont.lfOblique = 0;
 
1276
    logFont.lfSmallCaps = 0;
 
1277
    logFont.lfPitch = 0; // 0 = default
 
1278
    strcpy(logFont.lfFaceName, facename.c_str());
 
1279
 
 
1280
    XFontStruct* fontInfo = (XFontStruct*) malloc(sizeof(XFontStruct));
 
1281
    fontInfo->fid = GrCreateFont((GR_CHAR*) facename.c_str(), pixelHeight, & logFont);
 
1282
    GrGetFontInfo(fontInfo->fid, & fontInfo->info);
 
1283
    return (wxNativeFont) fontInfo;
 
1284
 
 
1285
#else
 
1286
    wxString fontSpec;
 
1287
    if (!facename.empty())
 
1288
    {
 
1289
        fontSpec.Printf(wxT("-*-%s-*-*-normal-*-*-*-*-*-*-*-*-*"),
 
1290
                        facename.c_str());
 
1291
 
 
1292
        if ( wxTestFontSpec(fontSpec) )
 
1293
        {
 
1294
            xfamily = facename;
 
1295
        }
 
1296
        //else: no such family, use default one instead
 
1297
    }
 
1298
 
 
1299
    wxString xstyle;
 
1300
    switch (style)
 
1301
    {
 
1302
        case wxSLANT:
 
1303
            fontSpec.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
 
1304
                    xfamily.c_str());
 
1305
            if ( wxTestFontSpec(fontSpec) )
 
1306
            {
 
1307
                xstyle = wxT("o");
 
1308
                break;
 
1309
            }
 
1310
            // fall through - try wxITALIC now
 
1311
 
 
1312
        case wxITALIC:
 
1313
            fontSpec.Printf(wxT("-*-%s-*-i-*-*-*-*-*-*-*-*-*-*"),
 
1314
                    xfamily.c_str());
 
1315
            if ( wxTestFontSpec(fontSpec) )
 
1316
            {
 
1317
                xstyle = wxT("i");
 
1318
            }
 
1319
            else if ( style == wxITALIC ) // and not wxSLANT
 
1320
            {
 
1321
                // try wxSLANT
 
1322
                fontSpec.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
 
1323
                        xfamily.c_str());
 
1324
                if ( wxTestFontSpec(fontSpec) )
 
1325
                {
 
1326
                    xstyle = wxT("o");
 
1327
                }
 
1328
                else
 
1329
                {
 
1330
                    // no italic, no slant - leave default
 
1331
                    xstyle = wxT("*");
 
1332
                }
 
1333
            }
 
1334
            break;
 
1335
 
 
1336
        default:
 
1337
            wxFAIL_MSG(wxT("unknown font style"));
 
1338
            // fall back to normal
 
1339
 
 
1340
        case wxNORMAL:
 
1341
            xstyle = wxT("r");
 
1342
            break;
 
1343
    }
 
1344
 
 
1345
    wxString xweight;
 
1346
    switch (weight)
 
1347
    {
 
1348
         case wxBOLD:
 
1349
             {
 
1350
                  fontSpec.Printf(wxT("-*-%s-bold-*-*-*-*-*-*-*-*-*-*-*"),
 
1351
                         xfamily.c_str());
 
1352
                  if ( wxTestFontSpec(fontSpec) )
 
1353
                  {
 
1354
                       xweight = wxT("bold");
 
1355
                       break;
 
1356
                  }
 
1357
                  fontSpec.Printf(wxT("-*-%s-heavy-*-*-*-*-*-*-*-*-*-*-*"),
 
1358
                         xfamily.c_str());
 
1359
                  if ( wxTestFontSpec(fontSpec) )
 
1360
                  {
 
1361
                       xweight = wxT("heavy");
 
1362
                       break;
 
1363
                  }
 
1364
                  fontSpec.Printf(wxT("-*-%s-extrabold-*-*-*-*-*-*-*-*-*-*-*"),
 
1365
                         xfamily.c_str());
 
1366
                  if ( wxTestFontSpec(fontSpec) )
 
1367
                  {
 
1368
                      xweight = wxT("extrabold");
 
1369
                      break;
 
1370
                  }
 
1371
                  fontSpec.Printf(wxT("-*-%s-demibold-*-*-*-*-*-*-*-*-*-*-*"),
 
1372
                         xfamily.c_str());
 
1373
                  if ( wxTestFontSpec(fontSpec) )
 
1374
                  {
 
1375
                      xweight = wxT("demibold");
 
1376
                      break;
 
1377
                  }
 
1378
                  fontSpec.Printf(wxT("-*-%s-black-*-*-*-*-*-*-*-*-*-*-*"),
 
1379
                         xfamily.c_str());
 
1380
                  if ( wxTestFontSpec(fontSpec) )
 
1381
                  {
 
1382
                      xweight = wxT("black");
 
1383
                      break;
 
1384
                  }
 
1385
                  fontSpec.Printf(wxT("-*-%s-ultrablack-*-*-*-*-*-*-*-*-*-*-*"),
 
1386
                         xfamily.c_str());
 
1387
                  if ( wxTestFontSpec(fontSpec) )
 
1388
                  {
 
1389
                      xweight = wxT("ultrablack");
 
1390
                      break;
 
1391
                  }
 
1392
              }
 
1393
              break;
 
1394
        case wxLIGHT:
 
1395
             {
 
1396
                  fontSpec.Printf(wxT("-*-%s-light-*-*-*-*-*-*-*-*-*-*-*"),
 
1397
                         xfamily.c_str());
 
1398
                  if ( wxTestFontSpec(fontSpec) )
 
1399
                  {
 
1400
                       xweight = wxT("light");
 
1401
                       break;
 
1402
                  }
 
1403
                  fontSpec.Printf(wxT("-*-%s-thin-*-*-*-*-*-*-*-*-*-*-*"),
 
1404
                         xfamily.c_str());
 
1405
                  if ( wxTestFontSpec(fontSpec) )
 
1406
                  {
 
1407
                       xweight = wxT("thin");
 
1408
                       break;
 
1409
                  }
 
1410
             }
 
1411
             break;
 
1412
         case wxNORMAL:
 
1413
             {
 
1414
                  fontSpec.Printf(wxT("-*-%s-medium-*-*-*-*-*-*-*-*-*-*-*"),
 
1415
                         xfamily.c_str());
 
1416
                  if ( wxTestFontSpec(fontSpec) )
 
1417
                  {
 
1418
                       xweight = wxT("medium");
 
1419
                       break;
 
1420
                  }
 
1421
                  fontSpec.Printf(wxT("-*-%s-normal-*-*-*-*-*-*-*-*-*-*-*"),
 
1422
                         xfamily.c_str());
 
1423
                  if ( wxTestFontSpec(fontSpec) )
 
1424
                  {
 
1425
                       xweight = wxT("normal");
 
1426
                       break;
 
1427
                  }
 
1428
                  fontSpec.Printf(wxT("-*-%s-regular-*-*-*-*-*-*-*-*-*-*-*"),
 
1429
                         xfamily.c_str());
 
1430
                  if ( wxTestFontSpec(fontSpec) )
 
1431
                  {
 
1432
                      xweight = wxT("regular");
 
1433
                      break;
 
1434
                  }
 
1435
                  xweight = wxT("*");
 
1436
              }
 
1437
              break;
 
1438
        default:           xweight = wxT("*"); break;
 
1439
    }
 
1440
 
 
1441
    // if pointSize is -1, don't specify any
 
1442
    wxString sizeSpec;
 
1443
    if ( pointSize == -1 )
 
1444
    {
 
1445
        sizeSpec = wxT('*');
 
1446
    }
 
1447
    else
 
1448
    {
 
1449
        sizeSpec.Printf(wxT("%d"), pointSize);
 
1450
    }
 
1451
 
 
1452
    // construct the X font spec from our data
 
1453
    fontSpec.Printf(wxT("-*-%s-%s-%s-normal-*-*-%s-*-*-*-*-%s-%s"),
 
1454
                    xfamily.c_str(), xweight.c_str(), xstyle.c_str(),
 
1455
                    sizeSpec.c_str(), xregistry.c_str(), xencoding.c_str());
 
1456
 
 
1457
    if( xFontName )
 
1458
        *xFontName = fontSpec;
 
1459
 
 
1460
    return wxLoadFont(fontSpec);
 
1461
#endif
 
1462
    // wxUSE_NANOX
 
1463
}
 
1464
 
 
1465
// ----------------------------------------------------------------------------
 
1466
// wxFontModule
 
1467
// ----------------------------------------------------------------------------
 
1468
 
 
1469
class wxFontModule : public wxModule
 
1470
{
 
1471
public:
 
1472
    bool OnInit();
 
1473
    void OnExit();
 
1474
 
 
1475
private:
 
1476
    DECLARE_DYNAMIC_CLASS(wxFontModule)
 
1477
};
 
1478
 
 
1479
IMPLEMENT_DYNAMIC_CLASS(wxFontModule, wxModule)
 
1480
 
 
1481
bool wxFontModule::OnInit()
 
1482
{
 
1483
    g_fontHash = new wxHashTable( wxKEY_STRING );
 
1484
 
 
1485
    return true;
 
1486
}
 
1487
 
 
1488
void wxFontModule::OnExit()
 
1489
{
 
1490
    wxDELETE(g_fontHash);
 
1491
}
 
1492
 
 
1493
#endif // GTK 2.0/1.x