1
/****************************************************************************
2
**
3
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4
** All rights reserved.
5
** Contact: Nokia Corporation (qt-info@nokia.com)
6
**
7
** This file is part of the QtGui module of the Qt Toolkit.
8
**
9
** $QT_BEGIN_LICENSE:LGPL$
10
** GNU Lesser General Public License Usage
11
** This file may be used under the terms of the GNU Lesser General Public
12
** License version 2.1 as published by the Free Software Foundation and
13
** appearing in the file LICENSE.LGPL included in the packaging of this
14
** file. Please review the following information to ensure the GNU Lesser
15
** General Public License version 2.1 requirements will be met:
16
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17
**
18
** In addition, as a special exception, Nokia gives you certain additional
19
** rights. These rights are described in the Nokia Qt LGPL Exception
20
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21
**
22
** GNU General Public License Usage
23
** Alternatively, this file may be used under the terms of the GNU General
24
** Public License version 3.0 as published by the Free Software Foundation
25
** and appearing in the file LICENSE.GPL included in the packaging of this
26
** file. Please review the following information to ensure the GNU General
27
** Public License version 3.0 requirements will be met:
28
** http://www.gnu.org/copyleft/gpl.html.
29
**
30
** Other Usage
31
** Alternatively, this file may be used in accordance with the terms and
32
** conditions contained in a signed written agreement between you and Nokia.
33
**
34
**
35
**
36
**
37
**
38
** $QT_END_LICENSE$
39
**
40
****************************************************************************/
41
42
#include <qdir.h>
43
#include "qfontdatabase.h"
44
#include "qdebug.h"
45
#include "qalgorithms.h"
46
#include "qapplication.h"
47
#include "qvarlengtharray.h" // here or earlier - workaround for VC++6
48
#include "qthread.h"
49
#include "qmutex.h"
50
#include "private/qunicodetables_p.h"
51
#include "qfontengine_p.h"
52
53
#ifdef Q_WS_QPA
54
#include <QtGui/private/qapplication_p.h>
55
#include <QtGui/qplatformfontdatabase_qpa.h>
56
#include "qabstractfileengine.h"
57
#endif
58
59
#ifdef Q_WS_X11
60
#include <locale.h>
61
#endif
62
#include <stdlib.h>
63
#include <limits.h>
64
65
#if (defined(Q_WS_QWS)|| defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE)
66
#  include <ft2build.h>
67
#  include FT_TRUETYPE_TABLES_H
68
#endif
69
70
// #define QFONTDATABASE_DEBUG
71
#ifdef QFONTDATABASE_DEBUG
72
#  define FD_DEBUG qDebug
73
#else
74
#  define FD_DEBUG if (false) qDebug
75
#endif
76
77
// #define FONT_MATCH_DEBUG
78
#ifdef FONT_MATCH_DEBUG
79
#  define FM_DEBUG qDebug
80
#else
81
#  define FM_DEBUG if (false) qDebug
82
#endif
83
84
#if defined(Q_WS_WIN) && !defined(QT_NO_DIRECTWRITE)
85
#  include <dwrite.h>
86
#endif
87
88
QT_BEGIN_NAMESPACE
89
90
#define SMOOTH_SCALABLE 0xffff
91
92
bool qt_enable_test_font = false;
93
94
static QString styleStringHelper(int weight, QFont::Style style);
95
96
Q_AUTOTEST_EXPORT void qt_setQtEnableTestFont(bool value)
97
{
98
    qt_enable_test_font = value;
99
}
100
101
static int getFontWeight(const QString &weightString)
102
{
103
    QString s = weightString.toLower();
104
105
    // Test in decreasing order of commonness
106
    if (s == QLatin1String("medium") ||
107
        s == QLatin1String("normal")
108
        || s.compare(QApplication::translate("QFontDatabase", "Normal"), Qt::CaseInsensitive) == 0)
109
        return QFont::Normal;
110
    if (s == QLatin1String("bold")
111
        || s.compare(QApplication::translate("QFontDatabase", "Bold"), Qt::CaseInsensitive) == 0)
112
        return QFont::Bold;
113
    if (s == QLatin1String("demibold") || s == QLatin1String("demi bold")
114
        || s.compare(QApplication::translate("QFontDatabase", "Demi Bold"), Qt::CaseInsensitive) == 0)
115
        return QFont::DemiBold;
116
    if (s == QLatin1String("black")
117
        || s.compare(QApplication::translate("QFontDatabase", "Black"), Qt::CaseInsensitive) == 0)
118
        return QFont::Black;
119
    if (s == QLatin1String("light"))
120
        return QFont::Light;
121
122
    if (s.contains(QLatin1String("bold"))
123
        || s.contains(QApplication::translate("QFontDatabase", "Bold"), Qt::CaseInsensitive)) {
124
        if (s.contains(QLatin1String("demi"))
125
            || s.compare(QApplication::translate("QFontDatabase", "Demi"), Qt::CaseInsensitive) == 0)
126
            return (int) QFont::DemiBold;
127
        return (int) QFont::Bold;
128
    }
129
130
    if (s.contains(QLatin1String("light"))
131
        || s.compare(QApplication::translate("QFontDatabase", "Light"), Qt::CaseInsensitive) == 0)
132
        return (int) QFont::Light;
133
134
    if (s.contains(QLatin1String("black"))
135
        || s.compare(QApplication::translate("QFontDatabase", "Black"), Qt::CaseInsensitive) == 0)
136
        return (int) QFont::Black;
137
138
    return (int) QFont::Normal;
139
}
140
141
// convert 0 ~ 1000 integer to QFont::Weight
142
QFont::Weight weightFromInteger(int weight)
143
{
144
    if (weight < 400)
145
        return QFont::Light;
146
    else if (weight < 600)
147
        return QFont::Normal;
148
    else if (weight < 700)
149
        return QFont::DemiBold;
150
    else if (weight < 800)
151
        return QFont::Bold;
152
    else
153
        return QFont::Black;
154
}
155
156
struct QtFontEncoding
157
{
158
    signed int encoding : 16;
159
160
    uint xpoint   : 16;
161
    uint xres     : 8;
162
    uint yres     : 8;
163
    uint avgwidth : 16;
164
    uchar pitch   : 8;
165
};
166
167
struct  QtFontSize
168
{
169
#ifdef Q_WS_X11
170
    QtFontEncoding *encodings;
171
    QtFontEncoding *encodingID(int id, uint xpoint = 0, uint xres = 0,
172
                                uint yres = 0, uint avgwidth = 0, bool add = false);
173
    unsigned short count : 16;
174
#endif // Q_WS_X11
175
176
#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
177
    QByteArray fileName;
178
    int fileIndex;
179
#endif // defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN)
180
#if defined(Q_WS_QPA)
181
    void *handle;
182
#endif
183
184
    unsigned short pixelSize : 16;
185
};
186
187
188
#ifdef Q_WS_X11
189
QtFontEncoding *QtFontSize::encodingID(int id, uint xpoint, uint xres,
190
                                        uint yres, uint avgwidth, bool add)
191
{
192
    // we don't match using the xpoint, xres and yres parameters, only the id
193
    for (int i = 0; i < count; ++i) {
194
        if (encodings[i].encoding == id)
195
            return encodings + i;
196
    }
197
198
    if (!add) return 0;
199
200
    if (!(count % 4)) {
201
        QtFontEncoding *newEncodings = (QtFontEncoding *)
202
                    realloc(encodings,
203
                             (((count+4) >> 2) << 2) * sizeof(QtFontEncoding));
204
        Q_CHECK_PTR(newEncodings);
205
        encodings = newEncodings;
206
    }
207
    encodings[count].encoding = id;
208
    encodings[count].xpoint = xpoint;
209
    encodings[count].xres = xres;
210
    encodings[count].yres = yres;
211
    encodings[count].avgwidth = avgwidth;
212
    encodings[count].pitch = '*';
213
    return encodings + count++;
214
}
215
#endif // Q_WS_X11
216
217
struct QtFontStyle
218
{
219
    struct Key {
220
        Key(const QString &styleString);
221
        Key() : style(QFont::StyleNormal),
222
                weight(QFont::Normal), stretch(0) { }
223
        Key(const Key &o) : style(o.style), weight(o.weight), stretch(o.stretch) { }
224
        uint style : 2;
225
        signed int  weight : 8;
226
        signed int stretch : 12;
227
228
        bool operator==(const Key & other) {
229
            return (style == other.style && weight == other.weight &&
230
                    (stretch == 0 || other.stretch == 0 || stretch == other.stretch));
231
        }
232
        bool operator!=(const Key &other) {
233
            return !operator==(other);
234
        }
235
        bool operator <(const Key &o) {
236
            int x = (style << 12) + (weight << 14) + stretch;
237
            int y = (o.style << 12) + (o.weight << 14) + o.stretch;
238
            return (x < y);
239
        }
240
    };
241
242
    QtFontStyle(const Key &k)
243
        : key(k), bitmapScalable(false), smoothScalable(false),
244
          count(0), pixelSizes(0)
245
    {
246
#if defined(Q_WS_X11)
247
        weightName = setwidthName = 0;
248
#endif // Q_WS_X11
249
    }
250
251
    ~QtFontStyle() {
252
#ifdef Q_WS_X11
253
        delete [] weightName;
254
        delete [] setwidthName;
255
#endif
256
#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN)
257
        while (count) {
258
            // bitfield count-- in while condition does not work correctly in mwccsym2
259
            count--;
260
#ifdef Q_WS_X11
261
            free(pixelSizes[count].encodings);
262
#endif
263
#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
264
            pixelSizes[count].fileName.~QByteArray();
265
#endif
266
#if defined (Q_WS_QPA)
267
            QPlatformIntegration *integration = QApplicationPrivate::platformIntegration();
268
            if (integration) { //on shut down there will be some that we don't release.
269
                integration->fontDatabase()->releaseHandle(pixelSizes[count].handle);
270
            }
271
#endif
272
        }
273
#endif
274
        free(pixelSizes);
275
    }
276
277
    Key key;
278
    bool bitmapScalable : 1;
279
    bool smoothScalable : 1;
280
    signed int count    : 30;
281
    QtFontSize *pixelSizes;
282
    QString styleName;
283
284
#ifdef Q_WS_X11
285
    const char *weightName;
286
    const char *setwidthName;
287
#endif // Q_WS_X11
288
#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN)
289
    bool antialiased;
290
#endif
291
292
    QtFontSize *pixelSize(unsigned short size, bool = false);
293
};
294
295
QtFontStyle::Key::Key(const QString &styleString)
296
    : style(QFont::StyleNormal), weight(QFont::Normal), stretch(0)
