~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/gui/text/qfontdatabase.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
 
4
**
 
5
** This file is part of the text module of the Qt Toolkit.
 
6
**
 
7
** This file may be distributed under the terms of the Q Public License
 
8
** as defined by Trolltech AS of Norway and appearing in the file
 
9
** LICENSE.QPL included in the packaging of this file.
 
10
**
 
11
** This file may be distributed and/or modified under the terms of the
 
12
** GNU General Public License version 2 as published by the Free Software
 
13
** Foundation and appearing in the file LICENSE.GPL included in the
 
14
** packaging of this file.
 
15
**
 
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
 
17
**   information about Qt Commercial License Agreements.
 
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
 
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
 
20
**
 
21
** Contact info@trolltech.com if any conditions of this licensing are
 
22
** not clear to you.
 
23
**
 
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
26
**
 
27
****************************************************************************/
 
28
 
 
29
#include "qfontdatabase.h"
 
30
 
 
31
#ifndef QT_NO_FONTDATABASE
 
32
 
 
33
#include <qalgorithms.h>
 
34
#include <qapplication.h>
 
35
 
 
36
#include <private/qunicodetables_p.h>
 
37
#include "qfontengine_p.h"
 
38
#include "qopentype_p.h"
 
39
 
 
40
#ifdef Q_WS_X11
 
41
#include <locale.h>
 
42
#endif
 
43
#include <stdlib.h>
 
44
#include <limits.h>
 
45
 
 
46
// #define QFONTDATABASE_DEBUG
 
47
#ifdef QFONTDATABASE_DEBUG
 
48
#  define FD_DEBUG qDebug
 
49
#else
 
50
#  define FD_DEBUG if (false) qDebug
 
51
#endif
 
52
 
 
53
// #define FONT_MATCH_DEBUG
 
54
#ifdef FONT_MATCH_DEBUG
 
55
#  define FM_DEBUG qDebug
 
56
#else
 
57
#  define FM_DEBUG if (false) qDebug
 
58
#endif
 
59
 
 
60
#if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET)
 
61
#  define for if(0){}else for
 
62
#endif
 
63
 
 
64
 
 
65
Q_GUI_EXPORT bool qt_enable_test_font = false;
 
66
 
 
67
static int ucstricmp(const QString &as, const QString &bs)
 
68
{
 
69
    const QChar *a = as.unicode();
 
70
    const QChar *b = bs.unicode();
 
71
    if (a == b)
 
72
        return 0;
 
73
    if (a == 0)
 
74
        return 1;
 
75
    if (b == 0)
 
76
        return -1;
 
77
    int l=qMin(as.length(),bs.length());
 
78
    while (l-- && ::lower(*a) == ::lower(*b))
 
79
        a++,b++;
 
80
    if (l==-1)
 
81
        return (as.length()-bs.length());
 
82
    return ::lower(*a).unicode() - ::lower(*b).unicode();
 
83
}
 
84
 
 
85
static int getFontWeight(const QString &weightString)
 
86
{
 
87
    QString s = weightString.toLower();
 
88
 
 
89
    // Test in decreasing order of commonness
 
90
    if (s == "medium" ||
 
91
        s == "normal")
 
92
        return QFont::Normal;
 
93
    if (s == "bold")
 
94
        return QFont::Bold;
 
95
    if (s == "demibold" || s == "demi bold")
 
96
        return QFont::DemiBold;
 
97
    if (s == "black")
 
98
        return QFont::Black;
 
99
    if (s == "light")
 
100
        return QFont::Light;
 
101
 
 
102
    if (s.contains("bold")) {
 
103
        if (s.contains("demi"))
 
104
            return (int) QFont::DemiBold;
 
105
        return (int) QFont::Bold;
 
106
    }
 
107
 
 
108
    if (s.contains("light"))
 
109
        return (int) QFont::Light;
 
110
 
 
111
    if (s.contains("black"))
 
112
        return (int) QFont::Black;
 
113
 
 
114
    return (int) QFont::Normal;
 
115
}
 
116
 
 
117
#ifdef Q_WS_X11
 
118
struct QtFontEncoding
 
119
{
 
120
    signed int encoding : 16;
 
121
 
 
122
    uint xpoint   : 16;
 
123
    uint xres     : 8;
 
124
    uint yres     : 8;
 
125
    uint avgwidth : 16;
 
126
    uchar pitch   : 8;
 
127
};
 
128
#endif // Q_WS_X11
 
129
 
 
130
struct QtFontSize
 
131
{
 
132
    unsigned short pixelSize;
 
133
 
 
134
#ifdef Q_WS_X11
 
135
    int count;
 
136
    QtFontEncoding *encodings;
 
137
    QtFontEncoding *encodingID(int id, uint xpoint = 0, uint xres = 0,
 
138
                                uint yres = 0, uint avgwidth = 0, bool add = false);
 
139
#endif // Q_WS_X11
 
140
#ifdef Q_WS_QWS
 
141
    QByteArray fileName;
 
142
#endif
 
143
};
 
144
 
 
145
 
 
146
#ifdef Q_WS_X11
 
147
QtFontEncoding *QtFontSize::encodingID(int id, uint xpoint, uint xres,
 
148
                                        uint yres, uint avgwidth, bool add)
 
149
{
 
150
    // we don't match using the xpoint, xres and yres parameters, only the id
 
151
    for (int i = 0; i < count; ++i) {
 
152
        if (encodings[i].encoding == id)
 
153
            return encodings + i;
 
154
    }
 
155
 
 
156
    if (!add) return 0;
 
157
 
 
158
    if (!(count % 4))
 
159
        encodings = (QtFontEncoding *)
 
160
                    realloc(encodings,
 
161
                             (((count+4) >> 2) << 2) * sizeof(QtFontEncoding));
 
162
    encodings[count].encoding = id;
 
163
    encodings[count].xpoint = xpoint;
 
164
    encodings[count].xres = xres;
 
165
    encodings[count].yres = yres;
 
166
    encodings[count].avgwidth = avgwidth;
 
167
    encodings[count].pitch = '*';
 
168
    return encodings + count++;
 
169
}
 
170
#endif // Q_WS_X11
 
171
 
 
172
struct QtFontStyle
 
173
{
 
174
    struct Key {
 
175
        Key(const QString &styleString);
 
176
        Key() : style(QFont::StyleNormal),
 
177
                weight(QFont::Normal), stretch(0) { }
 
178
        Key(const Key &o) : style(o.style),
 
179
                              weight(o.weight), stretch(o.stretch) { }
 
180
        uint style : 2;
 
181
        signed int  weight : 8;
 
182
        signed int stretch : 12;
 
183
 
 
184
        bool operator==(const Key & other) {
 
185
            return (style == other.style &&
 
186
                     weight == other.weight &&
 
187
                     (stretch == 0 || other.stretch == 0 || stretch == other.stretch));
 
188
        }
 
189
        bool operator!=(const Key &other) {
 
190
            return !operator==(other);
 
191
        }
 
192
        bool operator <(const Key &o) {
 
193
            int x = (style << 12) + (weight << 14) + stretch;
 
194
            int y = (o.style << 12) + (o.weight << 14) + o.stretch;
 
195
            return (x < y);
 
196
        }
 
197
    };
 
198
 
 
199
    QtFontStyle(const Key &k)
 
200
        : key(k), bitmapScalable(false), smoothScalable(false),
 
201
          fakeOblique(false), count(0), pixelSizes(0)
 
202
    {
 
203
#if defined(Q_WS_X11)
 
204
        weightName = setwidthName = 0;
 
205
#endif // Q_WS_X11
 
206
    }
 
207
 
 
208
    ~QtFontStyle() {
 
209
#ifdef Q_WS_X11
 
210
        delete [] weightName;
 
211
        delete [] setwidthName;
 
212
        while (count--)
 
213
            free(pixelSizes[count].encodings);
 
214
#endif
 
215
        free(pixelSizes);
 
216
    }
 
217
 
 
218
    Key key;
 
219
    bool bitmapScalable : 1;
 
220
    bool smoothScalable : 1;
 
221
    bool fakeOblique    : 1;
 
222
    signed int count    : 29;
 
223
    QtFontSize *pixelSizes;
 
224
 
 
225
#ifdef Q_WS_X11
 
226
    const char *weightName;
 
227
    const char *setwidthName;
 
228
#endif // Q_WS_X11
 
229
 
 
230
    QtFontSize *pixelSize(unsigned short size, bool = false);
 
231
};
 
232
 
 
233
QtFontStyle::Key::Key(const QString &styleString)
 
234
    : style(QFont::StyleNormal), weight(QFont::Normal), stretch(0)
 
235
{
 
236
    weight = getFontWeight(styleString);
 
237
 
 
238
    if (styleString.contains("Italic"))
 
239
        style = QFont::StyleItalic;
 
240
    else if (styleString.contains("Oblique"))
 
241
        style = QFont::StyleOblique;
 
242
}
 
243
 
 
244
QtFontSize *QtFontStyle::pixelSize(unsigned short size, bool add)
 
245
{
 
246
    for (int i = 0; i < count; i++) {
 
247
        if (pixelSizes[i].pixelSize == size)
 
248
            return pixelSizes + i;
 
249
    }
 
250
    if (!add)
 
251
        return 0;
 
252
 
 
253
    if (!(count % 8))
 
254
        pixelSizes = (QtFontSize *)
 
255
                     realloc(pixelSizes,
 
256
                              (((count+8) >> 3) << 3) * sizeof(QtFontSize));
 
257
    pixelSizes[count].pixelSize = size;
 
258
#ifdef Q_WS_X11
 
259
    pixelSizes[count].count = 0;
 
260
    pixelSizes[count].encodings = 0;
 
261
#endif
 
262
#ifdef Q_WS_QWS
 
263
    new (&pixelSizes[count].fileName) QByteArray;
 
264
#endif
 
265
    return pixelSizes + (count++);
 
266
}
 
267
 
 
268
struct QtFontFoundry
 
269
{
 
270
    QtFontFoundry(const QString &n) : name(n), count(0), styles(0) {}
 
271
    ~QtFontFoundry() {
 
272
        while (count--)
 
273
            delete styles[count];
 
274
        free(styles);
 
275
    }
 
276
 
 
277
    QString name;
 
278
 
 
279
    int count;
 
280
    QtFontStyle **styles;
 
281
    QtFontStyle *style(const QtFontStyle::Key &, bool = false);
 
282
};
 
283
 
 
284
QtFontStyle *QtFontFoundry::style(const QtFontStyle::Key &key, bool create)
 
