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