297
{
298
    weight = getFontWeight(styleString);
299
300
    if (styleString.contains(QLatin1String("Italic"))
301
        || styleString.contains(QApplication::translate("QFontDatabase", "Italic")))
302
        style = QFont::StyleItalic;
303
    else if (styleString.contains(QLatin1String("Oblique"))
304
             || styleString.contains(QApplication::translate("QFontDatabase", "Oblique")))
305
        style = QFont::StyleOblique;
306
}
307
308
QtFontSize *QtFontStyle::pixelSize(unsigned short size, bool add)
309
{
310
    for (int i = 0; i < count; i++) {
311
        if (pixelSizes[i].pixelSize == size)
312
            return pixelSizes + i;
313
    }
314
    if (!add)
315
        return 0;
316
317
    if (!pixelSizes) {
318
        // Most style have only one font size, we avoid waisting memory
319
        QtFontSize *newPixelSizes = (QtFontSize *)malloc(sizeof(QtFontSize));
320
        Q_CHECK_PTR(newPixelSizes);
321
        pixelSizes = newPixelSizes;
322
    } else if (!(count % 8) || count == 1) {
323
        QtFontSize *newPixelSizes = (QtFontSize *)
324
                     realloc(pixelSizes,
325
                              (((count+8) >> 3) << 3) * sizeof(QtFontSize));
326
        Q_CHECK_PTR(newPixelSizes);
327
        pixelSizes = newPixelSizes;
328
    }
329
    pixelSizes[count].pixelSize = size;
330
#ifdef Q_WS_X11
331
    pixelSizes[count].count = 0;
332
    pixelSizes[count].encodings = 0;
333
#endif
334
#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
335
    new (&pixelSizes[count].fileName) QByteArray;
336
    pixelSizes[count].fileIndex = 0;
337
#endif
338
#if defined(Q_WS_QPA)
339
    pixelSizes[count].handle = 0;
340
#endif
341
    return pixelSizes + (count++);
342
}
343
344
struct QtFontFoundry
345
{
346
    QtFontFoundry(const QString &n) : name(n), count(0), styles(0) {}
347
    ~QtFontFoundry() {
348
        while (count--)
349
            delete styles[count];
350
        free(styles);
351
    }
352
353
    QString name;
354
355
    int count;
356
    QtFontStyle **styles;
357
    QtFontStyle *style(const QtFontStyle::Key &, const QString & = QString(), bool = false);
358
};
359
360
QtFontStyle *QtFontFoundry::style(const QtFontStyle::Key &key, const QString &styleName, bool create)
361
{
362
    int pos = 0;
363
    for (; pos < count; pos++) {
364
        bool hasStyleName = !styleName.isEmpty(); // search styleName first if available
365
        if (hasStyleName && !styles[pos]->styleName.isEmpty()) {
366
            if (styles[pos]->styleName == styleName)
367
                return styles[pos];
368
        } else {
369
            if (styles[pos]->key == key)
370
                return styles[pos];
371
        }
372
    }
373
    if (!create)
374
        return 0;
375
376
    // qDebug("adding key (weight=%d, style=%d, stretch=%d) at %d", key.weight, key.style, key.stretch, pos);
377
    if (!(count % 8)) {
378
        QtFontStyle **newStyles = (QtFontStyle **)
379
                 realloc(styles, (((count+8) >> 3) << 3) * sizeof(QtFontStyle *));
380
        Q_CHECK_PTR(newStyles);
381
        styles = newStyles;
382
    }
383
384
    QtFontStyle *style = new QtFontStyle(key);
385
    style->styleName = styleName;
386
    styles[pos] = style;
387
    count++;
388
    return styles[pos];
389
}
390
391
struct  QtFontFamily
392
{
393
    enum WritingSystemStatus {
394
        Unknown         = 0,
395
        Supported       = 1,
396
        UnsupportedFT  = 2,
397
        UnsupportedXLFD = 4,
398
        Unsupported     = UnsupportedFT | UnsupportedXLFD
399
    };
400
401
    QtFontFamily(const QString &n)
402
        :
403
#ifdef Q_WS_X11
404
        fixedPitch(true), ftWritingSystemCheck(false),
405
        xlfdLoaded(false), synthetic(false), symbol_checked(false),
406
#else
407
        fixedPitch(false),
408
#endif
409
#ifdef Q_WS_WIN
410
        writingSystemCheck(false),
411
        loaded(false),
412
#endif
413
#if !defined(QWS) && defined(Q_OS_MAC)
414
        fixedPitchComputed(false),
415
#endif
416
        name(n), count(0), foundries(0)
417
#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
418
        , bogusWritingSystems(false)
419
#endif
420
#if defined(Q_WS_QPA)
421
        , askedForFallback(false)
422
#endif
423
    {
424
        memset(writingSystems, 0, sizeof(writingSystems));
425
    }
426
    ~QtFontFamily() {
427
        while (count--)
428
            delete foundries[count];
429
        free(foundries);
430
    }
431
432
    bool fixedPitch : 1;
433
#ifdef Q_WS_X11
434
    bool ftWritingSystemCheck : 1;
435
    bool xlfdLoaded : 1;
436
    bool synthetic : 1;
437
#endif
438
#ifdef Q_WS_WIN
439
    bool writingSystemCheck : 1;
440
    bool loaded : 1;
441
#endif
442
#if !defined(QWS) && defined(Q_OS_MAC)
443
    bool fixedPitchComputed : 1;
444
#endif
445
#ifdef Q_WS_X11
446
    bool symbol_checked : 1;
447
#endif
448
449
    QString name;
450
#if defined(Q_WS_X11) ||   defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
451
    QByteArray fontFilename;
452
    int fontFileIndex;
453
#endif
454
#ifdef Q_WS_WIN
455
    QString english_name;
456
#endif
457
    int count;
458
    QtFontFoundry **foundries;
459
460
#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
461
    bool bogusWritingSystems;
462
    QStringList fallbackFamilies;
463
#endif
464
#if defined (Q_WS_QPA)
465
    bool askedForFallback;
466
#endif
467
    unsigned char writingSystems[QFontDatabase::WritingSystemsCount];
468
469
    QtFontFoundry *foundry(const QString &f, bool = false);
470
};
471
472
#if !defined(QWS) && defined(Q_OS_MAC)
473
inline static void qt_mac_get_fixed_pitch(QtFontFamily *f)
474
{
475
    if(f && !f->fixedPitchComputed) {
476
        QFontMetrics fm(f->name);
477
        f->fixedPitch = fm.width(QLatin1Char('i')) == fm.width(QLatin1Char('m'));
478
        f->fixedPitchComputed = true;
479
    }
480
}
481
#endif
482
483
484
QtFontFoundry *QtFontFamily::foundry(const QString &f, bool create)
485
{
486
    if (f.isNull() && count == 1)
487
        return foundries[0];
488
489
    for (int i = 0; i < count; i++) {
490
        if (foundries[i]->name.compare(f, Qt::CaseInsensitive) == 0)
491
            return foundries[i];
492
    }
493
    if (!create)
494
        return 0;
495
496
    if (!(count % 8)) {
497
        QtFontFoundry **newFoundries = (QtFontFoundry **)
498
                    realloc(foundries,
499
                             (((count+8) >> 3) << 3) * sizeof(QtFontFoundry *));
500
        Q_CHECK_PTR(newFoundries);
501
        foundries = newFoundries;
502
    }
503
504
    foundries[count] = new QtFontFoundry(f);
505
    return foundries[count++];
506
}
507
508
// ### copied to tools/makeqpf/qpf2.cpp
509
510
// see the Unicode subset bitfields in the MSDN docs
511
static int requiredUnicodeBits[QFontDatabase::WritingSystemsCount][2] = {
512
        // Any,
513
    { 127, 127 },
514
        // Latin,
515
    { 0, 127 },
516
        // Greek,
517
    { 7, 127 },
518
        // Cyrillic,
519
    { 9, 127 },
520
        // Armenian,
521
    { 10, 127 },
522
        // Hebrew,
523
    { 11, 127 },
524
        // Arabic,
525
    { 13, 127 },
526
        // Syriac,
527
    { 71, 127 },
528
    //Thaana,
529
    { 72, 127 },
530
    //Devanagari,
531
    { 15, 127 },
532
    //Bengali,
533
    { 16, 127 },
534
    //Gurmukhi,
535
    { 17, 127 },
536
    //Gujarati,
537
    { 18, 127 },
538
    //Oriya,
539
    { 19, 127 },
540
    //Tamil,
541
    { 20, 127 },
542
    //Telugu,
543
    { 21, 127 },
544
    //Kannada,
545
    { 22, 127 },
546
    //Malayalam,
547
    { 23, 127 },
548
    //Sinhala,
549
    { 73, 127 },
550
    //Thai,
551
    { 24, 127 },
552
    //Lao,
553
    { 25, 127 },
554
    //Tibetan,
555
    { 70, 127 },
556
    //Myanmar,
557
    { 74, 127 },
558
        // Georgian,
559
    { 26, 127 },
560
        // Khmer,
561
    { 80, 127 },
562
        // SimplifiedChinese,
563
    { 126, 127 },
564
        // TraditionalChinese,
565
    { 126, 127 },
566
        // Japanese,
567
    { 126, 127 },
568
        // Korean,
569
    { 56, 127 },
570
        // Vietnamese,
571
    { 0, 127 }, // same as latin1
572
        // Other,
573
    { 126, 127 },
574
        // Ogham,
575
    { 78, 127 },
576
        // Runic,
577
    { 79, 127 },
578
        // Nko,
579
    { 14, 127 },
580
};
581
582
#define SimplifiedChineseCsbBit 18
583
#define TraditionalChineseCsbBit 20
584
#define JapaneseCsbBit 17
585
#define KoreanCsbBit 21
586
587
QList<QFontDatabase::WritingSystem> qt_determine_writing_systems_from_truetype_bits(quint32 unicodeRange[4], quint32 codePageRange[2])
588
{
589
    QList<QFontDatabase::WritingSystem> writingSystems;
590
    bool hasScript = false;
591
592
    int i;
593
    for(i = 0; i < QFontDatabase::WritingSystemsCount; i++) {
594
        int bit = requiredUnicodeBits[i][0];
595
        int index = bit/32;
596
        int flag =  1 << (bit&31);
597
        if (bit != 126 && unicodeRange[index] & flag) {
598
            bit = requiredUnicodeBits[i][1];
599
            index = bit/32;
600
601
            flag =  1 << (bit&31);
602
            if (bit == 127 || unicodeRange[index] & flag) {
603
                writingSystems.append(QFontDatabase::WritingSystem(i));
604
                hasScript = true;
605
                // qDebug("font %s: index=%d, flag=%8x supports script %d", familyName.latin1(), index, flag, i);
606
            }
607
        }
608
    }
609
    if(codePageRange[0] & (1 << SimplifiedChineseCsbBit)) {
610
        writingSystems.append(QFontDatabase::SimplifiedChinese);
611
        hasScript = true;
612
        //qDebug("font %s supports Simplified Chinese", familyName.latin1());
613
    }
614
    if(codePageRange[0] & (1 << TraditionalChineseCsbBit)) {
615
        writingSystems.append(QFontDatabase::TraditionalChinese);
616
        hasScript = true;
617
        //qDebug("font %s supports Traditional Chinese", familyName.latin1());
618
    }
619
    if(codePageRange[0] & (1 << JapaneseCsbBit)) {
620
        writingSystems.append(QFontDatabase::Japanese);
621
        hasScript = true;
622
        //qDebug("font %s supports Japanese", familyName.latin1());
623
    }
624
    if(codePageRange[0] & (1 << KoreanCsbBit)) {
625
        writingSystems.append(QFontDatabase::Korean);
626
        hasScript = true;
627
        //qDebug("font %s supports Korean", familyName.latin1());
628
    }
629
    if (!hasScript)
630
        writingSystems.append(QFontDatabase::Symbol);
631
632
    return writingSystems;
633
}
634
635
#if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
636
// class with virtual destructor, derived in qfontdatabase_s60.cpp
637
class QSymbianFontDatabaseExtras
638
{
639
public:
640
    virtual ~QSymbianFontDatabaseExtras() {}
641
};
642
#endif
643
644
class QFontDatabasePrivate
645
{
646
public:
647
    QFontDatabasePrivate()
648
        : count(0), families(0), reregisterAppFonts(false)
649
#if defined(Q_WS_QWS)
650
          , stream(0)
651
#endif
652
#if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
653
          , symbianExtras(0)
654
#endif
655
#if defined(Q_WS_WIN) && !defined(QT_NO_DIRECTWRITE)
656
          , directWriteFactory(0)
657
          , directWriteGdiInterop(0)
658
#endif
659
    { }
660
661
    ~QFontDatabasePrivate() {
662
        free();
663
#if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
664
        if (symbianExtras)
665
            delete symbianExtras;
666
#endif
667
#if defined(Q_WS_WIN) && !defined(QT_NO_DIRECTWRITE)
668
    if (directWriteGdiInterop)
669
        directWriteGdiInterop->Release();
670
    if (directWriteFactory != 0)
671
        directWriteFactory->Release();
672
#endif
673
    }
674
    QtFontFamily *family(const QString &f, bool = false);
675
    void free() {
676
        while (count--)
677
            delete families[count];
678
        ::free(families);
679
        families = 0;
680
        count = 0;
681
        // don't clear the memory fonts!
682
    }
683
684
    int count;
685
#if defined(Q_WS_X11) && !defined(QT_NO_FONTCONFIG)
686
    QString systemLang;
687
#endif
688
    QtFontFamily **families;
689
690
#if defined(Q_WS_WIN) && !defined(QT_NO_DIRECTWRITE)
691
    IDWriteFactory *directWriteFactory;
692
    IDWriteGdiInterop *directWriteGdiInterop;
693
#endif
694
695
696
    struct ApplicationFont {
697
        QString fileName;
698
        QByteArray data;
699
#if defined(Q_OS_WIN)
700
        HANDLE handle;
701
        bool memoryFont;
702
        QVector<FONTSIGNATURE> signatures;
703
#elif defined(Q_WS_MAC)
704
        ATSFontContainerRef handle;
705
#elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
706
        QString temporaryFileName;
707
        TInt screenDeviceFontFileId;
708
        TUid fontStoreFontFileUid;
709
#endif
710
        QStringList families;
711
    };
712
    QVector<ApplicationFont> applicationFonts;
713
    int addAppFont(const QByteArray &fontData, const QString &fileName);
714
    bool reregisterAppFonts;
715
    bool isApplicationFont(const QString &fileName);
716
717
    void invalidate();
718
719
#if defined(Q_WS_QWS)
720
    bool loadFromCache(const QString &fontPath);
721
    void addQPF2File(const QByteArray &file);
722
#endif // Q_WS_QWS
723
#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
724
    void addFont(const QString &familyname, const char *foundryname, int weight,
725
                 bool italic, int pixelSize, const QByteArray &file, int fileIndex,
726
                 bool antialiased,
727
                 const QList<QFontDatabase::WritingSystem> &writingSystems = QList<QFontDatabase::WritingSystem>());
728
#ifndef QT_NO_FREETYPE
729
    QStringList addTTFile(const QByteArray &file, const QByteArray &fontData = QByteArray());
730
#endif // QT_NO_FREETYPE
731
#endif
732
#if defined(Q_WS_QWS)
733
    QDataStream *stream;
734
#elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
735
    QSymbianFontDatabaseExtras *symbianExtras;
736
#endif
737
#if defined(Q_WS_QWS) || defined(Q_WS_QPA)
738
    QStringList fallbackFamilies;
739
#endif
740
};
741
742
void QFontDatabasePrivate::invalidate()
743
{
744
    QFontCache::instance()->clear();
745
    free();
746
    emit static_cast<QApplication *>(QApplication::instance())->fontDatabaseChanged();
747
}
748
749
QtFontFamily *QFontDatabasePrivate::family(const QString &f, bool create)
750
{
751
    int low = 0;
752
    int high = count;
753
    int pos = count / 2;
754
    int res = 1;
755
    if (count) {
756
        while ((res = families[pos]->name.compare(f, Qt::CaseInsensitive)) && pos != low) {
757
            if (res > 0)
758
                high = pos;
759
            else
760
                low = pos;
761
            pos = (high + low) / 2;
762
        }
763
        if (!res)
764
            return families[pos];
765
    }
766
    if (!create)
767
        return 0;
768
769
    if (res < 0)
770
        pos++;
771
772
    // qDebug("adding family %s at %d total=%d", f.latin1(), pos, count);
773
    if (!(count % 8)) {
774
        QtFontFamily **newFamilies = (QtFontFamily **)
775
                   realloc(families,
776
                            (((count+8) >> 3) << 3) * sizeof(QtFontFamily *));
777
        Q_CHECK_PTR(newFamilies);
778
        families = newFamilies;
779
    }
780
781
    QtFontFamily *family = new QtFontFamily(f);
782
    memmove(families + pos + 1, families + pos, (count-pos)*sizeof(QtFontFamily *));
783
    families[pos] = family;
784
    count++;
785
    return families[pos];
786
}
787
788
#if defined(Q_WS_QWS) ||  defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
789
void QFontDatabasePrivate::addFont(const QString &familyname, const char *foundryname, int weight, bool italic, int pixelSize,
790
                                   const QByteArray &file, int fileIndex, bool antialiased,
791
                                   const QList<QFontDatabase::WritingSystem> &writingSystems)