285
{
 
286
    int pos = 0;
 
287
    if (count) {
 
288
        int low = 0;
 
289
        int high = count;
 
290
        pos = count / 2;
 
291
        while (high > low) {
 
292
            if (styles[pos]->key == key)
 
293
                return styles[pos];
 
294
            if (styles[pos]->key < key)
 
295
                low = pos + 1;
 
296
            else
 
297
                high = pos;
 
298
            pos = (high + low) / 2;
 
299
        };
 
300
        pos = low;
 
301
    }
 
302
    if (!create)
 
303
        return 0;
 
304
 
 
305
//     qDebug("adding key (weight=%d, style=%d, oblique=%d stretch=%d) at %d", key.weight, key.style, key.oblique, key.stretch, pos);
 
306
    if (!(count % 8))
 
307
        styles = (QtFontStyle **)
 
308
                 realloc(styles, (((count+8) >> 3) << 3) * sizeof(QtFontStyle *));
 
309
 
 
310
    memmove(styles + pos + 1, styles + pos, (count-pos)*sizeof(QtFontStyle *));
 
311
    styles[pos] = new QtFontStyle(key);
 
312
    count++;
 
313
    return styles[pos];
 
314
}
 
315
 
 
316
 
 
317
struct QtFontFamily
 
318
{
 
319
    enum WritingSystemStatus {
 
320
        Unknown         = 0,
 
321
        Supported       = 1,
 
322
        UnsupportedFT  = 2,
 
323
        UnsupportedXLFD = 4,
 
324
        Unsupported     = UnsupportedFT | UnsupportedXLFD
 
325
    };
 
326
 
 
327
    QtFontFamily(const QString &n)
 
328
        :
 
329
#ifdef Q_WS_X11
 
330
        fixedPitch(true), hasFT(false), ftWritingSystemCheck(false),
 
331
        xlfdLoaded(false), synthetic(false),
 
332
#else
 
333
        fixedPitch(false),
 
334
#endif
 
335
#ifdef Q_WS_WIN
 
336
        writingSystemCheck(false),
 
337
#endif
 
338
#if defined(Q_OS_MAC) && !defined(QWS)
 
339
        fixedPitchComputed(false),
 
340
#endif
 
341
        name(n), count(0), foundries(0) {
 
342
        memset(writingSystems, 0, sizeof(writingSystems));
 
343
    }
 
344
    ~QtFontFamily() {
 
345
        while (count--)
 
346
            delete foundries[count];
 
347
        free(foundries);
 
348
    }
 
349
 
 
350
    bool fixedPitch : 1;
 
351
#ifdef Q_WS_X11
 
352
    bool hasFT : 1;
 
353
    bool ftWritingSystemCheck : 1;
 
354
    bool xlfdLoaded : 1;
 
355
    bool synthetic : 1;
 
356
#endif
 
357
#ifdef Q_WS_WIN
 
358
    bool writingSystemCheck : 1;
 
359
#endif
 
360
#if defined(Q_OS_MAC) && !defined(QWS)
 
361
    bool fixedPitchComputed : 1;
 
362
#endif
 
363
    QString name;
 
364
    QString rawName;
 
365
#ifdef Q_WS_X11
 
366
    QByteArray fontFilename;
 
367
    int fontFileIndex;
 
368
#endif
 
369
#ifdef Q_WS_WIN
 
370
    QString english_name;
 
371
#endif
 
372
    int count;
 
373
    QtFontFoundry **foundries;
 
374
 
 
375
    unsigned char writingSystems[QFontDatabase::WritingSystemsCount];
 
376
 
 
377
    QtFontFoundry *foundry(const QString &f, bool = false);
 
378
};
 
379
 
 
380
#if defined(Q_OS_MAC) && !defined(QWS)
 
381
inline static void qt_mac_get_fixed_pitch(QtFontFamily *f)
 
382
{
 
383
    if(f && !f->fixedPitchComputed) {
 
384
        QFontMetrics fm(f->name);
 
385
        f->fixedPitch = fm.width('i') == fm.width('m');
 
386
        f->fixedPitchComputed = true;
 
387
    }
 
388
}
 
389
#endif
 
390
 
 
391
 
 
392
QtFontFoundry *QtFontFamily::foundry(const QString &f, bool create)
 
393
{
 
394
    if (f.isNull() && count == 1)
 
395
        return foundries[0];
 
396
 
 
397
    for (int i = 0; i < count; i++) {
 
398
        if (ucstricmp(foundries[i]->name, f) == 0)
 
399
            return foundries[i];
 
400
    }
 
401
    if (!create)
 
402
        return 0;
 
403
 
 
404
    if (!(count % 8))
 
405
        foundries = (QtFontFoundry **)
 
406
                    realloc(foundries,
 
407
                             (((count+8) >> 3) << 3) * sizeof(QtFontFoundry *));
 
408
 
 
409
    foundries[count] = new QtFontFoundry(f);
 
410
    return foundries[count++];
 
411
}
 
412
 
 
413
class QFontDatabasePrivate
 
414
{
 
415
public:
 
416
    QFontDatabasePrivate() : count(0), families(0) { }
 
417
    ~QFontDatabasePrivate() {
 
418
        while (count--)
 
419
            delete families[count];
 
420
        free(families);
 
421
    }
 
422
    QtFontFamily *family(const QString &f, bool = false);
 
423
 
 
424
    int count;
 
425
    QtFontFamily **families;
 
426
};
 
427
 
 
428
QtFontFamily *QFontDatabasePrivate::family(const QString &f, bool create)
 
429
{
 
430
    int low = 0;
 
431
    int high = count;
 
432
    int pos = count / 2;
 
433
    int res = 1;
 
434
    if (count) {
 
435
        while ((res = ucstricmp(families[pos]->name, f)) && pos != low) {
 
436
            if (res > 0)
 
437
                high = pos;
 
438
            else
 
439
                low = pos;
 
440
            pos = (high + low) / 2;
 
441
        };
 
442
        if (!res)
 
443
            return families[pos];
 
444
    }
 
445
    if (!create)
 
446
        return 0;
 
447
 
 
448
    if (res < 0)
 
449
        pos++;
 
450
 
 
451
    // qDebug("adding family %s at %d total=%d", f.latin1(), pos, count);
 
452
    if (!(count % 8))
 
453
        families = (QtFontFamily **)
 
454
                   realloc(families,
 
455
                            (((count+8) >> 3) << 3) * sizeof(QtFontFamily *));
 
456
 
 
457
    memmove(families + pos + 1, families + pos, (count-pos)*sizeof(QtFontFamily *));
 
458
    families[pos] = new QtFontFamily(f);
 
459
    count++;
 
460
    return families[pos];
 
461
}
 
462
 
 
463
 
 
464
static const int scriptForWritingSystem[] = {
 
465
    QUnicodeTables::Common, // Any
 
466
    QUnicodeTables::Common, // Latin
 
467
    QUnicodeTables::Common, // Greek
 
468
    QUnicodeTables::Common, // Cyrillic
 
469
    QUnicodeTables::Common, // Armenian
 
470
    QUnicodeTables::Hebrew, // Hebrew
 
471
    QUnicodeTables::Arabic, // Arabic
 
472
    QUnicodeTables::Syriac, // Syriac
 
473
    QUnicodeTables::Thaana, // Thaana
 
474
    QUnicodeTables::Devanagari, // Devanagari
 
475
    QUnicodeTables::Bengali, // Bengali
 
476
    QUnicodeTables::Gurmukhi, // Gurmukhi
 
477
    QUnicodeTables::Gujarati, // Gujarati
 
478
    QUnicodeTables::Oriya, // Oriya
 
479
    QUnicodeTables::Tamil, // Tamil
 
480
    QUnicodeTables::Telugu, // Telugu
 
481
    QUnicodeTables::Kannada, // Kannada
 
482
    QUnicodeTables::Malayalam, // Malayalam
 
483
    QUnicodeTables::Sinhala, // Sinhala
 
484
    QUnicodeTables::Thai, // Thai
 
485
    QUnicodeTables::Lao, // Lao
 
486
    QUnicodeTables::Tibetan, // Tibetan
 
487
    QUnicodeTables::Myanmar, // Myanmar
 
488
    QUnicodeTables::Common, // Georgian
 
489
    QUnicodeTables::Khmer, // Khmer
 
490
    QUnicodeTables::Common, // SimplifiedChinese
 
491
    QUnicodeTables::Common, // TraditionalChinese
 
492
    QUnicodeTables::Common, // Japanese
 
493
    QUnicodeTables::Hangul, // Korean
 
494
    QUnicodeTables::Common, // Vietnamese
 
495
    QUnicodeTables::Common, // Yi
 
496
    QUnicodeTables::Common, // Tagalog
 
497
    QUnicodeTables::Common, // Hanunoo
 
498
    QUnicodeTables::Common, // Buhid
 
499
    QUnicodeTables::Common, // Tagbanwa
 
500
    QUnicodeTables::Common, // Limbu
 
501
    QUnicodeTables::Common, // TaiLe
 
502
    QUnicodeTables::Common, // Braille
 
503
    QUnicodeTables::Common  // Other
 
504
};
 
505
 
 
506
 
 
507
#if defined Q_WS_QWS || (defined(Q_WS_X11) && !defined(QT_NO_FONTCONFIG))
 
508
static inline bool requiresOpenType(int writingSystem)
 
509
{
 
510
    return ((writingSystem >= QFontDatabase::Syriac && writingSystem <= QFontDatabase::Sinhala)
 
511
            || writingSystem == QFontDatabase::Myanmar
 
512
            || writingSystem == QFontDatabase::Khmer);
 
513
}
 
514
static inline bool scriptRequiresOpenType(int script)
 
515
{
 
516
    return ((script >= QUnicodeTables::Syriac && script <= QUnicodeTables::Sinhala)
 
517
            || script == QUnicodeTables::Myanmar
 
518
            || script == QUnicodeTables::Khmer);
 
519
}
 
520
#endif
 
521
 
 
522
Q_GLOBAL_STATIC(QFontDatabasePrivate, privateDb);
 
523
 
 
524
#define SMOOTH_SCALABLE 0xffff
 
525
 
 
526
#if defined(Q_WS_X11)
 
527
#  include "qfontdatabase_x11.cpp"
 
528
#elif defined(Q_WS_MAC)
 
529
#  include "qfontdatabase_mac.cpp"
 
530
#elif defined(Q_WS_WIN)
 
531
#  include "qfontdatabase_win.cpp"
 
532
#elif defined(Q_WS_QWS)
 
533
#  include "qfontdatabase_qws.cpp"
 
534
#endif
 