792
{
793
//    qDebug() << "Adding font" << familyname << weight << italic << pixelSize << file << fileIndex << antialiased;
794
    QtFontStyle::Key styleKey;
795
    styleKey.style = italic ? QFont::StyleItalic : QFont::StyleNormal;
796
    styleKey.weight = weight;
797
    styleKey.stretch = 100;
798
    QtFontFamily *f = family(familyname, true);
799
800
    if (writingSystems.isEmpty()) {
801
        for (int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws) {
802
            f->writingSystems[ws] = QtFontFamily::Supported;
803
        }
804
        f->bogusWritingSystems = true;
805
    } else {
806
        for (int i = 0; i < writingSystems.count(); ++i) {
807
            f->writingSystems[writingSystems.at(i)] = QtFontFamily::Supported;
808
        }
809
    }
810
811
    QtFontFoundry *foundry = f->foundry(QString::fromLatin1(foundryname), true);
812
    QtFontStyle *style = foundry->style(styleKey, QString(), true);
813
    style->smoothScalable = (pixelSize == 0);
814
    style->antialiased = antialiased;
815
    QtFontSize *size = style->pixelSize(pixelSize?pixelSize:SMOOTH_SCALABLE, true);
816
    size->fileName = file;
817
    size->fileIndex = fileIndex;
818
819
#if defined(Q_WS_QWS)
820
    if (stream) {
821
        *stream << familyname << foundry->name << weight << quint8(italic) << pixelSize
822
                << file << fileIndex << quint8(antialiased);
823
        *stream << quint8(writingSystems.count());
824
        for (int i = 0; i < writingSystems.count(); ++i)
825
            *stream << quint8(writingSystems.at(i));
826
    }
827
#else // ..in case of defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
828
    f->fontFilename = file;
829
    f->fontFileIndex = fileIndex;
830
#endif
831
}
832
#endif
833
834
#if (defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE)
835
QStringList QFontDatabasePrivate::addTTFile(const QByteArray &file, const QByteArray &fontData)
836
{
837
    QStringList families;
838
    extern FT_Library qt_getFreetype();
839
    FT_Library library = qt_getFreetype();
840
841
    int index = 0;
842
    int numFaces = 0;
843
    do {
844
        FT_Face face;
845
        FT_Error error;
846
        if (!fontData.isEmpty()) {
847
            error = FT_New_Memory_Face(library, (const FT_Byte *)fontData.constData(), fontData.size(), index, &face);
848
        } else {
849
            error = FT_New_Face(library, file, index, &face);
850
        }
851
        if (error != FT_Err_Ok) {
852
            qDebug() << "FT_New_Face failed with index" << index << ":" << hex << error;
853
            break;
854
        }
855
        numFaces = face->num_faces;
856
857
        int weight = QFont::Normal;
858
        bool italic = face->style_flags & FT_STYLE_FLAG_ITALIC;
859
860
        if (face->style_flags & FT_STYLE_FLAG_BOLD)
861
            weight = QFont::Bold;
862
863
        QList<QFontDatabase::WritingSystem> writingSystems;
864
        // detect symbol fonts
865
        for (int i = 0; i < face->num_charmaps; ++i) {
866
            FT_CharMap cm = face->charmaps[i];
867
            if (cm->encoding == ft_encoding_adobe_custom
868
                    || cm->encoding == ft_encoding_symbol) {
869
                writingSystems.append(QFontDatabase::Symbol);
870
                break;
871
            }
872
        }
873
        if (writingSystems.isEmpty()) {
874
            TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2);
875
            if (os2) {
876
                quint32 unicodeRange[4] = {
877
                    static_cast<quint32>(os2->ulUnicodeRange1), static_cast<quint32>(os2->ulUnicodeRange2), static_cast<quint32>(os2->ulUnicodeRange3), static_cast<quint32>(os2->ulUnicodeRange4)
878
                };
879
                quint32 codePageRange[2] = {
880
                    static_cast<quint32>(os2->ulCodePageRange1), static_cast<quint32>(os2->ulCodePageRange2)
881
                };
882
883
                writingSystems = qt_determine_writing_systems_from_truetype_bits(unicodeRange, codePageRange);
884
                //for (int i = 0; i < writingSystems.count(); ++i)
885
                //    qDebug() << QFontDatabase::writingSystemName(writingSystems.at(i));
886
            }
887
        }
888
889
        QString family = QString::fromAscii(face->family_name);
890
        families.append(family);
891
        addFont(family, /*foundry*/ "", weight, italic,
892
                /*pixelsize*/ 0, file, index, /*antialias*/ true, writingSystems);
893
894
        FT_Done_Face(face);
895
        ++index;
896
    } while (index < numFaces);
897
    return families;
898
}
899
#endif
900
901
static const int scriptForWritingSystem[] = {
902
    QUnicodeTables::Common, // Any
903
    QUnicodeTables::Latin, // Latin
904
    QUnicodeTables::Greek, // Greek
905
    QUnicodeTables::Cyrillic, // Cyrillic
906
    QUnicodeTables::Armenian, // Armenian
907
    QUnicodeTables::Hebrew, // Hebrew
908
    QUnicodeTables::Arabic, // Arabic
909
    QUnicodeTables::Syriac, // Syriac
910
    QUnicodeTables::Thaana, // Thaana
911
    QUnicodeTables::Devanagari, // Devanagari
912
    QUnicodeTables::Bengali, // Bengali
913
    QUnicodeTables::Gurmukhi, // Gurmukhi
914
    QUnicodeTables::Gujarati, // Gujarati
915
    QUnicodeTables::Oriya, // Oriya
916
    QUnicodeTables::Tamil, // Tamil
917
    QUnicodeTables::Telugu, // Telugu
918
    QUnicodeTables::Kannada, // Kannada
919
    QUnicodeTables::Malayalam, // Malayalam
920
    QUnicodeTables::Sinhala, // Sinhala
921
    QUnicodeTables::Thai, // Thai
922
    QUnicodeTables::Lao, // Lao
923
    QUnicodeTables::Tibetan, // Tibetan
924
    QUnicodeTables::Myanmar, // Myanmar
925
    QUnicodeTables::Georgian, // Georgian
926
    QUnicodeTables::Khmer, // Khmer
927
    QUnicodeTables::Common, // SimplifiedChinese
928
    QUnicodeTables::Common, // TraditionalChinese
929
    QUnicodeTables::Common, // Japanese
930
    QUnicodeTables::Hangul, // Korean
931
    QUnicodeTables::Common, // Vietnamese
932
    QUnicodeTables::Common, // Yi
933
    QUnicodeTables::Common, // Tagalog
934
    QUnicodeTables::Common, // Hanunoo
935
    QUnicodeTables::Common, // Buhid
936
    QUnicodeTables::Common, // Tagbanwa
937
    QUnicodeTables::Common, // Limbu
938
    QUnicodeTables::Common, // TaiLe
939
    QUnicodeTables::Common, // Braille
940
    QUnicodeTables::Common, // Symbol
941
    QUnicodeTables::Ogham,  // Ogham
942
    QUnicodeTables::Runic, // Runic
943
    QUnicodeTables::Nko // Nko
944
};
945
946
int qt_script_for_writing_system(QFontDatabase::WritingSystem writingSystem)
947
{
948
    return scriptForWritingSystem[writingSystem];
949
}
950
951
952
#if defined Q_WS_QWS || (defined(Q_WS_X11) && !defined(QT_NO_FONTCONFIG)) || defined(Q_WS_WIN)
953
static inline bool requiresOpenType(int writingSystem)
954
{
955
    return ((writingSystem >= QFontDatabase::Syriac && writingSystem <= QFontDatabase::Sinhala)
956
            || writingSystem == QFontDatabase::Khmer || writingSystem == QFontDatabase::Nko);
957
}
958
static inline bool scriptRequiresOpenType(int script)
959
{
960
    return ((script >= QUnicodeTables::Syriac && script <= QUnicodeTables::Sinhala)
961
            || script == QUnicodeTables::Khmer || script == QUnicodeTables::Nko);
962
}
963
#endif
964
965
966
/*!
967
  \internal
968
969
  This makes sense of the font family name:
970
971
  if the family name contains a '[' and a ']', then we take the text
972
  between the square brackets as the foundry, and the text before the
973
  square brackets as the family (ie. "Arial [Monotype]")
974
*/
975
static void parseFontName(const QString &name, QString &foundry, QString &family)
976
{
977
    int i = name.indexOf(QLatin1Char('['));
978
    int li = name.lastIndexOf(QLatin1Char(']'));
979
    if (i >= 0 && li >= 0 && i < li) {
980
        foundry = name.mid(i + 1, li - i - 1);
981
        if (i > 0 && name[i - 1] == QLatin1Char(' '))
982
            i--;
983
        family = name.left(i);
984
    } else {
985
        foundry.clear();
986
        family = name;
987
    }
988
989
    // capitalize the family/foundry names
990
    bool space = true;
991
    QChar *s = family.data();
992
    int len = family.length();
993
    while(len--) {
994
        if (space) *s = s->toUpper();
995
        space = s->isSpace();
996
        ++s;
997
    }
998
999
    space = true;
1000
    s = foundry.data();
1001
    len = foundry.length();
1002
    while(len--) {
1003
        if (space) *s = s->toUpper();
1004
        space = s->isSpace();
1005
        ++s;
1006
    }
1007
}
1008
1009
1010
struct QtFontDesc
1011
{
1012
    inline QtFontDesc() : family(0), foundry(0), style(0), size(0), encoding(0), familyIndex(-1) {}
1013
    QtFontFamily *family;
1014
    QtFontFoundry *foundry;
1015
    QtFontStyle *style;
1016
    QtFontSize *size;
1017
    QtFontEncoding *encoding;
1018
    int familyIndex;
1019
};
1020
1021
#if !defined(Q_WS_MAC)
1022
static void match(int script, const QFontDef &request,
1023
                  const QString &family_name, const QString &foundry_name, int force_encoding_id,
1024
                  QtFontDesc *desc, const QList<int> &blacklistedFamilies = QList<int>(), bool forceXLFD=false);