535
 
 
536
static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &styleKey)
 
537
{
 
538
    int best = 0;
 
539
    int dist = 0xffff;
 
540
 
 
541
    for ( int i = 0; i < foundry->count; i++ ) {
 
542
        QtFontStyle *style = foundry->styles[i];
 
543
 
 
544
        int d = qAbs( styleKey.weight - style->key.weight );
 
545
 
 
546
        if ( styleKey.stretch != 0 && style->key.stretch != 0 ) {
 
547
            d += qAbs( styleKey.stretch - style->key.stretch );
 
548
        }
 
549
 
 
550
        if (styleKey.style != style->key.style) {
 
551
            if (styleKey.style != QFont::StyleNormal && style->key.style != QFont::StyleNormal)
 
552
                // one is italic, the other oblique
 
553
                d += 0x0001;
 
554
            else
 
555
                d += 0x1000;
 
556
        }
 
557
 
 
558
        if ( d < dist ) {
 
559
            best = i;
 
560
            dist = d;
 
561
        }
 
562
    }
 
563
 
 
564
    FM_DEBUG( "          best style has distance 0x%x", dist );
 
565
    return foundry->styles[best];
 
566
}
 
567
 
 
568
#if defined(Q_WS_X11)
 
569
static QtFontEncoding *findEncoding(int script, int styleStrategy,
 
570
                                    QtFontSize *size, int force_encoding_id)
 
571
{
 
572
    QtFontEncoding *encoding = 0;
 
573
 
 
574
    if (force_encoding_id >= 0) {
 
575
        encoding = size->encodingID(force_encoding_id);
 
576
        if (!encoding)
 
577
            FM_DEBUG("            required encoding_id not available");
 
578
        return encoding;
 
579
    }
 
580
 
 
581
    if (styleStrategy & (QFont::OpenGLCompatible | QFont::PreferBitmap)) {
 
582
        FM_DEBUG("            PreferBitmap and/or OpenGL set, skipping Freetype");
 
583
    } else {
 
584
        encoding = size->encodingID(-1); // -1 == prefer Freetype
 
585
        if (encoding)
 
586
            return encoding;
 
587
    }
 
588
 
 
589
    // FT not available, find an XLFD font, trying the default encoding first
 
590
    encoding = size->encodingID(QFontPrivate::defaultEncodingID);
 
591
    if (encoding) {
 
592
        // does it support the requested script?
 
593
        bool supportsScript = false;
 
594
        for (int ws = 1; !supportsScript && ws < QFontDatabase::WritingSystemsCount; ++ws) {
 
595
            if (scriptForWritingSystem[ws] != script)
 
596
                continue;
 
597
            supportsScript = writingSystems_for_xlfd_encoding[encoding->encoding][ws];
 
598
        }
 
599
        if (!supportsScript)
 
600
            encoding = 0;
 
601
    }
 
602
    // find the first encoding that supports the requested script
 
603
    for (int ws = 1; !encoding && ws < QFontDatabase::WritingSystemsCount; ++ws) {
 
604
        if (scriptForWritingSystem[ws] != script)
 
605
            continue;
 
606
        for (int x = 0; !encoding && x < size->count; ++x) {
 
607
            const int enc = size->encodings[x].encoding;
 
608
            if (writingSystems_for_xlfd_encoding[enc][ws])
 
609
                encoding = size->encodings + x;
 
610
        }
 
611
    }
 
612
 
 
613
    return encoding;
 
614
}
 
615
#endif // Q_WS_X11
 
616
 
 
617
static
 
618
unsigned int bestFoundry(int script, unsigned int score, int styleStrategy,
 
619
                         const QtFontFamily *family, const QString &foundry_name,
 
620
                         QtFontStyle::Key styleKey, int pixelSize, char pitch,
 
621
                         QtFontFoundry **best_foundry, QtFontStyle **best_style,
 
622
                         QtFontSize **best_size
 
623
#ifdef Q_WS_X11
 
624
                         , QtFontEncoding **best_encoding, int force_encoding_id
 
625
#endif
 
626
                         )
 
627
{
 
628
    Q_UNUSED(script);
 
629
    Q_UNUSED(pitch);
 
630
 
 
631
    FM_DEBUG("  REMARK: looking for best foundry for family '%s' [%d]", family->name.toLatin1().constData(), family->count);
 
632
 
 
633
    for (int x = 0; x < family->count; ++x) {
 
634
        QtFontFoundry *foundry = family->foundries[x];
 
635
        if (! foundry_name.isEmpty() &&
 
636
            ucstricmp(foundry->name, foundry_name) != 0)
 
637
            continue;
 
638
 
 
639
        FM_DEBUG("          looking for matching style in foundry '%s' %d",
 
640
                 foundry->name.isEmpty() ? "-- none --" : foundry->name.toLatin1().constData(), foundry->count);
 
641
 
 
642
        QtFontStyle *style = bestStyle(foundry, styleKey);
 
643
 
 
644
        if (! style->smoothScalable && (styleStrategy & QFont::ForceOutline)) {
 
645
            FM_DEBUG("            ForceOutline set, but not smoothly scalable");
 
646
            continue;
 
647
        }
 
648
 
 
649
        int px = -1;
 
650
        QtFontSize *size = 0;
 
651
 
 
652
        // 1. see if we have an exact matching size
 
653
        if (! (styleStrategy & QFont::ForceOutline)) {
 
654
            size = style->pixelSize(pixelSize);
 
655
            if (size) {
 
656
                FM_DEBUG("          found exact size match (%d pixels)", size->pixelSize);
 
657
                px = size->pixelSize;
 
658
            }
 
659
        }
 
660
 
 
661
        // 2. see if we have a smoothly scalable font
 
662
        if (! size && style->smoothScalable && ! (styleStrategy & QFont::PreferBitmap)) {
 
663
            size = style->pixelSize(SMOOTH_SCALABLE);
 
664
            if (size) {
 
665
                FM_DEBUG("          found smoothly scalable font (%d pixels)", pixelSize);
 
666
                px = pixelSize;
 
667
            }
 
668
        }
 
669
 
 
670
        // 3. see if we have a bitmap scalable font
 
671
        if (! size && style->bitmapScalable && (styleStrategy & QFont::PreferMatch)) {
 
672
            size = style->pixelSize(0);
 
673
            if (size) {
 
674
                FM_DEBUG("          found bitmap scalable font (%d pixels)", pixelSize);
 
675
                px = pixelSize;
 
676
            }
 
677
        }
 
678
 
 
679
#ifdef Q_WS_X11
 
680
        QtFontEncoding *encoding = 0;
 
681
#endif
 
682
 
 
683
        // 4. find closest size match
 
684
        if (! size) {
 
685
            unsigned int distance = ~0u;
 
686
            for (int x = 0; x < style->count; ++x) {
 
687
#ifdef Q_WS_X11
 
688
                encoding =
 
689
                    findEncoding(script, styleStrategy, style->pixelSizes + x, force_encoding_id);
 
690
                if (!encoding) {
 
691
                    FM_DEBUG("          size %3d does not support the script we want",
 
692
                             style->pixelSizes[x].pixelSize);
 
693
                    continue;
 
694
                }
 
695
#endif
 
696
 
 
697
                unsigned int d;
 
698
                if (style->pixelSizes[x].pixelSize < pixelSize) {
 
699
                    // penalize sizes that are smaller than the
 
700
                    // requested size, due to truncation from floating
 
701
                    // point to integer conversions
 
702
                    d = pixelSize - style->pixelSizes[x].pixelSize + 1;
 
703
                } else {
 
704
                    d = style->pixelSizes[x].pixelSize - pixelSize;
 
705
                }
 
706
 
 
707
                if (d < distance) {
 
708
                    distance = d;
 
709
                    size = style->pixelSizes + x;
 
710
                    FM_DEBUG("          best size so far: %3d (%d)", size->pixelSize, pixelSize);
 
711
                }
 
712
            }
 
713
 
 
714
            if (!size) {
 
715
                FM_DEBUG("          no size supports the script we want");
 
716
                continue;
 
717
            }
 
718
 
 
719
            if (style->bitmapScalable && ! (styleStrategy & QFont::PreferQuality) &&
 
720
                (distance * 10 / pixelSize) >= 2) {
 
721
                // the closest size is not close enough, go ahead and
 
722
                // use a bitmap scaled font
 
723
                size = style->pixelSize(0);
 
724
                px = pixelSize;
 
725
            } else {
 
726
                px = size->pixelSize;
 
727
            }
 
728
        }
 
729
 
 
730
#ifdef Q_WS_X11
 
731
        if (size) {
 
732
            encoding = findEncoding(script, styleStrategy, size, force_encoding_id);
 
733
            if (!encoding) size = 0;
 
734
        }
 
735
        if (! encoding) {
 
736
            FM_DEBUG("          foundry doesn't support the script we want");
 
737
            continue;
 
738
        }
 
739
#endif // Q_WS_X11
 
740
 
 
741
        unsigned int this_score = 0x0000;
 
742
        enum {
 
743
            PitchMismatch       = 0x4000,
 
744
            StyleMismatch       = 0x2000,
 
745
            BitmapScaledPenalty = 0x1000,
 
746
            EncodingMismatch    = 0x0002,
 
747
            XLFDPenalty         = 0x0001
 
748
        };
 
749
#ifdef Q_WS_X11
 
750
        if (encoding->encoding != -1) {
 
751
            this_score += XLFDPenalty;
 
752
            if (encoding->encoding != QFontPrivate::defaultEncodingID)
 
753
                this_score += EncodingMismatch;
 
754
        }
 
755
        if (pitch != '*') {
 
756
            if (!(pitch == 'm' && encoding->pitch == 'c') && pitch != encoding->pitch)
 
757
                this_score += PitchMismatch;
 
758
        }
 
759
#else
 
760
        if (pitch != '*') {
 
761
#if defined(Q_OS_MAC) && !defined(QWS)
 
762
            qt_mac_get_fixed_pitch(const_cast<QtFontFamily*>(family));
 
763
#endif
 
764
            if ((pitch == 'm' && !family->fixedPitch)
 
765
                || (pitch == 'p' && family->fixedPitch))
 
766
                this_score += PitchMismatch;
 
767
        }
 
768
#endif
 
769
        if (styleKey != style->key)
 
770
            this_score += StyleMismatch;
 
771
        if (!style->smoothScalable && px != size->pixelSize) // bitmap scaled
 
772
            this_score += BitmapScaledPenalty;
 
773
        if (px != pixelSize) // close, but not exact, size match
 
774
            this_score += qAbs(px - pixelSize);
 
775
 
 
776
        if (this_score < score) {
 
777
            FM_DEBUG("          found a match: score %x best score so far %x",
 
778
                     this_score, score);
 
779
 
 
780
            score = this_score;
 
781
            *best_foundry = foundry;
 
782
            *best_style = style;
 
783
            *best_size = size;
 
784
#ifdef Q_WS_X11
 
785
            *best_encoding = encoding;
 
786
#endif // Q_WS_X11
 
787
        } else {
 
788
            FM_DEBUG("          score %x no better than best %x", this_score, score);
 
789
        }
 
790
    }
 
791
 
 
792
    return score;
 
793
}
 