1025
1026
#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_QPA)
1027
static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDef *fontDef)
1028
{
1029
    fontDef->family = desc.family->name;
1030
    if (! desc.foundry->name.isEmpty() && desc.family->count > 1) {
1031
        fontDef->family += QString::fromLatin1(" [");
1032
        fontDef->family += desc.foundry->name;
1033
        fontDef->family += QLatin1Char(']');
1034
    }
1035
1036
    if (desc.style->smoothScalable)
1037
        fontDef->pixelSize = request.pixelSize;
1038
    else if ((desc.style->bitmapScalable && (request.styleStrategy & QFont::PreferMatch)))
1039
        fontDef->pixelSize = request.pixelSize;
1040
    else
1041
        fontDef->pixelSize = desc.size->pixelSize;
1042
1043
    fontDef->styleHint     = request.styleHint;
1044
    fontDef->styleStrategy = request.styleStrategy;
1045
1046
    fontDef->weight        = desc.style->key.weight;
1047
    fontDef->style         = desc.style->key.style;
1048
    fontDef->fixedPitch    = desc.family->fixedPitch;
1049
    fontDef->stretch       = desc.style->key.stretch;
1050
    fontDef->ignorePitch   = false;
1051
}
1052
#endif
1053
#endif
1054
1055
#if defined(Q_WS_X11) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) || defined(Q_WS_QPA)
1056
static void getEngineData(const QFontPrivate *d, const QFontCache::Key &key)
1057
{
1058
    // look for the requested font in the engine data cache
1059
    d->engineData = QFontCache::instance()->findEngineData(key);
1060
    if (!d->engineData) {
1061
        // create a new one
1062
        d->engineData = new QFontEngineData;
1063
        QFontCache::instance()->insertEngineData(key, d->engineData);
1064
    } else {
1065
        d->engineData->ref.ref();
1066
    }
1067
}
1068
#endif
1069
1070
static QStringList familyList(const QFontDef &req)
1071
{
1072
    // list of families to try
1073
    QStringList family_list;
1074
    if (req.family.isEmpty())
1075
        return family_list;
1076
1077
    QStringList list = req.family.split(QLatin1Char(','));
1078
    for (int i = 0; i < list.size(); ++i) {
1079
        QString str = list.at(i).trimmed();
1080
        if ((str.startsWith(QLatin1Char('"')) && str.endsWith(QLatin1Char('"')))
1081
            || (str.startsWith(QLatin1Char('\'')) && str.endsWith(QLatin1Char('\''))))
1082
            str = str.mid(1, str.length() - 2);
1083
        family_list << str;
1084
    }
1085
1086
    // append the substitute list for each family in family_list
1087
    QStringList subs_list;
1088
    QStringList::ConstIterator it = family_list.constBegin(), end = family_list.constEnd();
1089
    for (; it != end; ++it)
1090
        subs_list += QFont::substitutes(*it);
1091
//         qDebug() << "adding substs: " << subs_list;
1092
1093
    family_list += subs_list;
1094
1095
    return family_list;
1096
}
1097
1098
Q_GLOBAL_STATIC(QFontDatabasePrivate, privateDb)
1099
Q_GLOBAL_STATIC_WITH_ARGS(QMutex, fontDatabaseMutex, (QMutex::Recursive))
1100
1101
// used in qfontengine_x11.cpp
1102
QMutex *qt_fontdatabase_mutex()
1103
{
1104
    return fontDatabaseMutex();
1105
}
1106
1107
QT_BEGIN_INCLUDE_NAMESPACE
1108
#if defined(Q_WS_X11)
1109
#  include "qfontdatabase_x11.cpp"
1110
#elif defined(Q_WS_MAC)
1111
#  include "qfontdatabase_mac.cpp"
1112
#elif defined(Q_WS_WIN)
1113
#  include "qfontdatabase_win.cpp"
1114
#elif defined(Q_WS_QWS)
1115
#  include "qfontdatabase_qws.cpp"
1116
#elif defined(Q_WS_QPA)
1117
#  include "qfontdatabase_qpa.cpp"
1118
#elif defined(Q_OS_SYMBIAN)
1119
#  include "qfontdatabase_s60.cpp"
1120
#endif
1121
QT_END_INCLUDE_NAMESPACE
1122
1123
#if !defined(Q_WS_X11) && !defined(Q_WS_MAC)
1124
QString QFontDatabase::resolveFontFamilyAlias(const QString &family)
1125
{
1126
    return family;
1127
}
1128
#endif
1129
1130
static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &styleKey,
1131
                              const QString &styleName = QString())
1132
{
1133
    int best = 0;
1134
    int dist = 0xffff;
1135
1136
    for ( int i = 0; i < foundry->count; i++ ) {
1137
        QtFontStyle *style = foundry->styles[i];
1138
1139
        if (!styleName.isEmpty() && styleName == style->styleName) {
1140
            dist = 0;
1141
            best = i;
1142
            break;
1143
        }
1144
1145
        int d = qAbs( styleKey.weight - style->key.weight );
1146
1147
        if ( styleKey.stretch != 0 && style->key.stretch != 0 ) {
1148
            d += qAbs( styleKey.stretch - style->key.stretch );
1149
        }
1150
1151
        if (styleKey.style != style->key.style) {
1152
            if (styleKey.style != QFont::StyleNormal && style->key.style != QFont::StyleNormal)
1153
                // one is italic, the other oblique
1154
                d += 0x0001;
1155
            else
1156
                d += 0x1000;
1157
        }
1158
1159
        if ( d < dist ) {
1160
            best = i;
1161
            dist = d;
1162
        }
1163
    }
1164
1165
    FM_DEBUG( "          best style has distance 0x%x", dist );
1166
    return foundry->styles[best];
1167
}
1168
1169
#if defined(Q_WS_X11)
1170
static QtFontEncoding *findEncoding(int script, int styleStrategy,
1171
                                    QtFontSize *size, int force_encoding_id)
1172
{
1173
    QtFontEncoding *encoding = 0;
1174
1175
    if (force_encoding_id >= 0) {
1176
        encoding = size->encodingID(force_encoding_id);
1177
        if (!encoding)
1178
            FM_DEBUG("            required encoding_id not available");
1179
        return encoding;
1180
    }
1181
1182
    if (styleStrategy & (QFont::OpenGLCompatible | QFont::PreferBitmap)) {
1183
        FM_DEBUG("            PreferBitmap and/or OpenGL set, skipping Freetype");
1184
    } else {
1185
        encoding = size->encodingID(-1); // -1 == prefer Freetype
1186
        if (encoding)
1187
            return encoding;
1188
    }
1189
1190
    // FT not available, find an XLFD font, trying the default encoding first
1191
    encoding = size->encodingID(QFontPrivate::defaultEncodingID);
1192
    if (encoding) {
1193
        // does it support the requested script?
1194
        bool supportsScript = false;
1195
        for (int ws = 1; !supportsScript && ws < QFontDatabase::WritingSystemsCount; ++ws) {
1196
            if (scriptForWritingSystem[ws] != script)
1197
                continue;
1198
            supportsScript = writingSystems_for_xlfd_encoding[encoding->encoding][ws];
1199
        }
1200
        if (!supportsScript)
1201
            encoding = 0;
1202
    }
1203
    // find the first encoding that supports the requested script
1204
    for (int ws = 1; !encoding && ws < QFontDatabase::WritingSystemsCount; ++ws) {
1205
        if (scriptForWritingSystem[ws] != script)
1206
            continue;
1207
        for (int x = 0; !encoding && x < size->count; ++x) {
1208
            const int enc = size->encodings[x].encoding;
1209
            if (writingSystems_for_xlfd_encoding[enc][ws])
1210
                encoding = size->encodings + x;
1211
        }
1212
    }
1213
1214
    return encoding;
1215
}
1216
#endif // Q_WS_X11
1217
1218
#if !defined(Q_WS_MAC)
1219
static
1220
unsigned int bestFoundry(int script, unsigned int score, int styleStrategy,
1221
                         const QtFontFamily *family, const QString &foundry_name,
1222
                         QtFontStyle::Key styleKey, int pixelSize, char pitch,
1223
                         QtFontDesc *desc, int force_encoding_id)
1224
{
1225
    Q_UNUSED(force_encoding_id);
1226
    Q_UNUSED(script);
1227
    Q_UNUSED(pitch);
1228
1229
    desc->foundry = 0;
1230
    desc->style = 0;
1231
    desc->size = 0;
1232
    desc->encoding = 0;
1233
1234
1235
    FM_DEBUG("  REMARK: looking for best foundry for family '%s' [%d]", family->name.toLatin1().constData(), family->count);
1236
1237
    for (int x = 0; x < family->count; ++x) {
1238
        QtFontFoundry *foundry = family->foundries[x];
1239
        if (!foundry_name.isEmpty() && foundry->name.compare(foundry_name, Qt::CaseInsensitive) != 0)
1240
            continue;
1241
1242
        FM_DEBUG("          looking for matching style in foundry '%s' %d",
1243
                 foundry->name.isEmpty() ? "-- none --" : foundry->name.toLatin1().constData(), foundry->count);
1244
1245
        QtFontStyle *style = bestStyle(foundry, styleKey);
1246
1247
        if (!style->smoothScalable && (styleStrategy & QFont::ForceOutline)) {
1248
            FM_DEBUG("            ForceOutline set, but not smoothly scalable");
1249
            continue;
1250
        }
1251
1252
        int px = -1;
1253
        QtFontSize *size = 0;
1254
1255
        // 1. see if we have an exact matching size
1256
        if (!(styleStrategy & QFont::ForceOutline)) {
1257
            size = style->pixelSize(pixelSize);
1258
            if (size) {
1259
                FM_DEBUG("          found exact size match (%d pixels)", size->pixelSize);
1260
                px = size->pixelSize;
1261
            }
1262
        }
1263
1264
        // 2. see if we have a smoothly scalable font
1265
        if (!size && style->smoothScalable && ! (styleStrategy & QFont::PreferBitmap)) {
1266
            size = style->pixelSize(SMOOTH_SCALABLE);
1267
            if (size) {
1268
                FM_DEBUG("          found smoothly scalable font (%d pixels)", pixelSize);
1269
                px = pixelSize;
1270
            }
1271
        }
1272
1273
        // 3. see if we have a bitmap scalable font
1274
        if (!size && style->bitmapScalable && (styleStrategy & QFont::PreferMatch)) {
1275
            size = style->pixelSize(0);
1276
            if (size) {
1277
                FM_DEBUG("          found bitmap scalable font (%d pixels)", pixelSize);
1278
                px = pixelSize;
1279
            }
1280
        }
1281
1282
#ifdef Q_WS_X11
1283
        QtFontEncoding *encoding = 0;
1284
#endif
1285
1286
        // 4. find closest size match
1287
        if (! size) {
1288
            unsigned int distance = ~0u;
1289
            for (int x = 0; x < style->count; ++x) {
1290
#ifdef Q_WS_X11
1291
                encoding =
1292
                    findEncoding(script, styleStrategy, style->pixelSizes + x, force_encoding_id);
1293
                if (!encoding) {
1294
                    FM_DEBUG("          size %3d does not support the script we want",
1295
                             style->pixelSizes[x].pixelSize);
1296
                    continue;
1297
                }
1298
#endif
1299
1300
                unsigned int d;
1301
                if (style->pixelSizes[x].pixelSize < pixelSize) {
1302
                    // penalize sizes that are smaller than the
1303
                    // requested size, due to truncation from floating
1304
                    // point to integer conversions
1305
                    d = pixelSize - style->pixelSizes[x].pixelSize + 1;
1306
                } else {
1307
                    d = style->pixelSizes[x].pixelSize - pixelSize;
1308
                }
1309
1310
                if (d < distance) {
1311
                    distance = d;
1312
                    size = style->pixelSizes + x;
1313
                    FM_DEBUG("          best size so far: %3d (%d)", size->pixelSize, pixelSize);
1314
                }
1315
            }
1316
1317
            if (!size) {
1318
                FM_DEBUG("          no size supports the script we want");
1319
                continue;
1320
            }
1321
1322
            if (style->bitmapScalable && ! (styleStrategy & QFont::PreferQuality) &&
1323
                (distance * 10 / pixelSize) >= 2) {
1324
                // the closest size is not close enough, go ahead and
1325
                // use a bitmap scaled font
1326
                size = style->pixelSize(0);
1327
                px = pixelSize;
1328
            } else {
1329
                px = size->pixelSize;
1330
            }
1331
        }
1332
1333
#ifdef Q_WS_X11
1334
        if (size) {
1335
            encoding = findEncoding(script, styleStrategy, size, force_encoding_id);
1336
            if (!encoding) size = 0;
1337
        }
1338
        if (! encoding) {
1339
            FM_DEBUG("          foundry doesn't support the script we want");
1340
            continue;
1341
        }
1342
#endif // Q_WS_X11
1343
1344
        unsigned int this_score = 0x0000;
1345
        enum {
1346
            PitchMismatch       = 0x4000,
1347
            StyleMismatch       = 0x2000,
1348
            BitmapScaledPenalty = 0x1000,
1349
            EncodingMismatch    = 0x0002,
1350
            XLFDPenalty         = 0x0001
1351
        };
1352
#ifdef Q_WS_X11
1353
        if (encoding->encoding != -1) {
1354
            this_score += XLFDPenalty;
1355
            if (encoding->encoding != QFontPrivate::defaultEncodingID)
1356
                this_score += EncodingMismatch;
1357
        }
1358
        if (pitch != '*') {
1359
            if (!(pitch == 'm' && encoding->pitch == 'c') && pitch != encoding->pitch)
1360
                this_score += PitchMismatch;
1361
        }
1362
#else
1363
        if (pitch != '*') {
1364
#if !defined(QWS) && defined(Q_OS_MAC)
1365
            qt_mac_get_fixed_pitch(const_cast<QtFontFamily*>(family));
1366
#endif
1367
            if ((pitch == 'm' && !family->fixedPitch)
1368
                || (pitch == 'p' && family->fixedPitch))
1369
                this_score += PitchMismatch;
1370
        }
1371
#endif
1372
        if (styleKey != style->key)
1373
            this_score += StyleMismatch;
1374
        if (!style->smoothScalable && px != size->pixelSize) // bitmap scaled
1375
            this_score += BitmapScaledPenalty;
1376
        if (px != pixelSize) // close, but not exact, size match
1377
            this_score += qAbs(px - pixelSize);
1378
1379
        if (this_score < score) {
1380
            FM_DEBUG("          found a match: score %x best score so far %x",
1381
                     this_score, score);
1382
1383
            score = this_score;
1384
            desc->foundry = foundry;
1385
            desc->style = style;
1386
            desc->size = size;
1387
#ifdef Q_WS_X11
1388
            desc->encoding = encoding;
1389
#endif // Q_WS_X11
1390
        } else {
1391
            FM_DEBUG("          score %x no better than best %x", this_score, score);
1392
        }
1393
    }
1394
1395
    return score;
1396
}
1397
#endif
1398
1399
#if !defined(Q_WS_MAC)
1400
/*!
1401
    \internal
1402
1403
    Tries to find the best match for a given request and family/foundry
1404
*/
1405
static void match(int script, const QFontDef &request,
1406
                  const QString &family_name, const QString &foundry_name, int force_encoding_id,
1407
                  QtFontDesc *desc, const QList<int> &blacklistedFamilies, bool forceXLFD)