794
 
 
795
/*!
 
796
    \internal
 
797
*/
 
798
QFontEngine *
 
799
QFontDatabase::findFont(int script, const QFontPrivate *fp,
 
800
                        const QFontDef &request, int
 
801
#ifdef Q_WS_X11
 
802
                        force_encoding_id
 
803
#endif
 
804
    )
 
805
{
 
806
#ifdef Q_WS_X11
 
807
    Q_UNUSED(force_encoding_id);
 
808
#endif
 
809
 
 
810
    if (!privateDb()->count)
 
811
        initializeDb();
 
812
 
 
813
    QFontEngine *fe = 0;
 
814
    if (fp) {
 
815
        if (fp->rawMode) {
 
816
            fe = loadEngine(script, fp, request, 0, 0, 0
 
817
#ifdef Q_WS_X11
 
818
                            , 0, 0, false
 
819
#endif
 
820
#ifdef Q_WS_QWS
 
821
                            , 0
 
822
#endif
 
823
                );
 
824
 
 
825
            // if we fail to load the rawmode font, use a 12pixel box engine instead
 
826
            if (! fe) fe = new QFontEngineBox(12);
 
827
            return fe;
 
828
        }
 
829
 
 
830
        QFontCache::Key key(request, script
 
831
#if defined(Q_WS_X11)
 
832
                            , fp->screen
 
833
#endif
 
834
            );
 
835
        fe = QFontCache::instance->findEngine(key);
 
836
        if (fe)
 
837
            return fe;
 
838
    }
 
839
 
 
840
    QString family_name, foundry_name;
 
841
    QtFontStyle::Key styleKey;
 
842
    styleKey.style = request.style;
 
843
    styleKey.weight = request.weight;
 
844
    styleKey.stretch = request.stretch;
 
845
    char pitch = request.ignorePitch ? '*' : request.fixedPitch ? 'm' : 'p';
 
846
 
 
847
    parseFontName(request.family, foundry_name, family_name);
 
848
 
 
849
    FM_DEBUG("QFontDatabase::findFont\n"
 
850
             "  request:\n"
 
851
             "    family: %s [%s], script: %d\n"
 
852
             "    weight: %d, style: %d\n"
 
853
             "    stretch: %d\n"
 
854
             "    pixelSize: %d\n"
 
855
             "    pitch: %c",
 
856
             family_name.isEmpty() ? "-- first in script --" : family_name.toLatin1().constData(),
 
857
             foundry_name.isEmpty() ? "-- any --" : foundry_name.toLatin1().constData(),
 
858
             script, request.weight, request.style, request.stretch, request.pixelSize, pitch);
 
859
#if defined(FONT_MATCH_DEBUG) && defined(Q_WS_X11)
 
860
    if (force_encoding_id >= 0) {
 
861
        FM_DEBUG("    required encoding: %d", force_encoding_id);
 
862
    }
 
863
#endif
 
864
 
 
865
    if (qt_enable_test_font && request.family == QLatin1String("__Qt__Box__Engine__")) {
 
866
        fe = new QTestFontEngine(request.pixelSize);
 
867
        fe->fontDef = request;
 
868
    }
 
869
 
 
870
    if (!fe)
 
871
    {
 
872
        QtFontFamily *best_family = 0;
 
873
        QtFontFoundry *best_foundry = 0;
 
874
        QtFontStyle *best_style = 0;
 
875
        QtFontSize *best_size = 0;
 
876
#ifdef Q_WS_X11
 
877
        QtFontEncoding *best_encoding = 0;
 
878
#endif // Q_WS_X11
 
879
 
 
880
        unsigned int score = ~0u;
 
881
 
 
882
        load(family_name, script);
 
883
 
 
884
        QFontDatabasePrivate *db = privateDb();
 
885
        for (int x = 0; x < db->count; ++x) {
 
886
            QtFontFamily *try_family = db->families[x];
 
887
 
 
888
            if (!family_name.isEmpty()
 
889
                && ucstricmp(try_family->name, family_name) != 0
 
890
#ifdef Q_WS_WIN
 
891
                && ucstricmp(try_family->english_name, family_name) != 0
 
892
#endif
 
893
                )
 
894
                continue;
 
895
 
 
896
            if (family_name.isEmpty())
 
897
                load(try_family->name, script);
 
898
 
 
899
            uint score_adjust = 0;
 
900
 
 
901
            bool supported = false;
 
902
            for (int ws = 1; !supported && ws < WritingSystemsCount; ++ws) {
 
903
                if (scriptForWritingSystem[ws] != script)
 
904
                    continue;
 
905
                if (try_family->writingSystems[ws] & QtFontFamily::Supported)
 
906
                    supported = true;
 
907
            }
 
908
            if (!supported) {
 
909
                // family not supported in the script we want
 
910
                continue;
 
911
            }
 
912
 
 
913
            QtFontFoundry *try_foundry = 0;
 
914
            QtFontStyle *try_style = 0;
 
915
            QtFontSize *try_size = 0;
 
916
#ifdef Q_WS_X11
 
917
            QtFontEncoding *try_encoding = 0;
 
918
#endif // Q_WS_X11
 
919
 
 
920
            // as we know the script is supported, we can be sure
 
921
            // to find a matching font here.
 
922
            unsigned int newscore =
 
923
                bestFoundry(script, score, request.styleStrategy,
 
924
                            try_family, foundry_name, styleKey, request.pixelSize, pitch,
 
925
                            &try_foundry, &try_style, &try_size
 
926
#ifdef Q_WS_X11
 
927
                            , &try_encoding, force_encoding_id
 
928
#endif
 
929
                    );
 
930
            if (try_foundry == 0) {
 
931
                // the specific foundry was not found, so look for
 
932
                // any foundry matching our requirements
 
933
                newscore = bestFoundry(script, score, request.styleStrategy, try_family,
 
934
                                       QString(), styleKey, request.pixelSize,
 
935
                                       pitch, &try_foundry, &try_style, &try_size
 
936
#ifdef Q_WS_X11
 
937
                                       , &try_encoding, force_encoding_id
 
938
#endif
 
939
                    );
 
940
            }
 
941
            newscore += score_adjust;
 
942
 
 
943
            if (newscore < score) {
 
944
                score = newscore;
 
945
                best_family = try_family;
 
946
                best_foundry = try_foundry;
 
947
                best_style = try_style;
 
948
                best_size = try_size;
 
949
#ifdef Q_WS_X11
 
950
                best_encoding = try_encoding;
 
951
#endif // Q_WS_X11
 
952
            }
 
953
            if (newscore < 10) // xlfd instead of FT... just accept it
 
954
                break;
 
955
        }
 
956
 
 
957
        if (best_family != 0 && best_foundry != 0 && best_style != 0
 
958
#ifdef Q_WS_X11
 
959
            && best_size != 0 && best_encoding != 0
 
960
#endif
 
961
            ) {
 
962
            FM_DEBUG("  BEST:\n"
 
963
                     "    family: %s [%s]\n"
 
964
                     "    weight: %d, style: %d\n"
 
965
                     "    stretch: %d\n"
 
966
                     "    pixelSize: %d\n"
 
967
                     "    pitch: %c\n"
 
968
                     "    encoding: %d\n",
 
969
                     best_family->name.toLatin1().constData(),
 
970
                     best_foundry->name.isEmpty() ? "-- none --" : best_foundry->name.toLatin1().constData(),
 
971
                     best_style->key.weight, best_style->key.style,
 
972
                     best_style->key.stretch, best_size ? best_size->pixelSize : 0xffff,
 
973
#ifdef Q_WS_X11
 
974
                     best_encoding->pitch, best_encoding->encoding
 
975
#else
 
976
                     'p', 0
 
977
#endif
 
978
                );
 
979
 
 
980
            fe = loadEngine(script, fp, request, best_family, best_foundry, best_style
 
981
#ifdef Q_WS_X11
 
982
                            , best_size, best_encoding, (force_encoding_id >= 0)
 
983
#endif
 
984
#ifdef Q_WS_QWS
 
985
                            , best_size
 
986
#endif
 
987
                );
 
988
        } else {
 
989
            FM_DEBUG("  NO MATCH FOUND\n");
 
990
        }
 
991
        if (fe) {
 
992
            fe->fontDef.family = best_family->name;
 
993
            if (! best_foundry->name.isEmpty()) {
 
994
                fe->fontDef.family += QString::fromLatin1(" [");
 
995
                fe->fontDef.family += best_foundry->name;
 
996
                fe->fontDef.family += QString::fromLatin1("]");
 
997
            }
 
998
 
 
999
            if (best_style->smoothScalable)
 
1000
                fe->fontDef.pixelSize = request.pixelSize;
 
1001
            else if ((best_style->bitmapScalable && (request.styleStrategy & QFont::PreferMatch)))
 
1002
                fe->fontDef.pixelSize = request.pixelSize;
 
1003
            else
 
1004
                fe->fontDef.pixelSize = best_size->pixelSize;
 
1005
 
 
1006
            fe->fontDef.styleHint     = request.styleHint;
 
1007
            fe->fontDef.styleStrategy = request.styleStrategy;
 
1008
 
 
1009
            fe->fontDef.weight        = best_style->key.weight;
 
1010
            fe->fontDef.style         = best_style->key.style;
 
1011
            fe->fontDef.fixedPitch    = best_family->fixedPitch;
 
1012
            fe->fontDef.stretch       = best_style->key.stretch;
 
1013
            fe->fontDef.ignorePitch   = false;
 
1014
        }
 
1015
    }
 
1016
 
 
1017
    if (fe) {
 
1018
        if (fp) {
 
1019
            QFontDef def = request;
 
1020
            if (def.family.isEmpty()) {
 
1021
                def.family = fp->request.family;
 
1022
                def.family = def.family.left(def.family.indexOf(','));
 
1023
            }
 
1024
            QFontCache::Key key(def, script
 
1025
#if defined(Q_WS_X11)
 
1026
                                , fp->screen
 
1027
#endif
 
1028
                );
 
1029
            QFontCache::instance->insertEngine(key, fe);
 
1030
        }
 
1031
 
 
1032
#if defined(Q_WS_X11) && !defined(QT_NO_FONTCONFIG)
 
1033
        if (scriptRequiresOpenType(script)) {
 
1034
            QOpenType *ot = fe->openType();
 
1035
            if (!ot || !ot->supportsScript(script)) {
 
1036
                FM_DEBUG("  OpenType support missing for script");
 
1037
                fe = 0;
 
1038
            }
 
1039
        }
 
1040
#endif
 
1041
    }
 
1042
 
 
1043
    if (!fe) {
 
1044
        if (!request.family.isEmpty())
 
1045
            return 0;
 
1046
 
 
1047
        FM_DEBUG("returning box engine");
 
1048
 
 
1049
        fe = new QFontEngineBox(request.pixelSize);
 
1050
 
 
1051
        if (fp) {
 
1052
            QFontCache::Key key(request, script
 
1053
#if defined(Q_WS_X11)
 
1054
                                , fp->screen
 
1055
#endif
 
1056
                );
 
1057
            QFontCache::instance->insertEngine(key, fe);
 
1058
        }
 
1059
    }
 
1060
 
 
1061
    if (fp) {
 
1062
#if defined(Q_WS_X11)
 
1063
        fe->fontDef.pointSize = qt_pointSize(fe->fontDef.pixelSize, fp->dpi);
 
1064
#elif defined(Q_WS_WIN)
 
1065
        fe->fontDef.pointSize = qreal(fe->fontDef.pixelSize) * 72.0
 
1066
                                / GetDeviceCaps(shared_dc,LOGPIXELSY);
 
1067
#elif defined(Q_WS_MAC)
 
1068
        fe->fontDef.pointSize = qt_mac_pointsize(fe->fontDef, fp->dpi);
 
1069
#else
 
1070
        fe->fontDef.pointSize = qreal(fe->fontDef.pixelSize); //####int(double(fe->fontDef.pixelSize) * 72.0 / 96.0);
 
1071
#endif
 
1072
    } else {
 
1073
        fe->fontDef.pointSize = request.pointSize;
 
1074
    }
 
1075
 
 
1076
    return fe;
 
1077
}
 
1078
 
 
1079
 
 
1080
static QString styleString(int weight, QFont::Style style)
 
1081
{
 
1082
    QString result;
 
1083
    if (weight >= QFont::Black)
 
1084
        result = "Black";
 
1085
    else if (weight >= QFont::Bold)
 
1086
        result = "Bold";
 
1087
    else if (weight >= QFont::DemiBold)
 
1088
        result = "Demi Bold";
 
1089
    else if (weight < QFont::Normal)
 
1090
        result = "Light";
 
1091
 
 
1092
    if (style == QFont::StyleItalic)
 
1093
        result += " Italic";
 
1094
    else if (style == QFont::StyleOblique)
 
1095
        result += " Oblique";
 
1096
 
 
1097
    if (result.isEmpty())
 
1098
        result = "Normal";
 
1099
 
 
1100
    return result.simplified();
 
1101
}
 
1102
 
 
1103
/*!
 
1104
    Returns a string that describes the style of the font \a f. For
 
1105
    example, "Bold Italic", "Bold", "Italic" or "Normal". An empty
 
1106
    string may be returned.
 
1107
*/
 
1108
QString QFontDatabase::styleString(const QFont &f)
 
1109
{
 
1110
    return ::styleString(f.weight(), f.style());
 
1111
}
 
1112
 
 
1113
 
 
1114
/*!
 
1115
    \class QFontDatabase qfontdatabase.h
 
1116
    \brief The QFontDatabase class provides information about the fonts available in the underlying window system.
 
1117
 
 
1118
    \ingroup environment
 
1119
    \ingroup multimedia
 
1120
 
 
1121
    The most common uses of this class are to query the database for
 
1122
    the list of font families() and for the pointSizes() and styles()
 
1123
    that are available for each family. An alternative to pointSizes()
 
1124
    is smoothSizes() which returns the sizes at which a given family
 
1125
    and style will look attractive.
 
1126
 
 
1127
    If the font family is available from two or more foundries the
 
1128
    foundry name is included in the family name, e.g. "Helvetica
 
1129
    [Adobe]" and "Helvetica [Cronyx]". When you specify a family you
 
1130
    can either use the old hyphenated Qt 2.x "foundry-family" format,
 
1131
    e.g. "Cronyx-Helvetica", or the new bracketed Qt 3.x "family
 
1132
    [foundry]" format e.g. "Helvetica [Cronyx]". If the family has a
 
1133
    foundry it is always returned, e.g. by families(), using the
 
1134
    bracketed format.
 
1135
 
 
1136
    The font() function returns a QFont given a family, style and
 
1137
    point size.
 
1138
 
 
1139
    A family and style combination can be checked to see if it is
 
1140
    italic() or bold(), and to retrieve its weight(). Similarly we can
 
1141
    call isBitmapScalable(), isSmoothlyScalable(), isScalable() and
 
1142
    isFixedPitch().
 
1143
 
 
1144
    Use the styleString() to obtain a text version of a style.
 
1145
 
 
1146
    The QFontDatabase class also supports some static functions, for
 
1147
    example, standardSizes(). You can retrieve the description of a
 
1148
    writing system using writingSystemName(), and a sample of
 
1149
    characters in a writing system with writingSystemSample().
 
1150
 
 
1151
    Example:
 
1152
\code
 
1153
#include <qapplication.h>
 
1154
#include <qfontdatabase.h>
 
1155
 
 
1156
int main(int argc, char **argv)
 
1157
{
 
1158
    QApplication app(argc, argv);
 
1159
    QFontDatabase fdb;
 
1160
    QStringList families = fdb.families();
 
1161
    for (QStringList::Iterator f = families.begin(); f != families.end(); ++f) {
 
1162
        QString family = *f;
 
1163
        qDebug(family);
 
1164
        QStringList styles = fdb.styles(family);
 
1165
        for (QStringList::Iterator s = styles.begin(); s != styles.end(); ++s) {
 
1166
            QString style = *s;
 
1167
            QString dstyle = "\t" + style + " (";
 
1168
            QList<int> smoothies = fdb.smoothSizes(family, style);
 
1169
            for (QList<int>::Iterator points = smoothies.begin();
 
1170
                  points != smoothies.end(); ++points) {
 
1171
                dstyle += QString::number(*points) + " ";
 
1172
            }
 
1173
            dstyle = dstyle.left(dstyle.length() - 1) + ")";
 
1174
            qDebug(dstyle);
 
1175
        }
 
1176
    }
 
1177
    return 0;
 
1178
}
 
1179
\endcode
 
1180
    This example gets the list of font families, then the list of
 
1181
    styles for each family and the point sizes that are available for
 
1182
    each family/style combination.
 
1183
*/
 
1184
 
 
1185
/*!
 
1186
    Creates a font database object.
 
1187
*/
 
1188
QFontDatabase::QFontDatabase()
 
1189
{
 
1190
    createDatabase();
 
1191
 
 
1192
    d = privateDb();
 
1193
}
 
1194
 
 
1195
/*!
 
1196
    \enum QFontDatabase::WritingSystem
 
1197
 
 
1198
    \value Any
 
1199
    \value Latin
 
1200
    \value Greek
 
1201
    \value Cyrillic
 
1202
    \value Armenian
 
1203
    \value Hebrew
 
1204
    \value Arabic
 
1205
    \value Syriac
 
1206
    \value Thaana
 
1207
    \value Devanagari
 
1208
    \value Bengali
 
1209
    \value Gurmukhi
 
1210
    \value Gujarati
 
1211
    \value Oriya
 
1212
    \value Tamil
 
1213
    \value Telugu
 
1214
    \value Kannada
 
1215
    \value Malayalam
 
1216
    \value Sinhala
 
1217
    \value Thai
 
1218
    \value Lao
 
1219
    \value Tibetan
 
1220
    \value Myanmar
 
1221
    \value Georgian
 
1222
    \value Khmer
 
1223
    \value SimplifiedChinese
 
1224
    \value TraditionalChinese
 
1225
    \value Japanese
 
1226
    \value Korean
 
1227
    \value Vietnamese
 
1228
    \value Other
 
1229
 
 
1230
    \omitvalue WritingSystemsCount
 
1231
*/
 
1232
 
 
1233
/*!
 
1234
    Returns a sorted list of the available writing systems. This is
 
1235
    list generated from information about all installed fonts on the
 
1236
    system.
 
1237
 
 
1238
    \sa families()
 
1239
*/
 
1240
QList<QFontDatabase::WritingSystem> QFontDatabase::writingSystems() const
 
1241
{
 
1242
    load();
 
1243
 
 
1244
    QList<WritingSystem> list;
 
1245
    for (int i = 0; i < d->count; ++i) {
 
1246
        QtFontFamily *family = d->families[i];
 
1247
        if (family->count == 0)
 
1248
            continue;
 
1249
        for (int x = Latin; x < WritingSystemsCount; ++x) {
 
1250
            const WritingSystem writingSystem = WritingSystem(x);
 
1251
            if (!family->writingSystems[writingSystem])
 
1252
                continue;
 
1253
            if (!list.contains(writingSystem))
 
1254
                list.append(writingSystem);
 
1255
        }
 
1256
    }
 
1257
    qSort(list);
 
1258
    return list;
 
1259
}
 
1260
 
 
1261
 
 
1262
/*!
 
1263
    Returns a sorted list of the available font families which support
 
1264
    the \a writingSystem.
 
1265
 
 
1266
    If a family exists in several foundries, the returned name for
 
1267
    that font is in the form "family [foundry]". Examples: "Times
 
1268
    [Adobe]", "Times [Cronyx]", "Palatino".
 
1269
 
 
1270
    \sa writingSystems()
 
1271
*/
 
1272
QStringList QFontDatabase::families(WritingSystem writingSystem) const
 
1273
{
 
1274
    load();
 
1275
 
 
1276
    QStringList flist;
 
1277
    for (int i = 0; i < d->count; i++) {
 
1278
        QtFontFamily *f = d->families[i];
 
1279
        if (f->count == 0)
 
1280
            continue;
 
1281
        if (writingSystem != Any && (f->writingSystems[writingSystem] != QtFontFamily::Supported))
 
1282
            continue;
 
1283
        if (f->count == 1) {
 
1284
            flist.append(f->name);
 
1285
        } else {
 
1286
            for (int j = 0; j < f->count; j++) {
 
1287
                QString str = f->name;
 
1288
                QString foundry = f->foundries[j]->name;
 
1289
                if (!foundry.isEmpty()) {
 
1290
                    str += " [";
 
1291
                    str += foundry;
 
1292
                    str += "]";
 
1293
                }
 
1294
                flist.append(str);
 
1295
            }
 
1296
        }
 
1297
    }
 
1298
    return flist;
 
1299
}
 