1408
{
1409
    Q_UNUSED(force_encoding_id);
1410
1411
    QtFontStyle::Key styleKey;
1412
    styleKey.style = request.style;
1413
    styleKey.weight = request.weight;
1414
    styleKey.stretch = request.stretch;
1415
    char pitch = request.ignorePitch ? '*' : request.fixedPitch ? 'm' : 'p';
1416
1417
1418
    FM_DEBUG("QFontDatabase::match\n"
1419
             "  request:\n"
1420
             "    family: %s [%s], script: %d\n"
1421
             "    weight: %d, style: %d\n"
1422
             "    stretch: %d\n"
1423
             "    pixelSize: %g\n"
1424
             "    pitch: %c",
1425
             family_name.isEmpty() ? "-- first in script --" : family_name.toLatin1().constData(),
1426
             foundry_name.isEmpty() ? "-- any --" : foundry_name.toLatin1().constData(),
1427
             script, request.weight, request.style, request.stretch, request.pixelSize, pitch);
1428
#if defined(FONT_MATCH_DEBUG) && defined(Q_WS_X11)
1429
    if (force_encoding_id >= 0) {
1430
        FM_DEBUG("    required encoding: %d", force_encoding_id);
1431
    }
1432
#endif
1433
1434
    desc->family = 0;
1435
    desc->foundry = 0;
1436
    desc->style = 0;
1437
    desc->size = 0;
1438
    desc->encoding = 0;
1439
    desc->familyIndex = -1;
1440
1441
    unsigned int score = ~0u;
1442
1443
#ifdef Q_WS_X11
1444
    load(family_name, script, forceXLFD);
1445
#else
1446
    Q_UNUSED(forceXLFD);
1447
    load(family_name, script);
1448
#endif
1449
1450
    QFontDatabasePrivate *db = privateDb();
1451
    for (int x = 0; x < db->count; ++x) {
1452
        if (blacklistedFamilies.contains(x))
1453
            continue;
1454
        QtFontDesc test;
1455
        test.family = db->families[x];
1456
        test.familyIndex = x;
1457
1458
        if (!family_name.isEmpty()
1459
            && test.family->name.compare(family_name, Qt::CaseInsensitive) != 0
1460
#ifdef Q_WS_WIN
1461
            && test.family->english_name.compare(family_name, Qt::CaseInsensitive) != 0
1462
#endif
1463
            )
1464
            continue;
1465
1466
        if (family_name.isEmpty())
1467
            load(test.family->name, script);
1468
1469
        uint score_adjust = 0;
1470
1471
        bool supported = (script == QUnicodeTables::Common);
1472
        for (int ws = 1; !supported && ws < QFontDatabase::WritingSystemsCount; ++ws) {
1473
            if (scriptForWritingSystem[ws] != script)
1474
                continue;
1475
            if (test.family->writingSystems[ws] & QtFontFamily::Supported)
1476
                supported = true;
1477
        }
1478
        if (!supported) {
1479
            // family not supported in the script we want
1480
            continue;
1481
        }
1482
1483
        // as we know the script is supported, we can be sure
1484
        // to find a matching font here.
1485
        unsigned int newscore =
1486
            bestFoundry(script, score, request.styleStrategy,
1487
                        test.family, foundry_name, styleKey, request.pixelSize, pitch,
1488
                        &test, force_encoding_id);
1489
        if (test.foundry == 0) {
1490
            // the specific foundry was not found, so look for
1491
            // any foundry matching our requirements
1492
            newscore = bestFoundry(script, score, request.styleStrategy, test.family,
1493
                                   QString(), styleKey, request.pixelSize,
1494
                                   pitch, &test, force_encoding_id);
1495
        }
1496
        newscore += score_adjust;
1497
1498
        if (newscore < score) {
1499
            score = newscore;
1500
            *desc = test;
1501
        }
1502
        if (newscore < 10) // xlfd instead of FT... just accept it
1503
            break;
1504
    }
1505
}
1506
#endif
1507
1508
static QString styleStringHelper(int weight, QFont::Style style)
1509
{
1510
    QString result;
1511
    if (weight >= QFont::Black)
1512
        result = QApplication::translate("QFontDatabase", "Black");
1513
    else if (weight >= QFont::Bold)
1514
        result = QApplication::translate("QFontDatabase", "Bold");
1515
    else if (weight >= QFont::DemiBold)
1516
        result = QApplication::translate("QFontDatabase", "Demi Bold");
1517
    else if (weight < QFont::Normal)
1518
        result = QApplication::translate("QFontDatabase", "Light");
1519
1520
    if (style == QFont::StyleItalic)
1521
        result += QLatin1Char(' ') + QApplication::translate("QFontDatabase", "Italic");
1522
    else if (style == QFont::StyleOblique)
1523
        result += QLatin1Char(' ') + QApplication::translate("QFontDatabase", "Oblique");
1524
1525
    if (result.isEmpty())
1526
        result = QApplication::translate("QFontDatabase", "Normal");
1527
1528
    return result.simplified();
1529
}
1530
1531
/*!
1532
    Returns a string that describes the style of the \a font. For
1533
    example, "Bold Italic", "Bold", "Italic" or "Normal". An empty
1534
    string may be returned.
1535
*/
1536
QString QFontDatabase::styleString(const QFont &font)
1537
{
1538
    return font.styleName().isEmpty() ? styleStringHelper(font.weight(), font.style())
1539
                                      : font.styleName();
1540
}
1541
1542
/*!
1543
    Returns a string that describes the style of the \a fontInfo. For
1544
    example, "Bold Italic", "Bold", "Italic" or "Normal". An empty
1545
    string may be returned.
1546
*/
1547
QString QFontDatabase::styleString(const QFontInfo &fontInfo)
1548
{
1549
    return fontInfo.styleName().isEmpty() ? styleStringHelper(fontInfo.weight(), fontInfo.style())
1550
                                          : fontInfo.styleName();
1551
}
1552
1553
1554
/*!
1555
    \class QFontDatabase
1556
    \threadsafe
1557
1558
    \brief The QFontDatabase class provides information about the fonts available in the underlying window system.
1559
1560
    \ingroup appearance
1561
1562
    The most common uses of this class are to query the database for
1563
    the list of font families() and for the pointSizes() and styles()
1564
    that are available for each family. An alternative to pointSizes()
1565
    is smoothSizes() which returns the sizes at which a given family
1566
    and style will look attractive.
1567
1568
    If the font family is available from two or more foundries the
1569
    foundry name is included in the family name; for example:
1570
    "Helvetica [Adobe]" and "Helvetica [Cronyx]". When you specify a
1571
    family, you can either use the old hyphenated "foundry-family"
1572
    format or the bracketed "family [foundry]" format; for example:
1573
    "Cronyx-Helvetica" or "Helvetica [Cronyx]". If the family has a
1574
    foundry it is always returned using the bracketed format, as is
1575
    the case with the value returned by families().
1576
1577
    The font() function returns a QFont given a family, style and
1578
    point size.
1579
1580
    A family and style combination can be checked to see if it is
1581
    italic() or bold(), and to retrieve its weight(). Similarly we can
1582
    call isBitmapScalable(), isSmoothlyScalable(), isScalable() and
1583
    isFixedPitch().
1584
1585
    Use the styleString() to obtain a text version of a style.
1586
1587
    The QFontDatabase class also supports some static functions, for
1588
    example, standardSizes(). You can retrieve the description of a
1589
    writing system using writingSystemName(), and a sample of
1590
    characters in a writing system with writingSystemSample().
1591
1592
    Example:
1593
1594
    \snippet doc/src/snippets/qfontdatabase/main.cpp 0
1595
    \snippet doc/src/snippets/qfontdatabase/main.cpp 1
1596
1597
    This example gets the list of font families, the list of
1598
    styles for each family, and the point sizes that are available for
1599
    each combination of family and style, displaying this information
1600
    in a tree view.
1601
1602
    \sa QFont, QFontInfo, QFontMetrics, QFontComboBox, {Character Map Example}
1603
*/
1604
1605
/*!
1606
    Creates a font database object.
1607
*/
1608
QFontDatabase::QFontDatabase()
1609
{
1610
    QMutexLocker locker(fontDatabaseMutex());
1611
    createDatabase();
1612
    d = privateDb();
1613
}
1614
1615
/*!
1616
    \enum QFontDatabase::WritingSystem
1617
1618
    \value Any
1619
    \value Latin
1620
    \value Greek
1621
    \value Cyrillic
1622
    \value Armenian
1623
    \value Hebrew
1624
    \value Arabic
1625
    \value Syriac
1626
    \value Thaana
1627
    \value Devanagari
1628
    \value Bengali
1629
    \value Gurmukhi
1630
    \value Gujarati
1631
    \value Oriya
1632
    \value Tamil
1633
    \value Telugu
1634
    \value Kannada
1635
    \value Malayalam
1636
    \value Sinhala
1637
    \value Thai
1638
    \value Lao
1639
    \value Tibetan
1640
    \value Myanmar
1641
    \value Georgian
1642
    \value Khmer
1643
    \value SimplifiedChinese
1644
    \value TraditionalChinese
1645
    \value Japanese
1646
    \value Korean
1647
    \value Vietnamese
1648
    \value Symbol
1649
    \value Other (the same as Symbol)
1650
    \value Ogham
1651
    \value Runic
1652
    \value Nko
1653
1654
    \omitvalue WritingSystemsCount
1655
*/
1656
1657
/*!
1658
    Returns a sorted list of the available writing systems. This is
1659
    list generated from information about all installed fonts on the
1660
    system.
1661
1662
    \sa families()
1663
*/
1664
QList<QFontDatabase::WritingSystem> QFontDatabase::writingSystems() const
1665
{
1666
    QMutexLocker locker(fontDatabaseMutex());
1667
1668
    QT_PREPEND_NAMESPACE(load)();
1669
#ifdef Q_WS_X11
1670
    checkSymbolFonts();
1671
#endif
1672
1673
    QList<WritingSystem> list;
1674
    for (int i = 0; i < d->count; ++i) {
1675
        QtFontFamily *family = d->families[i];
1676
        if (family->count == 0)
1677
            continue;
1678
        for (int x = Latin; x < WritingSystemsCount; ++x) {
1679
            const WritingSystem writingSystem = WritingSystem(x);
1680
            if (!(family->writingSystems[writingSystem] & QtFontFamily::Supported))
1681
                continue;
1682
            if (!list.contains(writingSystem))
1683
                list.append(writingSystem);
1684
        }
1685
    }
1686
    qSort(list);
1687
    return list;
1688
}
1689
1690
1691
/*!
1692
    Returns a sorted list of the writing systems supported by a given
1693
    font \a family.
1694
1695
    \sa families()
1696
*/
1697
QList<QFontDatabase::WritingSystem> QFontDatabase::writingSystems(const QString &family) const
1698
{
1699
    QString familyName, foundryName;
1700
    parseFontName(family, foundryName, familyName);
1701
1702
    QMutexLocker locker(fontDatabaseMutex());
1703
1704
    QT_PREPEND_NAMESPACE(load)();
1705
#ifdef Q_WS_X11
1706
    checkSymbolFonts(familyName);
1707
#endif
1708
1709
    QList<WritingSystem> list;
1710
    QtFontFamily *f = d->family(familyName);
1711
    if (!f || f->count == 0)
1712
        return list;
1713
1714
    for (int x = Latin; x < WritingSystemsCount; ++x) {
1715
        const WritingSystem writingSystem = WritingSystem(x);
1716
        if (f->writingSystems[writingSystem] & QtFontFamily::Supported)
1717
            list.append(writingSystem);
1718
    }
1719
    return list;
1720
}
1721
1722
1723
/*!
1724
    Returns a sorted list of the available font families which support
1725
    the \a writingSystem.
1726
1727
    If a family exists in several foundries, the returned name for
1728
    that font is in the form "family [foundry]". Examples: "Times
1729
    [Adobe]", "Times [Cronyx]", "Palatino".
1730
1731
    \sa writingSystems()
1732
*/
1733
QStringList QFontDatabase::families(WritingSystem writingSystem) const
1734
{
1735
    QMutexLocker locker(fontDatabaseMutex());
1736
1737
    QT_PREPEND_NAMESPACE(load)();
1738
#ifdef Q_WS_X11
1739
    if (writingSystem != Any)
1740
        checkSymbolFonts();
1741
#endif
1742
1743
    QStringList flist;
1744
    for (int i = 0; i < d->count; i++) {
1745
        QtFontFamily *f = d->families[i];
1746
        if (f->count == 0)
1747
            continue;
1748
        if (writingSystem != Any && (f->writingSystems[writingSystem] != QtFontFamily::Supported))
1749
            continue;
1750
        if (f->count == 1) {
1751
            flist.append(f->name);
1752
        } else {
1753
            for (int j = 0; j < f->count; j++) {
1754
                QString str = f->name;
1755
                QString foundry = f->foundries[j]->name;
1756
                if (!foundry.isEmpty()) {
1757
                    str += QLatin1String(" [");
1758
                    str += foundry;
1759
                    str += QLatin1Char(']');
1760
                }
1761
                flist.append(str);
1762
            }
1763
        }
1764
    }
1765
    return flist;
1766
}
1767
1768
/*!
1769
    Returns a list of the styles available for the font family \a
1770
    family. Some example styles: "Light", "Light Italic", "Bold",
1771
    "Oblique", "Demi". The list may be empty.
1772
1773
    \sa families()
1774
*/
1775
QStringList QFontDatabase::styles(const QString &family) const
1776
{
1777
    QString familyName, foundryName;
1778
    parseFontName(family, foundryName, familyName);
1779
1780
    QMutexLocker locker(fontDatabaseMutex());
1781
1782
    QT_PREPEND_NAMESPACE(load)(familyName);
1783
1784
    QStringList l;
1785
    QtFontFamily *f = d->family(familyName);
1786
    if (!f)
1787
        return l;
1788
1789
    QtFontFoundry allStyles(foundryName);
1790
    for (int j = 0; j < f->count; j++) {
1791
        QtFontFoundry *foundry = f->foundries[j];
1792
        if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1793
            for (int k = 0; k < foundry->count; k++) {
1794
                QtFontStyle::Key ke(foundry->styles[k]->key);
1795
                ke.stretch = 0;
1796
                allStyles.style(ke, foundry->styles[k]->styleName, true);
1797
            }
1798
        }
1799
    }
1800
1801
    for (int i = 0; i < allStyles.count; i++) {
1802
        l.append(allStyles.styles[i]->styleName.isEmpty() ?
1803
                 styleStringHelper(allStyles.styles[i]->key.weight,
1804
                                   (QFont::Style)allStyles.styles[i]->key.style) :
1805
                 allStyles.styles[i]->styleName);
1806
    }
1807
    return l;
1808
}
1809
1810
/*!
1811
    Returns true if the font that has family \a family and style \a
1812
    style is fixed pitch; otherwise returns false.
1813
*/
1814
1815
bool QFontDatabase::isFixedPitch(const QString &family,
1816
                                 const QString &style) const
1817
{
1818
    Q_UNUSED(style);
1819
1820
    QString familyName, foundryName;
1821
    parseFontName(family, foundryName, familyName);
1822
1823
    QMutexLocker locker(fontDatabaseMutex());
1824
1825
    QT_PREPEND_NAMESPACE(load)(familyName);
1826
1827
    QtFontFamily *f = d->family(familyName);
1828
#if !defined(QWS) && defined(Q_OS_MAC)
1829
    qt_mac_get_fixed_pitch(f);
1830
#endif
1831
    return (f && f->fixedPitch);
1832
}
1833
1834
/*!
1835
    Returns true if the font that has family \a family and style \a
1836
    style is a scalable bitmap font; otherwise returns false. Scaling
1837
    a bitmap font usually produces an unattractive hardly readable
1838
    result, because the pixels of the font are scaled. If you need to
1839
    scale a bitmap font it is better to scale it to one of the fixed
1840
    sizes returned by smoothSizes().
1841
1842
    \sa isScalable(), isSmoothlyScalable()
1843
*/
1844
bool QFontDatabase::isBitmapScalable(const QString &family,
1845
                                      const QString &style) const
1846
{
1847
    bool bitmapScalable = false;
1848
    QString familyName, foundryName;
1849
    parseFontName(family, foundryName, familyName);
1850
1851
    QMutexLocker locker(fontDatabaseMutex());
1852
1853
    QT_PREPEND_NAMESPACE(load)(familyName);
1854
1855
    QtFontStyle::Key styleKey(style);
1856
1857
    QtFontFamily *f = d->family(familyName);
1858
    if (!f) return bitmapScalable;
1859
1860
    for (int j = 0; j < f->count; j++) {
1861
        QtFontFoundry *foundry = f->foundries[j];
1862
        if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1863
            for (int k = 0; k < foundry->count; k++)
1864
                if ((style.isEmpty() ||
1865
                     foundry->styles[k]->styleName == style ||
1866
                     foundry->styles[k]->key == styleKey)
1867
                    && foundry->styles[k]->bitmapScalable && !foundry->styles[k]->smoothScalable) {
1868
                    bitmapScalable = true;
1869
                    goto end;
1870
                }
1871
        }
1872
    }
1873
 end:
1874
    return bitmapScalable;
1875
}
1876
1877
1878
/*!
1879
    Returns true if the font that has family \a family and style \a
1880
    style is smoothly scalable; otherwise returns false. If this
1881
    function returns true, it's safe to scale this font to any size,
1882
    and the result will always look attractive.
1883
1884
    \sa isScalable(), isBitmapScalable()
1885
*/
1886
bool QFontDatabase::isSmoothlyScalable(const QString &family, const QString &style) const
1887
{
1888
    bool smoothScalable = false;
1889
    QString familyName, foundryName;
1890
    parseFontName(family, foundryName, familyName);
1891
1892
    QMutexLocker locker(fontDatabaseMutex());
1893
1894
    QT_PREPEND_NAMESPACE(load)(familyName);
1895
1896
    QtFontStyle::Key styleKey(style);
1897
1898
    QtFontFamily *f = d->family(familyName);
1899
    if (!f) return smoothScalable;
1900
1901
    for (int j = 0; j < f->count; j++) {
1902
        QtFontFoundry *foundry = f->foundries[j];
1903
        if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1904
            for (int k = 0; k < foundry->count; k++)
1905
                if ((style.isEmpty() ||
1906
                     foundry->styles[k]->styleName == style ||
1907
                     foundry->styles[k]->key == styleKey) && foundry->styles[k]->smoothScalable) {
1908
                    smoothScalable = true;
1909
                    goto end;
1910
                }
1911
        }
1912
    }
1913
 end:
1914
    return smoothScalable;
1915
}
1916
1917
/*!
1918
    Returns true if the font that has family \a family and style \a
1919
    style is scalable; otherwise returns false.
1920
1921
    \sa isBitmapScalable(), isSmoothlyScalable()
1922
*/
1923
bool  QFontDatabase::isScalable(const QString &family,
1924
                                 const QString &style) const
1925
{
1926
    QMutexLocker locker(fontDatabaseMutex());
1927
    if (isSmoothlyScalable(family, style))
1928
        return true;
1929
    return isBitmapScalable(family, style);
1930
}
1931
1932
1933
/*!
1934
    \fn QList<int> QFontDatabase::pointSizes(const QString &family, const QString &style)
1935
    Returns a list of the point sizes available for the font with the
1936
    given \a family and \a style. The list may be empty.
1937
1938
    \sa smoothSizes(), standardSizes()
1939
*/
1940
QList<int> QFontDatabase::pointSizes(const QString &family,
1941
                                           const QString &styleName)
1942
{
1943
#if defined(Q_WS_WIN)
1944
    // windows and macosx are always smoothly scalable
1945
    Q_UNUSED(family);
1946
    Q_UNUSED(styleName);
1947
    return standardSizes();
1948
#else
1949
    bool smoothScalable = false;
1950
    QString familyName, foundryName;
1951
    parseFontName(family, foundryName, familyName);
1952
1953
    QMutexLocker locker(fontDatabaseMutex());
1954
1955
    QT_PREPEND_NAMESPACE(load)(familyName);
1956
1957
    QtFontStyle::Key styleKey(styleName);
1958
1959
    QList<int> sizes;
1960
1961
    QtFontFamily *fam = d->family(familyName);
1962
    if (!fam) return sizes;
1963
1964
1965
#ifdef Q_WS_X11
1966
    int dpi = QX11Info::appDpiY();
1967
#else
1968
    const int dpi = qt_defaultDpiY(); // embedded
1969
#endif
1970
1971
    for (int j = 0; j < fam->count; j++) {
1972
        QtFontFoundry *foundry = fam->foundries[j];
1973
        if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1974
            QtFontStyle *style = foundry->style(styleKey, styleName);
1975
            if (!style) continue;
1976
1977
            if (style->smoothScalable) {
1978
                smoothScalable = true;
1979
                goto end;
1980
            }
1981
            for (int l = 0; l < style->count; l++) {
1982
                const QtFontSize *size = style->pixelSizes + l;
1983
1984
                if (size->pixelSize != 0 && size->pixelSize != USHRT_MAX) {
1985
                    const uint pointSize = qRound(size->pixelSize * qreal(72.0) / dpi);
1986
                    if (! sizes.contains(pointSize))
1987
                        sizes.append(pointSize);
1988
                }
1989
            }
1990
        }
1991
    }
1992
 end:
1993
    if (smoothScalable)
1994
        return standardSizes();
1995
1996
    qSort(sizes);
1997
    return sizes;
1998
#endif
1999
}
2000
2001
/*!
2002
    Returns a QFont object that has family \a family, style \a style
2003
    and point size \a pointSize. If no matching font could be created,
2004
    a QFont object that uses the application's default font is
2005
    returned.
2006
*/
2007
QFont QFontDatabase::font(const QString &family, const QString &style,
2008
                           int pointSize) const