1300
 
 
1301
/*!
 
1302
    Returns a list of the styles available for the font family \a
 
1303
    family. Some example styles: "Light", "Light Italic", "Bold",
 
1304
    "Oblique", "Demi". The list may be empty.
 
1305
 
 
1306
    \sa families()
 
1307
*/
 
1308
QStringList QFontDatabase::styles(const QString &family) const
 
1309
{
 
1310
    QString familyName, foundryName;
 
1311
    parseFontName(family, foundryName, familyName);
 
1312
 
 
1313
    load(familyName);
 
1314
 
 
1315
    QStringList l;
 
1316
    QtFontFamily *f = d->family(familyName);
 
1317
    if (!f)
 
1318
        return l;
 
1319
 
 
1320
    QtFontFoundry allStyles(foundryName);
 
1321
    for (int j = 0; j < f->count; j++) {
 
1322
        QtFontFoundry *foundry = f->foundries[j];
 
1323
        if (foundryName.isEmpty() || ucstricmp(foundry->name, foundryName) == 0) {
 
1324
            for (int k = 0; k < foundry->count; k++) {
 
1325
                QtFontStyle::Key ke(foundry->styles[k]->key);
 
1326
                ke.stretch = 0;
 
1327
                allStyles.style(ke, true);
 
1328
            }
 
1329
        }
 
1330
    }
 
1331
 
 
1332
    for (int i = 0; i < allStyles.count; i++)
 
1333
        l.append(::styleString(allStyles.styles[i]->key.weight, (QFont::Style)allStyles.styles[i]->key.style));
 
1334
    return l;
 
1335
}
 
1336
 
 
1337
/*!
 
1338
    Returns true if the font that has family \a family and style \a
 
1339
    style is fixed pitch; otherwise returns false.
 
1340
*/
 
1341
 
 
1342
bool QFontDatabase::isFixedPitch(const QString &family,
 
1343
                                 const QString &style) const
 
1344
{
 
1345
    Q_UNUSED(style);
 
1346
 
 
1347
    QString familyName, foundryName;
 
1348
    parseFontName(family, foundryName, familyName);
 
1349
 
 
1350
    load(familyName);
 
1351
 
 
1352
    QtFontFamily *f = d->family(familyName);
 
1353
#if defined(Q_OS_MAC) && !defined(QWS)
 
1354
    qt_mac_get_fixed_pitch(f);
 
1355
#endif
 
1356
    return (f && f->fixedPitch);
 
1357
}
 
1358
 
 
1359
/*!
 
1360
    Returns true if the font that has family \a family and style \a
 
1361
    style is a scalable bitmap font; otherwise returns false. Scaling
 
1362
    a bitmap font usually produces an unattractive hardly readable
 
1363
    result, because the pixels of the font are scaled. If you need to
 
1364
    scale a bitmap font it is better to scale it to one of the fixed
 
1365
    sizes returned by smoothSizes().
 
1366
 
 
1367
    \sa isScalable(), isSmoothlyScalable()
 
1368
*/
 
1369
bool QFontDatabase::isBitmapScalable(const QString &family,
 
1370
                                      const QString &style) const
 
1371
{
 
1372
    bool bitmapScalable = false;
 
1373
    QString familyName, foundryName;
 
1374
    parseFontName(family, foundryName, familyName);
 
1375
 
 
1376
    load(familyName);
 
1377
 
 
1378
    QtFontStyle::Key styleKey(style);
 
1379
 
 
1380
    QtFontFamily *f = d->family(familyName);
 
1381
    if (!f) return bitmapScalable;
 
1382
 
 
1383
    for (int j = 0; j < f->count; j++) {
 
1384
        QtFontFoundry *foundry = f->foundries[j];
 
1385
        if (foundryName.isEmpty() || ucstricmp(foundry->name, foundryName) == 0) {
 
1386
            for (int k = 0; k < foundry->count; k++)
 
1387
                if ((style.isEmpty() || foundry->styles[k]->key == styleKey)
 
1388
                    && foundry->styles[k]->bitmapScalable && !foundry->styles[k]->smoothScalable) {
 
1389
                    bitmapScalable = true;
 
1390
                    goto end;
 
1391
                }
 
1392
        }
 
1393
    }
 
1394
 end:
 
1395
    return bitmapScalable;
 
1396
}
 
1397
 
 
1398
 
 
1399
/*!
 
1400
    Returns true if the font that has family \a family and style \a
 
1401
    style is smoothly scalable; otherwise returns false. If this
 
1402
    function returns true, it's safe to scale this font to any size,
 
1403
    and the result will always look attractive.
 
1404
 
 
1405
    \sa isScalable(), isBitmapScalable()
 
1406
*/
 
1407
bool  QFontDatabase::isSmoothlyScalable(const QString &family,
 
1408
                                         const QString &style) const
 
1409
{
 
1410
    bool smoothScalable = false;
 
1411
    QString familyName, foundryName;
 
1412
    parseFontName(family, foundryName, familyName);
 
1413
 
 
1414
    load(familyName);
 
1415
 
 
1416
    QtFontStyle::Key styleKey(style);
 
1417
 
 
1418
    QtFontFamily *f = d->family(familyName);
 
1419
    if (!f) return smoothScalable;
 
1420
 
 
1421
    for (int j = 0; j < f->count; j++) {
 
1422
        QtFontFoundry *foundry = f->foundries[j];
 
1423
        if (foundryName.isEmpty() || ucstricmp(foundry->name, foundryName) == 0) {
 
1424
            for (int k = 0; k < foundry->count; k++)
 
1425
                if ((style.isEmpty() || foundry->styles[k]->key == styleKey) && foundry->styles[k]->smoothScalable) {
 
1426
                    smoothScalable = true;
 
1427
                    goto end;
 
1428
                }
 
1429
        }
 
1430
    }
 
1431
 end:
 
1432
    return smoothScalable;
 
1433
}
 
1434
 
 
1435
/*!
 
1436
    Returns true if the font that has family \a family and style \a
 
1437
    style is scalable; otherwise returns false.
 
1438
 
 
1439
    \sa isBitmapScalable(), isSmoothlyScalable()
 
1440
*/
 
1441
bool  QFontDatabase::isScalable(const QString &family,
 
1442
                                 const QString &style) const
 
1443
{
 
1444
    if (isSmoothlyScalable(family, style))
 
1445
        return true;
 
1446
 
 
1447
    return isBitmapScalable(family, style);
 
1448
}
 
1449
 
 
1450
 
 
1451
/*!
 
1452
    Returns a list of the point sizes available for the font that has
 
1453
    family \a family and style \a style. The list may be empty.
 
1454
 
 
1455
    \sa smoothSizes(), standardSizes()
 
1456
*/
 
1457
QList<int> QFontDatabase::pointSizes(const QString &family,
 
1458
                                           const QString &style)
 
1459
{
 
1460
#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
 
1461
    // windows and macosx are always smoothly scalable
 
1462
    Q_UNUSED(family);
 
1463
    Q_UNUSED(style);
 
1464
    return standardSizes();
 
1465
#else
 
1466
    bool smoothScalable = false;
 
1467
    QString familyName, foundryName;
 
1468
    parseFontName(family, foundryName, familyName);
 
1469
 
 
1470
    load(familyName);
 
1471
 
 
1472
    QtFontStyle::Key styleKey(style);
 
1473
 
 
1474
    QList<int> sizes;
 
1475
 
 
1476
    QtFontFamily *fam = d->family(familyName);
 
1477
    if (!fam) return sizes;
 
1478
 
 
1479
 
 
1480
#ifdef Q_WS_X11
 
1481
    int dpi = QX11Info::appDpiY();
 
1482
#else
 
1483
    const int dpi = 72; // embedded
 
1484
#endif
 
1485
 
 
1486
    for (int j = 0; j < fam->count; j++) {
 
1487
        QtFontFoundry *foundry = fam->foundries[j];
 
1488
        if (foundryName.isEmpty() || ucstricmp(foundry->name, foundryName) == 0) {
 
1489
            QtFontStyle *style = foundry->style(styleKey);
 
1490
            if (!style) continue;
 
1491
 
 
1492
            if (style->smoothScalable) {
 
1493
                smoothScalable = true;
 
1494
                goto end;
 
1495
            }
 
1496
            for (int l = 0; l < style->count; l++) {
 
1497
                const QtFontSize *size = style->pixelSizes + l;
 
1498
 
 
1499
                if (size->pixelSize != 0 && size->pixelSize != USHRT_MAX) {
 
1500
                    const uint pointSize = qRound(size->pixelSize * dpi / 72.);
 
1501
                    if (! sizes.contains(pointSize))
 
1502
                        sizes.append(pointSize);
 
1503
                }
 
1504
            }
 
1505
        }
 
1506
    }
 
1507
 end:
 
1508
    if (smoothScalable)
 
1509
        return standardSizes();
 
1510
 
 
1511
    qSort(sizes);
 
1512
    return sizes;
 
1513
#endif
 
1514
}
 
1515
 
 
1516
/*!
 
1517
    Returns a QFont object that has family \a family, style \a style
 
1518
    and point size \a pointSize. If no matching font could be created,
 
1519
    a QFont object that uses the application's default font is
 
1520
    returned.
 
1521
*/
 
1522
QFont QFontDatabase::font(const QString &family, const QString &style,
 
1523
                           int pointSize) const
 
1524
{
 
1525
    QString familyName, foundryName;
 
1526
    parseFontName(family, foundryName, familyName);
 
1527
 
 
1528
    load(familyName);
 
1529
 
 
1530
    QtFontFoundry allStyles(foundryName);
 
1531
    QtFontFamily *f = d->family(familyName);
 
1532
    if (!f) return QApplication::font();
 
1533
 
 
1534
    for (int j = 0; j < f->count; j++) {
 
1535
        QtFontFoundry *foundry = f->foundries[j];
 
1536
        if (foundryName.isEmpty() || ucstricmp(foundry->name, foundryName) == 0) {
 
1537
            for (int k = 0; k < foundry->count; k++)
 
1538
                allStyles.style(foundry->styles[k]->key, true);
 
1539
        }
 
1540
    }
 
1541
 
 
1542
    QtFontStyle::Key styleKey(style);
 
1543
    QtFontStyle *s = bestStyle(&allStyles, styleKey);
 
1544
 
 
1545
    if (!s) // no styles found?
 
1546
        return QApplication::font();
 
1547
    QFont fnt(family, pointSize, s->key.weight);
 
1548
    fnt.setStyle((QFont::Style)s->key.style);
 
1549
    return fnt;
 
1550
}
 