2009
{
2010
    QString familyName, foundryName;
2011
    parseFontName(family, foundryName, familyName);
2012
2013
    QMutexLocker locker(fontDatabaseMutex());
2014
2015
    QT_PREPEND_NAMESPACE(load)(familyName);
2016
2017
    QtFontFoundry allStyles(foundryName);
2018
    QtFontFamily *f = d->family(familyName);
2019
    if (!f) return QApplication::font();
2020
2021
    for (int j = 0; j < f->count; j++) {
2022
        QtFontFoundry *foundry = f->foundries[j];
2023
        if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
2024
            for (int k = 0; k < foundry->count; k++)
2025
                allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true);
2026
        }
2027
    }
2028
2029
    QtFontStyle::Key styleKey(style);
2030
    QtFontStyle *s = bestStyle(&allStyles, styleKey, style);
2031
2032
    if (!s) // no styles found?
2033
        return QApplication::font();
2034
2035
    QFont fnt(family, pointSize, s->key.weight);
2036
    fnt.setStyle((QFont::Style)s->key.style);
2037
    if (!s->styleName.isEmpty())
2038
        fnt.setStyleName(s->styleName);
2039
    return fnt;
2040
}
2041
2042
2043
/*!
2044
    \fn QList<int> QFontDatabase::smoothSizes(const QString &family, const QString &style)
2045
    Returns the point sizes of a font with the given \a family and \a style
2046
    that will look attractive. The list may be empty.
2047
    For non-scalable fonts and bitmap scalable fonts, this function
2048
    is equivalent to pointSizes().
2049
2050
  \sa pointSizes(), standardSizes()
2051
*/
2052
QList<int> QFontDatabase::smoothSizes(const QString &family,
2053
                                            const QString &styleName)
2054
{
2055
#ifdef Q_WS_WIN
2056
    Q_UNUSED(family);
2057
    Q_UNUSED(styleName);
2058
    return QFontDatabase::standardSizes();
2059
#else
2060
    bool smoothScalable = false;
2061
    QString familyName, foundryName;
2062
    parseFontName(family, foundryName, familyName);
2063
2064
    QMutexLocker locker(fontDatabaseMutex());
2065
2066
    QT_PREPEND_NAMESPACE(load)(familyName);
2067
2068
    QtFontStyle::Key styleKey(styleName);
2069
2070
    QList<int> sizes;
2071
2072
    QtFontFamily *fam = d->family(familyName);
2073
    if (!fam)
2074
        return sizes;
2075
2076
#ifdef Q_WS_X11
2077
    int dpi = QX11Info::appDpiY();
2078
#else
2079
    const int dpi = qt_defaultDpiY(); // embedded
2080
#endif
2081
2082
    for (int j = 0; j < fam->count; j++) {
2083
        QtFontFoundry *foundry = fam->foundries[j];
2084
        if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
2085
            QtFontStyle *style = foundry->style(styleKey, styleName);
2086
            if (!style) continue;
2087
2088
            if (style->smoothScalable) {
2089
                smoothScalable = true;
2090
                goto end;
2091
            }
2092
            for (int l = 0; l < style->count; l++) {
2093
                const QtFontSize *size = style->pixelSizes + l;
2094
2095
                if (size->pixelSize != 0 && size->pixelSize != USHRT_MAX) {
2096
                    const uint pointSize = qRound(size->pixelSize * qreal(72.0) / dpi);
2097
                    if (! sizes.contains(pointSize))
2098
                        sizes.append(pointSize);
2099
                }
2100
            }
2101
        }
2102
    }
2103
 end:
2104
    if (smoothScalable)
2105
        return QFontDatabase::standardSizes();
2106
2107
    qSort(sizes);
2108
    return sizes;
2109
#endif
2110
}
2111
2112
2113
/*!
2114
    Returns a list of standard font sizes.
2115
2116
    \sa smoothSizes(), pointSizes()
2117
*/
2118
QList<int> QFontDatabase::standardSizes()
2119
{
2120
    QList<int> ret;
2121
    static const unsigned short standard[] =
2122
        { 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72, 0 };
2123
    const unsigned short *sizes = standard;
2124
    while (*sizes) ret << *sizes++;
2125
    return ret;
2126
}
2127
2128
2129
/*!
2130
    Returns true if the font that has family \a family and style \a
2131
    style is italic; otherwise returns false.
2132
2133
    \sa weight(), bold()
2134
*/
2135
bool QFontDatabase::italic(const QString &family, const QString &style) const
2136
{
2137
    QString familyName, foundryName;
2138
    parseFontName(family, foundryName, familyName);
2139
2140
    QMutexLocker locker(fontDatabaseMutex());
2141
2142
    QT_PREPEND_NAMESPACE(load)(familyName);
2143
2144
    QtFontFoundry allStyles(foundryName);
2145
    QtFontFamily *f = d->family(familyName);
2146
    if (!f) return false;
2147
2148
    for (int j = 0; j < f->count; j++) {
2149
        QtFontFoundry *foundry = f->foundries[j];
2150
        if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
2151
            for (int k = 0; k < foundry->count; k++)
2152
                allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true);
2153
        }
2154
    }
2155
2156
    QtFontStyle::Key styleKey(style);
2157
    QtFontStyle *s = allStyles.style(styleKey, style);
2158
    return s && s->key.style == QFont::StyleItalic;
2159
}
2160
2161
2162
/*!
2163
    Returns true if the font that has family \a family and style \a
2164
    style is bold; otherwise returns false.
2165
2166
    \sa italic(), weight()
2167
*/
2168
bool QFontDatabase::bold(const QString &family,
2169
                          const QString &style) const
2170
{
2171
    QString familyName, foundryName;
2172
    parseFontName(family, foundryName, familyName);
2173
2174
    QMutexLocker locker(fontDatabaseMutex());
2175
2176
    QT_PREPEND_NAMESPACE(load)(familyName);
2177
2178
    QtFontFoundry allStyles(foundryName);
2179
    QtFontFamily *f = d->family(familyName);
2180
    if (!f) return false;
2181
2182
    for (int j = 0; j < f->count; j++) {
2183
        QtFontFoundry *foundry = f->foundries[j];
2184
        if (foundryName.isEmpty() ||
2185
            foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
2186
            for (int k = 0; k < foundry->count; k++)
2187
                allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true);
2188
        }
2189
    }
2190
2191
    QtFontStyle::Key styleKey(style);
2192
    QtFontStyle *s = allStyles.style(styleKey, style);
2193
    return s && s->key.weight >= QFont::Bold;
2194
}
2195
2196
2197
/*!
2198
    Returns the weight of the font that has family \a family and style
2199
    \a style. If there is no such family and style combination,
2200
    returns -1.
2201
2202
    \sa italic(), bold()
2203
*/
2204
int QFontDatabase::weight(const QString &family,
2205
                           const QString &style) const
2206
{
2207
    QString familyName, foundryName;
2208
    parseFontName(family, foundryName, familyName);
2209
2210
    QMutexLocker locker(fontDatabaseMutex());
2211
2212
    QT_PREPEND_NAMESPACE(load)(familyName);
2213
2214
    QtFontFoundry allStyles(foundryName);
2215
    QtFontFamily *f = d->family(familyName);
2216
    if (!f) return -1;
2217
2218
    for (int j = 0; j < f->count; j++) {
2219
        QtFontFoundry *foundry = f->foundries[j];
2220
        if (foundryName.isEmpty() ||
2221
            foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
2222
            for (int k = 0; k < foundry->count; k++)
2223
                allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true);
2224
        }
2225
    }
2226
2227
    QtFontStyle::Key styleKey(style);
2228
    QtFontStyle *s = allStyles.style(styleKey, style);
2229
    return s ? s->key.weight : -1;
2230
}
2231
2232
2233
/*! \internal */
2234
bool QFontDatabase::hasFamily(const QString &family) const
2235
{
2236
    QString parsedFamily, foundry;
2237
    parseFontName(family, foundry, parsedFamily);
2238
    const QString familyAlias = resolveFontFamilyAlias(parsedFamily);
2239
    return families().contains(familyAlias, Qt::CaseInsensitive);
2240
}
2241
2242
2243
/*!
2244
    Returns the names the \a writingSystem (e.g. for displaying to the
2245
    user in a dialog).
2246
*/
2247
QString QFontDatabase::writingSystemName(WritingSystem writingSystem)
2248
{
2249
    const char *name = 0;
2250
    switch (writingSystem) {
2251
    case Any:
2252
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Any");
2253
        break;
2254
    case Latin:
2255
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Latin");
2256
        break;
2257
    case Greek:
2258
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Greek");
2259
        break;
2260
    case Cyrillic:
2261
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Cyrillic");
2262
        break;
2263
    case Armenian:
2264
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Armenian");
2265
        break;
2266
    case Hebrew:
2267
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Hebrew");
2268
        break;
2269
    case Arabic:
2270
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Arabic");
2271
        break;
2272
    case Syriac:
2273
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Syriac");
2274
        break;
2275
    case Thaana:
2276
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Thaana");
2277
        break;
2278
    case Devanagari:
2279
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Devanagari");
2280
        break;
2281
    case Bengali:
2282
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Bengali");
2283
        break;
2284
    case Gurmukhi:
2285
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Gurmukhi");
2286
        break;
2287
    case Gujarati:
2288
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Gujarati");
2289
        break;
2290
    case Oriya:
2291
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Oriya");
2292
        break;
2293
    case Tamil:
2294
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Tamil");
2295
        break;
2296
    case Telugu:
2297
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Telugu");
2298
        break;
2299
    case Kannada:
2300
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Kannada");
2301
        break;
2302
    case Malayalam:
2303
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Malayalam");
2304
        break;
2305
    case Sinhala:
2306
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Sinhala");
2307
        break;
2308
    case Thai:
2309
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Thai");
2310
        break;
2311
    case Lao:
2312
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Lao");
2313
        break;
2314
    case Tibetan:
2315
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Tibetan");
2316
        break;
2317
    case Myanmar:
2318
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Myanmar");
2319
        break;
2320
    case Georgian:
2321
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Georgian");
2322
        break;
2323
    case Khmer:
2324
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Khmer");
2325
        break;
2326
    case SimplifiedChinese:
2327
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Simplified Chinese");
2328
        break;
2329
    case TraditionalChinese:
2330
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Traditional Chinese");
2331
        break;
2332
    case Japanese:
2333
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Japanese");
2334
        break;
2335
    case Korean:
2336
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Korean");
2337
        break;
2338
    case Vietnamese:
2339
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Vietnamese");
2340
        break;
2341
    case Symbol:
2342
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Symbol");
2343
        break;
2344
    case Ogham:
2345
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Ogham");
2346
        break;
2347
    case Runic:
2348
        name = QT_TRANSLATE_NOOP("QFontDatabase", "Runic");
2349
        break;
2350
    case Nko:
2351
        name = QT_TRANSLATE_NOOP("QFontDatabase", "N'Ko");
2352
        break;
2353
    default:
2354
        Q_ASSERT_X(false, "QFontDatabase::writingSystemName", "invalid 'writingSystem' parameter");
2355
        break;
2356
    }
2357
    return QApplication::translate("QFontDatabase", name);
2358
}
2359
2360
2361
/*!
2362
    Returns a string with sample characters from \a writingSystem.
2363
*/
2364
QString QFontDatabase::writingSystemSample(WritingSystem writingSystem)
2365
{
2366
    QString sample;
2367
    switch (writingSystem) {
2368
    case Any:
2369
    case Symbol:
2370
        // show only ascii characters
2371
        sample += QLatin1String("AaBbzZ");
2372
        break;
2373
    case Latin:
2374
        // This is cheating... we only show latin-1 characters so that we don't
2375
        // end up loading lots of fonts - at least on X11...
2376
        sample = QLatin1String("Aa");
2377
        sample += QChar(0x00C3);
2378
        sample += QChar(0x00E1);
2379
        sample += QLatin1String("Zz");
2380
        break;
2381
    case Greek:
2382
        sample += QChar(0x0393);
2383
        sample += QChar(0x03B1);
2384
        sample += QChar(0x03A9);
2385
        sample += QChar(0x03C9);
2386
        break;
2387
    case Cyrillic:
2388
        sample += QChar(0x0414);
2389
        sample += QChar(0x0434);
2390
        sample += QChar(0x0436);
2391
        sample += QChar(0x044f);
2392
        break;
2393
    case Armenian:
2394
        sample += QChar(0x053f);
2395
        sample += QChar(0x054f);
2396
        sample += QChar(0x056f);
2397
        sample += QChar(0x057f);
2398
        break;
2399
    case Hebrew:
2400
        sample += QChar(0x05D0);
2401
        sample += QChar(0x05D1);
2402
        sample += QChar(0x05D2);
2403
        sample += QChar(0x05D3);
2404
        break;
2405
    case Arabic:
2406
        sample += QChar(0x0628);
2407
        sample += QChar(0x0629);
2408
        sample += QChar(0x062A);
2409
        sample += QChar(0x063A);
2410
        break;
2411
    case Syriac:
2412
        sample += QChar(0x0715);
2413
        sample += QChar(0x0725);
2414
        sample += QChar(0x0716);
2415
        sample += QChar(0x0726);
2416
        break;
2417
    case Thaana:
2418
        sample += QChar(0x0784);
2419
        sample += QChar(0x0794);
2420
        sample += QChar(0x078c);
2421
        sample += QChar(0x078d);
2422
        break;
2423
    case Devanagari:
2424
        sample += QChar(0x0905);
2425
        sample += QChar(0x0915);
2426
        sample += QChar(0x0925);
2427
        sample += QChar(0x0935);
2428
        break;
2429
    case Bengali:
2430
        sample += QChar(0x0986);
2431
        sample += QChar(0x0996);
2432
        sample += QChar(0x09a6);
2433
        sample += QChar(0x09b6);
2434
        break;
2435
    case Gurmukhi:
2436
        sample += QChar(0x0a05);
2437
        sample += QChar(0x0a15);
2438
        sample += QChar(0x0a25);
2439
        sample += QChar(0x0a35);
2440
        break;
2441
    case Gujarati:
2442
        sample += QChar(0x0a85);
2443
        sample += QChar(0x0a95);
2444
        sample += QChar(0x0aa5);
2445
        sample += QChar(0x0ab5);
2446
        break;
2447
    case Oriya:
2448
        sample += QChar(0x0b06);
2449
        sample += QChar(0x0b16);
2450
        sample += QChar(0x0b2b);
2451
        sample += QChar(0x0b36);
2452
        break;
2453
    case Tamil:
2454
        sample += QChar(0x0b89);
2455
        sample += QChar(0x0b99);
2456
        sample += QChar(0x0ba9);
2457
        sample += QChar(0x0bb9);
2458
        break;
2459
    case Telugu:
2460
        sample += QChar(0x0c05);
2461
        sample += QChar(0x0c15);
2462
        sample += QChar(0x0c25);
2463
        sample += QChar(0x0c35);
2464
        break;
2465
    case Kannada:
2466
        sample += QChar(0x0c85);
2467
        sample += QChar(0x0c95);
2468
        sample += QChar(0x0ca5);
2469
        sample += QChar(0x0cb5);
2470
        break;
2471
    case Malayalam:
2472
        sample += QChar(0x0d05);
2473
        sample += QChar(0x0d15);
2474
        sample += QChar(0x0d25);
2475
        sample += QChar(0x0d35);
2476
        break;
2477
    case Sinhala:
2478
        sample += QChar(0x0d90);
2479
        sample += QChar(0x0da0);
2480
        sample += QChar(0x0db0);
2481
        sample += QChar(0x0dc0);
2482
        break;
2483
    case Thai:
2484
        sample += QChar(0x0e02);
2485
        sample += QChar(0x0e12);
2486
        sample += QChar(0x0e22);
2487
        sample += QChar(0x0e32);
2488
        break;
2489
    case Lao:
2490
        sample += QChar(0x0e8d);
2491
        sample += QChar(0x0e9d);
2492
        sample += QChar(0x0ead);
2493
        sample += QChar(0x0ebd);
2494
        break;
2495
    case Tibetan:
2496
        sample += QChar(0x0f00);
2497
        sample += QChar(0x0f01);
2498
        sample += QChar(0x0f02);
2499
        sample += QChar(0x0f03);
2500
        break;
2501
    case Myanmar:
2502
        sample += QChar(0x1000);
2503
        sample += QChar(0x1001);
2504
        sample += QChar(0x1002);
2505
        sample += QChar(0x1003);
2506
        break;
2507
    case Georgian:
2508
        sample += QChar(0x10a0);
2509
        sample += QChar(0x10b0);
2510
        sample += QChar(0x10c0);
2511
        sample += QChar(0x10d0);
2512
        break;
2513
    case Khmer:
2514
        sample += QChar(0x1780);
2515
        sample += QChar(0x1790);
2516
        sample += QChar(0x17b0);
2517
        sample += QChar(0x17c0);
2518
        break;
2519
    case SimplifiedChinese:
2520
        sample += QChar(0x4e2d);
2521
        sample += QChar(0x6587);
2522
        sample += QChar(0x8303);
2523
        sample += QChar(0x4f8b);
2524
        break;
2525
    case TraditionalChinese:
2526
        sample += QChar(0x4e2d);
2527
        sample += QChar(0x6587);
2528
        sample += QChar(0x7bc4);
2529
        sample += QChar(0x4f8b);
2530
        break;
2531
    case Japanese:
2532
        sample += QChar(0x30b5);
2533
        sample += QChar(0x30f3);
2534
        sample += QChar(0x30d7);
2535
        sample += QChar(0x30eb);
2536
        sample += QChar(0x3067);
2537
        sample += QChar(0x3059);
2538
        break;
2539
    case Korean:
2540
        sample += QChar(0xac00);
2541
        sample += QChar(0xac11);
2542
        sample += QChar(0xac1a);
2543
        sample += QChar(0xac2f);
2544
        break;
2545
    case Vietnamese:
2546
    {
2547
        static const char vietnameseUtf8[] = {
2548
            char(0xef), char(0xbb), char(0xbf), char(0xe1), char(0xbb), char(0x97),
2549
            char(0xe1), char(0xbb), char(0x99),
2550
            char(0xe1), char(0xbb), char(0x91),
2551
            char(0xe1), char(0xbb), char(0x93),
2552
        };
2553
        sample += QString::fromUtf8(vietnameseUtf8, sizeof(vietnameseUtf8));
2554
        break;
2555
    }
2556
    case Ogham:
2557
        sample += QChar(0x1681);
2558
        sample += QChar(0x1682);
2559
        sample += QChar(0x1683);
2560
        sample += QChar(0x1684);
2561
        break;
2562
    case Runic:
2563
        sample += QChar(0x16a0);
2564
        sample += QChar(0x16a1);
2565
        sample += QChar(0x16a2);
2566
        sample += QChar(0x16a3);
2567
        break;
2568
    case Nko:
2569
        sample += QChar(0x7ca);
2570
        sample += QChar(0x7cb);
2571
        sample += QChar(0x7cc);
2572
        sample += QChar(0x7cd);
2573
        break;
2574
    default:
2575
        break;
2576
    }
2577
    return sample;
2578
}
2579
2580
2581
void QFontDatabase::parseFontName(const QString &name, QString &foundry, QString &family)
2582
{
2583
    QT_PREPEND_NAMESPACE(parseFontName)(name, foundry, family);
2584
}
2585
2586
void QFontDatabase::createDatabase()
2587
{ initializeDb(); }
2588
2589
// used from qfontengine_ft.cpp
2590
Q_GUI_EXPORT QByteArray qt_fontdata_from_index(int index)
2591
{
2592
    QMutexLocker locker(fontDatabaseMutex());
2593
    return privateDb()->applicationFonts.value(index).data;
2594
}
2595
2596
int QFontDatabasePrivate::addAppFont(const QByteArray &fontData, const QString &fileName)
2597
{
2598
    QFontDatabasePrivate::ApplicationFont font;
2599
    font.data = fontData;
2600
    font.fileName = fileName;
2601
2602
    int i;
2603
    for (i = 0; i < applicationFonts.count(); ++i)
2604
        if (applicationFonts.at(i).families.isEmpty())
2605
            break;
2606
    if (i >= applicationFonts.count()) {
2607
        applicationFonts.append(ApplicationFont());
2608
        i = applicationFonts.count() - 1;
2609
    }
2610
2611
    if (font.fileName.isEmpty() && !fontData.isEmpty())
2612
        font.fileName = QString::fromLatin1(":qmemoryfonts/") + QString::number(i);
2613
2614
    registerFont(&font);
2615
    if (font.families.isEmpty())
2616
        return -1;
2617
2618
    applicationFonts[i] = font;
2619
2620
    invalidate();
2621
    return i;
2622
}
2623
2624
bool QFontDatabasePrivate::isApplicationFont(const QString &fileName)
2625
{
2626
    for (int i = 0; i < applicationFonts.count(); ++i)
2627
        if (applicationFonts.at(i).fileName == fileName)
2628
            return true;
2629
    return false;
2630
}
2631
2632
/*!
2633
    \since 4.2
2634
2635
    Loads the font from the file specified by \a fileName and makes it available to
2636
    the application. An ID is returned that can be used to remove the font again
2637
    with removeApplicationFont() or to retrieve the list of family names contained
2638
    in the font.
2639
2640
    The function returns -1 if the font could not be loaded.
2641
2642
    Currently only TrueType fonts, TrueType font collections, and OpenType fonts are
2643
    supported.
2644
2645
    \note Adding application fonts on Unix/X11 platforms without fontconfig is
2646
    currently not supported.
2647
2648
    \note On Symbian, the font family names get truncated to a length of 20 characters.
2649
2650
    \sa addApplicationFontFromData(), applicationFontFamilies(), removeApplicationFont()
2651
*/
2652
int QFontDatabase::addApplicationFont(const QString &fileName)
2653
{
2654
    QByteArray data;
2655
    QFile f(fileName);
2656
    if (!(f.fileEngine()->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::LocalDiskFlag)) {
2657
        if (!f.open(QIODevice::ReadOnly))
2658
            return -1;
2659
        data = f.readAll();
2660
    }
2661
    QMutexLocker locker(fontDatabaseMutex());
2662
    return privateDb()->addAppFont(data, fileName);
2663
}
2664
2665
/*!
2666
    \since 4.2
2667
2668
    Loads the font from binary data specified by \a fontData and makes it available to
2669
    the application. An ID is returned that can be used to remove the font again
2670
    with removeApplicationFont() or to retrieve the list of family names contained
2671
    in the font.
2672
2673
    The function returns -1 if the font could not be loaded.
2674
2675
    Currently only TrueType fonts and TrueType font collections are supported.
2676
2677
    \bold{Note:} Adding application fonts on Unix/X11 platforms without fontconfig is
2678
    currently not supported.
2679
2680
    \note On Symbian, the font family names get truncated to a length of 20 characters.
2681
2682
    \sa addApplicationFont(), applicationFontFamilies(), removeApplicationFont()
2683
*/
2684
int QFontDatabase::addApplicationFontFromData(const QByteArray &fontData)
2685
{
2686
    QMutexLocker locker(fontDatabaseMutex());
2687
    return privateDb()->addAppFont(fontData, QString() /* fileName */);
2688
}
2689
2690
/*!
2691
    \since 4.2
2692
2693
    Returns a list of font families for the given application font identified by
2694
    \a id.
2695
2696
    \sa addApplicationFont(), addApplicationFontFromData()
2697
*/
2698
QStringList QFontDatabase::applicationFontFamilies(int id)
2699
{
2700
    QMutexLocker locker(fontDatabaseMutex());
2701
    return privateDb()->applicationFonts.value(id).families;
2702
}
2703
2704
/*!
2705
    \fn bool QFontDatabase::removeApplicationFont(int id)
2706
    \since 4.2
2707
2708
    Removes the previously loaded application font identified by \a
2709
    id. Returns true if unloading of the font succeeded; otherwise
2710
    returns false.
2711
2712
    \sa removeAllApplicationFonts(), addApplicationFont(),
2713
        addApplicationFontFromData()
2714
*/
2715
2716
/*!
2717
    \fn bool QFontDatabase::removeAllApplicationFonts()
2718
    \since 4.2
2719
2720
    Removes all application-local fonts previously added using addApplicationFont()
2721
    and addApplicationFontFromData().
2722
2723
    Returns true if unloading of the fonts succeeded; otherwise
2724
    returns false.
2725
2726
    \sa removeApplicationFont(), addApplicationFont(), addApplicationFontFromData()
2727
*/
2728
2729
/*!
2730
    \fn bool QFontDatabase::supportsThreadedFontRendering()
2731
    \since 4.4
2732
2733
    Returns true if font rendering is supported outside the GUI
2734
    thread, false otherwise. In other words, a return value of false
2735
    means that all QPainter::drawText() calls outside the GUI thread
2736
    will not produce readable output.
2737
2738
    \sa {Thread-Support in Qt Modules#Painting In Threads}{Painting In Threads}
2739
*/
2740
2741
2742
QT_END_NAMESPACE