1551
 
 
1552
 
 
1553
/*!
 
1554
    Returns the point sizes of a font that has family \a family and
 
1555
    style \a style that will look attractive. The list may be empty.
 
1556
    For non-scalable fonts and bitmap scalable fonts, this function
 
1557
    is equivalent to pointSizes().
 
1558
 
 
1559
  \sa pointSizes(), standardSizes()
 
1560
*/
 
1561
QList<int> QFontDatabase::smoothSizes(const QString &family,
 
1562
                                            const QString &style)
 
1563
{
 
1564
#ifdef Q_WS_WIN
 
1565
    Q_UNUSED(family);
 
1566
    Q_UNUSED(style);
 
1567
    return QFontDatabase::standardSizes();
 
1568
#else
 
1569
    bool smoothScalable = false;
 
1570
    QString familyName, foundryName;
 
1571
    parseFontName(family, foundryName, familyName);
 
1572
 
 
1573
    load(familyName);
 
1574
 
 
1575
    QtFontStyle::Key styleKey(style);
 
1576
 
 
1577
    QList<int> sizes;
 
1578
 
 
1579
    QtFontFamily *fam = d->family(familyName);
 
1580
    if (!fam)
 
1581
        return sizes;
 
1582
 
 
1583
#ifdef Q_WS_X11
 
1584
    int dpi = QX11Info::appDpiY();
 
1585
#else
 
1586
    const int dpi = 72; // embedded
 
1587
#endif
 
1588
    for (int j = 0; j < fam->count; j++) {
 
1589
        QtFontFoundry *foundry = fam->foundries[j];
 
1590
        if (foundryName.isEmpty() ||
 
1591
             ucstricmp(foundry->name, foundryName) == 0) {
 
1592
            QtFontStyle *style = foundry->style(styleKey);
 
1593
            if (!style) continue;
 
1594
 
 
1595
            if (style->smoothScalable) {
 
1596
                smoothScalable = true;
 
1597
                goto end;
 
1598
            }
 
1599
            for (int l = 0; l < style->count; l++) {
 
1600
                const QtFontSize *size = style->pixelSizes + l;
 
1601
 
 
1602
                if (size->pixelSize != 0 && size->pixelSize != USHRT_MAX) {
 
1603
                    const uint pointSize = qRound(size->pixelSize * dpi / 72.);
 
1604
                    if (! sizes.contains(pointSize))
 
1605
                        sizes.append(pointSize);
 
1606
                }
 
1607
            }
 
1608
        }
 
1609
    }
 
1610
 end:
 
1611
    if (smoothScalable)
 
1612
        return QFontDatabase::standardSizes();
 
1613
 
 
1614
    qSort(sizes);
 
1615
    return sizes;
 
1616
#endif
 
1617
}
 
1618
 
 
1619
 
 
1620
/*!
 
1621
    Returns a list of standard font sizes.
 
1622
 
 
1623
    \sa smoothSizes(), pointSizes()
 
1624
*/
 
1625
QList<int> QFontDatabase::standardSizes()
 
1626
{
 
1627
    QList<int> ret;
 
1628
    static const unsigned short standard[] =
 
1629
        { 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72, 0 };
 
1630
    const unsigned short *sizes = standard;
 
1631
    while (*sizes) ret << *sizes++;
 
1632
    return ret;
 
1633
}
 
1634
 
 
1635
 
 
1636
/*!
 
1637
    Returns true if the font that has family \a family and style \a
 
1638
    style is italic; otherwise returns false.
 
1639
 
 
1640
    \sa weight(), bold()
 
1641
*/
 
1642
bool QFontDatabase::italic(const QString &family, const QString &style) const
 
1643
{
 
1644
    QString familyName, foundryName;
 
1645
    parseFontName(family, foundryName, familyName);
 
1646
 
 
1647
    load(familyName);
 
1648
 
 
1649
    QtFontFoundry allStyles(foundryName);
 
1650
    QtFontFamily *f = d->family(familyName);
 
1651
    if (!f) return false;
 
1652
 
 
1653
    for (int j = 0; j < f->count; j++) {
 
1654
        QtFontFoundry *foundry = f->foundries[j];
 
1655
        if (foundryName.isEmpty() || ucstricmp(foundry->name, foundryName) == 0) {
 
1656
            for (int k = 0; k < foundry->count; k++)
 
1657
                allStyles.style(foundry->styles[k]->key, true);
 
1658
        }
 
1659
    }
 
1660
 
 
1661
    QtFontStyle::Key styleKey(style);
 
1662
    QtFontStyle *s = allStyles.style(styleKey);
 
1663
    return s && s->key.style == QFont::StyleItalic;
 
1664
}
 
1665
 
 
1666
 
 
1667
/*!
 
1668
    Returns true if the font that has family \a family and style \a
 
1669
    style is bold; otherwise returns false.
 
1670
 
 
1671
    \sa italic(), weight()
 
1672
*/
 
1673
bool QFontDatabase::bold(const QString &family,
 
1674
                          const QString &style) const
 
1675
{
 
1676
    QString familyName, foundryName;
 
1677
    parseFontName(family, foundryName, familyName);
 
1678
 
 
1679
    load(familyName);
 
1680
 
 
1681
    QtFontFoundry allStyles(foundryName);
 
1682
    QtFontFamily *f = d->family(familyName);
 
1683
    if (!f) return false;
 
1684
 
 
1685
    for (int j = 0; j < f->count; j++) {
 
1686
        QtFontFoundry *foundry = f->foundries[j];
 
1687
        if (foundryName.isEmpty() ||
 
1688
             ucstricmp(foundry->name, foundryName) == 0) {
 
1689
            for (int k = 0; k < foundry->count; k++)
 
1690
                allStyles.style(foundry->styles[k]->key, true);
 
1691
        }
 
1692
    }
 
1693
 
 
1694
    QtFontStyle::Key styleKey(style);
 
1695
    QtFontStyle *s = allStyles.style(styleKey);
 
1696
    return s && s->key.weight >= QFont::Bold;
 
1697
}
 
1698
 
 
1699
 
 
1700
/*!
 
1701
    Returns the weight of the font that has family \a family and style
 
1702
    \a style. If there is no such family and style combination,
 
1703
    returns -1.
 
1704
 
 
1705
    \sa italic(), bold()
 
1706
*/
 
1707
int QFontDatabase::weight(const QString &family,
 
1708
                           const QString &style) const
 
1709
{
 
1710
    QString familyName, foundryName;
 
1711
    parseFontName(family, foundryName, familyName);
 
1712
 
 
1713
    load(familyName);
 
1714
 
 
1715
    QtFontFoundry allStyles(foundryName);
 
1716
    QtFontFamily *f = d->family(familyName);
 
1717
    if (!f) return -1;
 
1718
 
 
1719
    for (int j = 0; j < f->count; j++) {
 
1720
        QtFontFoundry *foundry = f->foundries[j];
 
1721
        if (foundryName.isEmpty() ||
 
1722
             ucstricmp(foundry->name, foundryName) == 0) {
 
1723
            for (int k = 0; k < foundry->count; k++)
 
1724
                allStyles.style(foundry->styles[k]->key, true);
 
1725
        }
 
1726
    }
 
1727
 
 
1728
    QtFontStyle::Key styleKey(style);
 
1729
    QtFontStyle *s = allStyles.style(styleKey);
 
1730
    return s ? s->key.weight : -1;
 
1731
}
 
1732
 
 
1733
 
 
1734
/*!
 
1735
    Returns the names the \a writingSystem (e.g. for displaying to the
 
1736
    user in a dialog).
 
1737
*/
 
1738
QString QFontDatabase::writingSystemName(WritingSystem writingSystem)
 
1739
{
 
1740
    const char *name = 0;
 
1741
    switch (writingSystem) {
 
1742
    case Any:
 
1743
        name = "Any";
 
1744
        break;
 
1745
    case Latin:
 
1746
        name = "Latin";
 
1747
        break;
 
1748
    case Greek:
 
1749
        name = "Greek";
 
1750
        break;
 
1751
    case Cyrillic:
 
1752
        name = "Cyrillic";
 
1753
        break;
 
1754
    case Armenian:
 
1755
        name = "Armenian";
 
1756
        break;
 
1757
    case Hebrew:
 
1758
        name = "Hebrew";
 
1759
        break;
 
1760
    case Arabic:
 
1761
        name = "Arabic";
 
1762
        break;
 
1763
    case Syriac:
 
1764
        name = "Syriac";
 
1765
        break;
 
1766
    case Thaana:
 
1767
        name = "Thaana";
 
1768
        break;
 
1769
    case Devanagari:
 
1770
        name = "Devanagari";
 
1771
        break;
 
1772
    case Bengali:
 
1773
        name = "Bengali";
 
1774
        break;
 
1775
    case Gurmukhi:
 
1776
        name = "Gurmukhi";
 
1777
        break;
 
1778
    case Gujarati:
 
1779
        name = "Gujarati";
 
1780
        break;
 
1781
    case Oriya:
 
1782
        name = "Oriya";
 
1783
        break;
 
1784
    case Tamil:
 
1785
        name = "Tamil";
 
1786
        break;
 
1787
    case Telugu:
 
1788
        name = "Telugu";
 
1789
        break;
 
1790
    case Kannada:
 
1791
        name = "Kannada";
 
1792
        break;
 
1793
    case Malayalam:
 
1794
        name = "Malayalam";
 
1795
        break;
 
1796
    case Sinhala:
 
1797
        name = "Sinhala";
 
1798
        break;
 
1799
    case Thai:
 
1800
        name = "Thai";
 
1801
        break;
 
1802
    case Lao:
 
1803
        name = "Lao";
 
1804
        break;
 
1805
    case Tibetan:
 
1806
        name = "Tibetan";
 
1807
        break;
 
1808
    case Myanmar:
 
1809
        name = "Myanmar";
 
1810
        break;
 
1811
    case Georgian:
 
1812
        name = "Georgian";
 
1813
        break;
 
1814
    case Khmer:
 
1815
        name = "Khmer";
 
1816
        break;
 
1817
    case SimplifiedChinese:
 
1818
        name = "Simplified Chinese";
 
1819
        break;
 
1820
    case TraditionalChinese:
 
1821
        name = "Traditional Chinese";
 
1822
        break;
 
1823
    case Japanese:
 
1824
        name = "Japanese";
 
1825
        break;
 
1826
    case Korean:
 
1827
        name = "Korean";
 
1828
        break;
 
1829
    case Vietnamese:
 
1830
        name = "Vietnamese";
 
1831
        break;
 
1832
    case Other:
 
1833
        name = "Other";
 
1834
        break;
 
1835
    default:
 
1836
        Q_ASSERT_X(false, "QFontDatabase::writingSystemName", "invalid 'writingSystem' parameter");
 
1837
        break;
 
1838
    }
 
1839
    return qApp ? qApp->translate("QFont", name) : QString::fromLatin1(name);
 
1840
}
 
1841
 
 
1842
 
 
1843
/*!
 
1844
    Returns a string with sample characters from \a writingSystem.
 
1845
*/
 
1846
QString QFontDatabase::writingSystemSample(WritingSystem writingSystem)
 
1847
{
 
1848
    QString sample = QString::fromLatin1("AaBb");
 
1849
    switch (writingSystem) {
 
1850
    case Any:
 
1851
    case Other:
 
1852
        // show only ascii characters
 
1853
        sample += "YyzZ";
 
1854
        break;
 
1855
    case Latin:
 
1856
        // This is cheating... we only show latin-1 characters so that we don't
 
1857
        // end up loading lots of fonts - at least on X11...
 
1858
        sample += QChar(0x00C3);
 
1859
        sample += QChar(0x00E1);
 
1860
        sample += "Zz";
 
1861
        break;
 
1862
    case Greek:
 
1863
        sample += QChar(0x0393);
 
1864
        sample += QChar(0x03B1);
 
1865
        sample += QChar(0x03A9);
 
1866
        sample += QChar(0x03C9);
 
1867
        break;
 
1868
    case Cyrillic:
 
1869
        sample += QChar(0x0414);
 
1870
        sample += QChar(0x0434);
 
1871
        sample += QChar(0x0436);
 
1872
        sample += QChar(0x0402);
 
1873
        break;
 
1874
    case Armenian:
 
1875
        sample += QChar(0x053f);
 
1876
        sample += QChar(0x054f);
 
1877
        sample += QChar(0x056f);
 
1878
        sample += QChar(0x057f);
 
1879
        break;
 
1880
    case Hebrew:
 
1881
        sample += QChar(0x05D0);
 
1882
        sample += QChar(0x05D1);
 
1883
        sample += QChar(0x05D2);
 
1884
        sample += QChar(0x05D3);
 
1885
        break;
 
1886
    case Arabic:
 
1887
        sample += QChar(0x0628);
 
1888
        sample += QChar(0x0629);
 
1889
        sample += QChar(0x062A);
 
1890
        sample += QChar(0x063A);
 
1891
        break;
 
1892
    case Syriac:
 
1893
        sample += QChar(0x0715);
 
1894
        sample += QChar(0x0725);
 
1895
        sample += QChar(0x0716);
 
1896
        sample += QChar(0x0726);
 
1897
        break;
 
1898
    case Thaana:
 
1899
        sample += QChar(0x0784);
 
1900
        sample += QChar(0x0794);
 
1901
        sample += QChar(0x078c);
 
1902
        sample += QChar(0x078d);
 
1903
        break;
 
1904
    case Devanagari:
 
1905
        sample += QChar(0x0905);
 
1906
        sample += QChar(0x0915);
 
1907
        sample += QChar(0x0925);
 
1908
        sample += QChar(0x0935);
 
1909
        break;
 
1910
    case Bengali:
 
1911
        sample += QChar(0x0986);
 
1912
        sample += QChar(0x0996);
 
1913
        sample += QChar(0x09a6);
 
1914
        sample += QChar(0x09b6);
 
1915
        break;
 
1916
    case Gurmukhi:
 
1917
        sample += QChar(0x0a05);
 
1918
        sample += QChar(0x0a15);
 
1919
        sample += QChar(0x0a25);
 
1920
        sample += QChar(0x0a35);
 
1921
        break;
 
1922
    case Gujarati:
 
1923
        sample += QChar(0x0a85);
 
1924
        sample += QChar(0x0a95);
 
1925
        sample += QChar(0x0aa5);
 
1926
        sample += QChar(0x0ab5);
 
1927
        break;
 
1928
    case Oriya:
 
1929
        sample += QChar(0x0b06);
 
1930
        sample += QChar(0x0b16);
 
1931
        sample += QChar(0x0b2b);
 
1932
        sample += QChar(0x0b36);
 
1933
        break;
 
1934
    case Tamil:
 
1935
        sample += QChar(0x0b89);
 
1936
        sample += QChar(0x0b99);
 
1937
        sample += QChar(0x0ba9);
 
1938
        sample += QChar(0x0bb9);
 
1939
        break;
 
1940
    case Telugu:
 
1941
        sample += QChar(0x0c05);
 
1942
        sample += QChar(0x0c15);
 
1943
        sample += QChar(0x0c25);
 
1944
        sample += QChar(0x0c35);
 
1945
        break;
 
1946
    case Kannada:
 
1947
        sample += QChar(0x0c85);
 
1948
        sample += QChar(0x0c95);
 
1949
        sample += QChar(0x0ca5);
 
1950
        sample += QChar(0x0cb5);
 
1951
        break;
 
1952
    case Malayalam:
 
1953
        sample += QChar(0x0d05);
 
1954
        sample += QChar(0x0d15);
 
1955
        sample += QChar(0x0d25);
 
1956
        sample += QChar(0x0d35);
 
1957
        break;
 
1958
    case Sinhala:
 
1959
        sample += QChar(0x0d90);
 
1960
        sample += QChar(0x0da0);
 
1961
        sample += QChar(0x0db0);
 
1962
        sample += QChar(0x0dc0);
 
1963
        break;
 
1964
    case Thai:
 
1965
        sample += QChar(0x0e02);
 
1966
        sample += QChar(0x0e12);
 
1967
        sample += QChar(0x0e22);
 
1968
        sample += QChar(0x0e32);
 
1969
        break;
 
1970
    case Lao:
 
1971
        sample += QChar(0x0e8d);
 
1972
        sample += QChar(0x0e9d);
 
1973
        sample += QChar(0x0ead);
 
1974
        sample += QChar(0x0ebd);
 
1975
        break;
 
1976
    case Tibetan:
 
1977
        sample += QChar(0x0f00);
 
1978
        sample += QChar(0x0f01);
 
1979
        sample += QChar(0x0f02);
 
1980
        sample += QChar(0x0f03);
 
1981
        break;
 
1982
    case Myanmar:
 
1983
        sample += QChar(0x1000);
 
1984
        sample += QChar(0x1001);
 
1985
        sample += QChar(0x1002);
 
1986
        sample += QChar(0x1003);
 
1987
        break;
 
1988
    case Georgian:
 
1989
        sample += QChar(0x10a0);
 
1990
        sample += QChar(0x10b0);
 
1991
        sample += QChar(0x10c0);
 
1992
        sample += QChar(0x10d0);
 
1993
        break;
 
1994
    case Khmer:
 
1995
        sample += QChar(0x1780);
 
1996
        sample += QChar(0x1790);
 
1997
        sample += QChar(0x17b0);
 
1998
        sample += QChar(0x17c0);
 
1999
        break;
 
2000
    case SimplifiedChinese:
 
2001
        sample += QChar(0x3105);
 
2002
        sample += QChar(0x3115);
 
2003
        sample += QChar(0x3125);
 
2004
        sample += QChar(0x3129);
 
2005
        break;
 
2006
    case TraditionalChinese:
 
2007
        break;
 
2008
    case Japanese:
 
2009
        sample += QChar(0x3050);
 
2010
        sample += QChar(0x3060);
 
2011
        sample += QChar(0x30b0);
 
2012
        sample += QChar(0x30c0);
 
2013
        break;
 
2014
    case Korean:
 
2015
        sample += QChar(0xac00);
 
2016
        sample += QChar(0xac11);
 
2017
        sample += QChar(0xac1a);
 
2018
        sample += QChar(0xac2f);
 
2019
        break;
 
2020
    case Vietnamese:
 
2021
        break;
 
2022
    default:
 
2023
        break;
 
2024
    }
 
2025
    return sample;
 
2026
}
 
2027
 
 
2028
 
 
2029
 
 
2030
 
 
2031
/*!
 
2032
  \internal
 
2033
 
 
2034
  This makes sense of the font family name:
 
2035
 
 
2036
  1) if the family name contains a '-' (ie. "Adobe-Courier"), then we
 
2037
  split at the '-', and use the string as the foundry, and the string to
 
2038
  the right as the family
 
2039
 
 
2040
  2) if the family name contains a '[' and a ']', then we take the text
 
2041
  between the square brackets as the foundry, and the text before the
 
2042
  square brackets as the family (ie. "Arial [Monotype]")
 
2043
*/
 
2044
void QFontDatabase::parseFontName(const QString &name, QString &foundry, QString &family)
 
2045
{
 
2046
    if (name.contains('-')) {
 
2047
        int i = name.indexOf('-');
 
2048
        foundry = name.left(i);
 
2049
        family = name.right(name.length() - i - 1);
 
2050
    } else if (name.contains('[') && name.contains(']')) {
 
2051
        int i = name.indexOf('[');
 
2052
        int li = name.lastIndexOf(']');
 
2053
 
 
2054
        if (i < li) {
 
2055
            foundry = name.mid(i + 1, li - i - 1);
 
2056
            if (name[i - 1] == ' ')
 
2057
                i--;
 
2058
            family = name.left(i);
 
2059
        }
 
2060
    } else {
 
2061
        foundry.clear();
 
2062
        family = name;
 
2063
    }
 
2064
 
 
2065
    // capitalize the family/foundry names
 
2066
    bool space = true;
 
2067
    QChar *s = family.data();
 
2068
    int len = family.length();
 
2069
    while(len--) {
 
2070
        if (space) *s = s->toUpper();
 
2071
        space = s->isSpace();
 
2072
        ++s;
 
2073
    }
 
2074
 
 
2075
    s = foundry.data();
 
2076
    len = foundry.length();
 
2077
    while(len--) {
 
2078
        if (space) *s = s->toUpper();
 
2079
        space = s->isSpace();
 
2080
        ++s;
 
2081
    }
 
2082
}
 
2083
 
 
2084
void QFontDatabase::createDatabase()
 
2085
{ initializeDb(); }
 
2086
 
 
2087
#endif // QT_NO_FONTDATABASE