Export QTextImageHandler and add accessor for image
[profile/ivi/qtbase.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 "qguiapplication.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/qguiapplication_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(QCoreApplication::translate("QFontDatabase", "Normal"), Qt::CaseInsensitive) == 0)
107         return QFont::Normal;
108     if (s == QLatin1String("bold")
109         || s.compare(QCoreApplication::translate("QFontDatabase", "Bold"), Qt::CaseInsensitive) == 0)
110         return QFont::Bold;
111     if (s == QLatin1String("demibold") || s == QLatin1String("demi bold")
112         || s.compare(QCoreApplication::translate("QFontDatabase", "Demi Bold"), Qt::CaseInsensitive) == 0)
113         return QFont::DemiBold;
114     if (s == QLatin1String("black")
115         || s.compare(QCoreApplication::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(QCoreApplication::translate("QFontDatabase", "Bold"), Qt::CaseInsensitive)) {
122         if (s.contains(QLatin1String("demi"))
123             || s.compare(QCoreApplication::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(QCoreApplication::translate("QFontDatabase", "Light"), Qt::CaseInsensitive) == 0)
130         return (int) QFont::Light;
131
132     if (s.contains(QLatin1String("black"))
133         || s.compare(QCoreApplication::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 = QGuiApplicationPrivate::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(QCoreApplication::translate("QFontDatabase", "Italic")))
300         style = QFont::StyleItalic;
301     else if (styleString.contains(QLatin1String("Oblique"))
302              || styleString.contains(QCoreApplication::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     bool loadFromCache(const QString &fontPath);
733     void addQPF2File(const QByteArray &file);
734 #endif // Q_WS_QWS
735 #if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
736     void addFont(const QString &familyname, const char *foundryname, int weight,
737                  bool italic, int pixelSize, const QByteArray &file, int fileIndex,
738                  bool antialiased,
739                  const QList<QFontDatabase::WritingSystem> &writingSystems = QList<QFontDatabase::WritingSystem>());
740 #ifndef QT_NO_FREETYPE
741     QStringList addTTFile(const QByteArray &file, const QByteArray &fontData = QByteArray());
742 #endif // QT_NO_FREETYPE
743 #endif
744 #if defined(Q_WS_QWS)
745     QDataStream *stream;
746 #elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
747     QSymbianFontDatabaseExtras *symbianExtras;
748 #endif
749 #if defined(Q_WS_QWS) || defined(Q_WS_QPA)
750     QStringList fallbackFamilies;
751 #endif
752 };
753
754 void QFontDatabasePrivate::invalidate()
755 {
756     QFontCache::instance()->clear();
757     free();
758     emit static_cast<QGuiApplication *>(QCoreApplication::instance())->fontDatabaseChanged();
759 }
760
761 QtFontFamily *QFontDatabasePrivate::family(const QString &f, bool create)
762 {
763     int low = 0;
764     int high = count;
765     int pos = count / 2;
766     int res = 1;
767     if (count) {
768         while ((res = families[pos]->name.compare(f, Qt::CaseInsensitive)) && pos != low) {
769             if (res > 0)
770                 high = pos;
771             else
772                 low = pos;
773             pos = (high + low) / 2;
774         }
775         if (!res)
776             return families[pos];
777     }
778     if (!create)
779         return 0;
780
781     if (res < 0)
782         pos++;
783
784     // qDebug("adding family %s at %d total=%d", f.latin1(), pos, count);
785     if (!(count % 8)) {
786         QtFontFamily **newFamilies = (QtFontFamily **)
787                    realloc(families,
788                             (((count+8) >> 3) << 3) * sizeof(QtFontFamily *));
789         Q_CHECK_PTR(newFamilies);
790         families = newFamilies;
791     }
792
793     QtFontFamily *family = new QtFontFamily(f);
794     memmove(families + pos + 1, families + pos, (count-pos)*sizeof(QtFontFamily *));
795     families[pos] = family;
796     count++;
797     return families[pos];
798 }
799
800 #if defined(Q_WS_QWS) ||  defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
801 void QFontDatabasePrivate::addFont(const QString &familyname, const char *foundryname, int weight, bool italic, int pixelSize,
802                                    const QByteArray &file, int fileIndex, bool antialiased,
803                                    const QList<QFontDatabase::WritingSystem> &writingSystems)
804 {
805 //    qDebug() << "Adding font" << familyname << weight << italic << pixelSize << file << fileIndex << antialiased;
806     QtFontStyle::Key styleKey;
807     styleKey.style = italic ? QFont::StyleItalic : QFont::StyleNormal;
808     styleKey.weight = weight;
809     styleKey.stretch = 100;
810     QtFontFamily *f = family(familyname, true);
811
812     if (writingSystems.isEmpty()) {
813         for (int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws) {
814             f->writingSystems[ws] = QtFontFamily::Supported;
815         }
816         f->bogusWritingSystems = true;
817     } else {
818         for (int i = 0; i < writingSystems.count(); ++i) {
819             f->writingSystems[writingSystems.at(i)] = QtFontFamily::Supported;
820         }
821     }
822
823     QtFontFoundry *foundry = f->foundry(QString::fromLatin1(foundryname), true);
824     QtFontStyle *style = foundry->style(styleKey, QString(), true);
825     style->smoothScalable = (pixelSize == 0);
826     style->antialiased = antialiased;
827     QtFontSize *size = style->pixelSize(pixelSize?pixelSize:SMOOTH_SCALABLE, true);
828     size->fileName = file;
829     size->fileIndex = fileIndex;
830
831 #if defined(Q_WS_QWS)
832     if (stream) {
833         *stream << familyname << foundry->name << weight << quint8(italic) << pixelSize
834                 << file << fileIndex << quint8(antialiased);
835         *stream << quint8(writingSystems.count());
836         for (int i = 0; i < writingSystems.count(); ++i)
837             *stream << quint8(writingSystems.at(i));
838     }
839 #else // ..in case of defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
840     f->fontFilename = file;
841     f->fontFileIndex = fileIndex;
842 #endif
843 }
844 #endif
845
846 #if (defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE)
847 QStringList QFontDatabasePrivate::addTTFile(const QByteArray &file, const QByteArray &fontData)
848 {
849     QStringList families;
850     extern FT_Library qt_getFreetype();
851     FT_Library library = qt_getFreetype();
852
853     int index = 0;
854     int numFaces = 0;
855     do {
856         FT_Face face;
857         FT_Error error;
858         if (!fontData.isEmpty()) {
859             error = FT_New_Memory_Face(library, (const FT_Byte *)fontData.constData(), fontData.size(), index, &face);
860         } else {
861             error = FT_New_Face(library, file, index, &face);
862         }
863         if (error != FT_Err_Ok) {
864             qDebug() << "FT_New_Face failed with index" << index << ":" << hex << error;
865             break;
866         }
867         numFaces = face->num_faces;
868
869         int weight = QFont::Normal;
870         bool italic = face->style_flags & FT_STYLE_FLAG_ITALIC;
871
872         if (face->style_flags & FT_STYLE_FLAG_BOLD)
873             weight = QFont::Bold;
874
875         QList<QFontDatabase::WritingSystem> writingSystems;
876         // detect symbol fonts
877         for (int i = 0; i < face->num_charmaps; ++i) {
878             FT_CharMap cm = face->charmaps[i];
879             if (cm->encoding == ft_encoding_adobe_custom
880                     || cm->encoding == ft_encoding_symbol) {
881                 writingSystems.append(QFontDatabase::Symbol);
882                 break;
883             }
884         }
885         if (writingSystems.isEmpty()) {
886             TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2);
887             if (os2) {
888                 quint32 unicodeRange[4] = {
889                     static_cast<quint32>(os2->ulUnicodeRange1), static_cast<quint32>(os2->ulUnicodeRange2), static_cast<quint32>(os2->ulUnicodeRange3), static_cast<quint32>(os2->ulUnicodeRange4)
890                 };
891                 quint32 codePageRange[2] = {
892                     static_cast<quint32>(os2->ulCodePageRange1), static_cast<quint32>(os2->ulCodePageRange2)
893                 };
894
895                 writingSystems = qt_determine_writing_systems_from_truetype_bits(unicodeRange, codePageRange);
896                 //for (int i = 0; i < writingSystems.count(); ++i)
897                 //    qDebug() << QFontDatabase::writingSystemName(writingSystems.at(i));
898             }
899         }
900
901         QString family = QString::fromAscii(face->family_name);
902         families.append(family);
903         addFont(family, /*foundry*/ "", weight, italic,
904                 /*pixelsize*/ 0, file, index, /*antialias*/ true, writingSystems);
905
906         FT_Done_Face(face);
907         ++index;
908     } while (index < numFaces);
909     return families;
910 }
911 #endif
912
913 static const int scriptForWritingSystem[] = {
914     QUnicodeTables::Common, // Any
915     QUnicodeTables::Latin, // Latin
916     QUnicodeTables::Greek, // Greek
917     QUnicodeTables::Cyrillic, // Cyrillic
918     QUnicodeTables::Armenian, // Armenian
919     QUnicodeTables::Hebrew, // Hebrew
920     QUnicodeTables::Arabic, // Arabic
921     QUnicodeTables::Syriac, // Syriac
922     QUnicodeTables::Thaana, // Thaana
923     QUnicodeTables::Devanagari, // Devanagari
924     QUnicodeTables::Bengali, // Bengali
925     QUnicodeTables::Gurmukhi, // Gurmukhi
926     QUnicodeTables::Gujarati, // Gujarati
927     QUnicodeTables::Oriya, // Oriya
928     QUnicodeTables::Tamil, // Tamil
929     QUnicodeTables::Telugu, // Telugu
930     QUnicodeTables::Kannada, // Kannada
931     QUnicodeTables::Malayalam, // Malayalam
932     QUnicodeTables::Sinhala, // Sinhala
933     QUnicodeTables::Thai, // Thai
934     QUnicodeTables::Lao, // Lao
935     QUnicodeTables::Tibetan, // Tibetan
936     QUnicodeTables::Myanmar, // Myanmar
937     QUnicodeTables::Georgian, // Georgian
938     QUnicodeTables::Khmer, // Khmer
939     QUnicodeTables::Common, // SimplifiedChinese
940     QUnicodeTables::Common, // TraditionalChinese
941     QUnicodeTables::Common, // Japanese
942     QUnicodeTables::Hangul, // Korean
943     QUnicodeTables::Common, // Vietnamese
944     QUnicodeTables::Common, // Yi
945     QUnicodeTables::Common, // Tagalog
946     QUnicodeTables::Common, // Hanunoo
947     QUnicodeTables::Common, // Buhid
948     QUnicodeTables::Common, // Tagbanwa
949     QUnicodeTables::Common, // Limbu
950     QUnicodeTables::Common, // TaiLe
951     QUnicodeTables::Common, // Braille
952     QUnicodeTables::Common, // Symbol
953     QUnicodeTables::Ogham,  // Ogham
954     QUnicodeTables::Runic, // Runic
955     QUnicodeTables::Nko // Nko
956 };
957
958 int qt_script_for_writing_system(QFontDatabase::WritingSystem writingSystem)
959 {
960     return scriptForWritingSystem[writingSystem];
961 }
962
963
964 #if defined Q_WS_QWS || (defined(Q_WS_X11) && !defined(QT_NO_FONTCONFIG)) || defined(Q_WS_WIN)
965 static inline bool requiresOpenType(int writingSystem)
966 {
967     return ((writingSystem >= QFontDatabase::Syriac && writingSystem <= QFontDatabase::Sinhala)
968             || writingSystem == QFontDatabase::Khmer || writingSystem == QFontDatabase::Nko);
969 }
970 static inline bool scriptRequiresOpenType(int script)
971 {
972     return ((script >= QUnicodeTables::Syriac && script <= QUnicodeTables::Sinhala)
973             || script == QUnicodeTables::Khmer || script == QUnicodeTables::Nko);
974 }
975 #endif
976
977
978 /*!
979   \internal
980
981   This makes sense of the font family name:
982
983   if the family name contains a '[' and a ']', then we take the text
984   between the square brackets as the foundry, and the text before the
985   square brackets as the family (ie. "Arial [Monotype]")
986 */
987 static void parseFontName(const QString &name, QString &foundry, QString &family)
988 {
989     int i = name.indexOf(QLatin1Char('['));
990     int li = name.lastIndexOf(QLatin1Char(']'));
991     if (i >= 0 && li >= 0 && i < li) {
992         foundry = name.mid(i + 1, li - i - 1);
993         if (i > 0 && name[i - 1] == QLatin1Char(' '))
994             i--;
995         family = name.left(i);
996     } else {
997         foundry.clear();
998         family = name;
999     }
1000
1001     // capitalize the family/foundry names
1002     bool space = true;
1003     QChar *s = family.data();
1004     int len = family.length();
1005     while(len--) {
1006         if (space) *s = s->toUpper();
1007         space = s->isSpace();
1008         ++s;
1009     }
1010
1011     space = true;
1012     s = foundry.data();
1013     len = foundry.length();
1014     while(len--) {
1015         if (space) *s = s->toUpper();
1016         space = s->isSpace();
1017         ++s;
1018     }
1019 }
1020
1021
1022 struct QtFontDesc
1023 {
1024     inline QtFontDesc() : family(0), foundry(0), style(0), size(0), encoding(0), familyIndex(-1) {}
1025     QtFontFamily *family;
1026     QtFontFoundry *foundry;
1027     QtFontStyle *style;
1028     QtFontSize *size;
1029     QtFontEncoding *encoding;
1030     int familyIndex;
1031 };
1032
1033 #if !defined(Q_WS_MAC)
1034 static void match(int script, const QFontDef &request,
1035                   const QString &family_name, const QString &foundry_name, int force_encoding_id,
1036                   QtFontDesc *desc, const QList<int> &blacklistedFamilies = QList<int>(), bool forceXLFD=false);
1037
1038 #if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_QPA)
1039 static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDef *fontDef)
1040 {
1041     fontDef->family = desc.family->name;
1042     if (! desc.foundry->name.isEmpty() && desc.family->count > 1) {
1043         fontDef->family += QString::fromLatin1(" [");
1044         fontDef->family += desc.foundry->name;
1045         fontDef->family += QLatin1Char(']');
1046     }
1047
1048     if (desc.style->smoothScalable)
1049         fontDef->pixelSize = request.pixelSize;
1050     else if ((desc.style->bitmapScalable && (request.styleStrategy & QFont::PreferMatch)))
1051         fontDef->pixelSize = request.pixelSize;
1052     else
1053         fontDef->pixelSize = desc.size->pixelSize;
1054
1055     fontDef->styleHint     = request.styleHint;
1056     fontDef->styleStrategy = request.styleStrategy;
1057
1058     fontDef->weight        = desc.style->key.weight;
1059     fontDef->style         = desc.style->key.style;
1060     fontDef->fixedPitch    = desc.family->fixedPitch;
1061     fontDef->stretch       = desc.style->key.stretch;
1062     fontDef->ignorePitch   = false;
1063 }
1064 #endif
1065 #endif
1066
1067 #if defined(Q_WS_X11) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) || defined(Q_WS_QPA)
1068 static void getEngineData(const QFontPrivate *d, const QFontCache::Key &key)
1069 {
1070     // look for the requested font in the engine data cache
1071     d->engineData = QFontCache::instance()->findEngineData(key);
1072     if (!d->engineData) {
1073         // create a new one
1074         d->engineData = new QFontEngineData;
1075         QFontCache::instance()->insertEngineData(key, d->engineData);
1076     } else {
1077         d->engineData->ref.ref();
1078     }
1079 }
1080 #endif
1081
1082 static QStringList familyList(const QFontDef &req)
1083 {
1084     // list of families to try
1085     QStringList family_list;
1086     if (req.family.isEmpty())
1087         return family_list;
1088
1089     QStringList list = req.family.split(QLatin1Char(','));
1090     for (int i = 0; i < list.size(); ++i) {
1091         QString str = list.at(i).trimmed();
1092         if ((str.startsWith(QLatin1Char('"')) && str.endsWith(QLatin1Char('"')))
1093             || (str.startsWith(QLatin1Char('\'')) && str.endsWith(QLatin1Char('\''))))
1094             str = str.mid(1, str.length() - 2);
1095         family_list << str;
1096     }
1097
1098     // append the substitute list for each family in family_list
1099     QStringList subs_list;
1100     QStringList::ConstIterator it = family_list.constBegin(), end = family_list.constEnd();
1101     for (; it != end; ++it)
1102         subs_list += QFont::substitutes(*it);
1103 //         qDebug() << "adding substs: " << subs_list;
1104
1105     family_list += subs_list;
1106
1107     return family_list;
1108 }
1109
1110 Q_GLOBAL_STATIC(QFontDatabasePrivate, privateDb)
1111 Q_GLOBAL_STATIC_WITH_ARGS(QMutex, fontDatabaseMutex, (QMutex::Recursive))
1112
1113 // used in qfontengine_x11.cpp
1114 QMutex *qt_fontdatabase_mutex()
1115 {
1116     return fontDatabaseMutex();
1117 }
1118
1119 QT_BEGIN_INCLUDE_NAMESPACE
1120 #if defined(Q_WS_X11)
1121 #  include "qfontdatabase_x11.cpp"
1122 #elif defined(Q_WS_MAC)
1123 #  include "qfontdatabase_mac.cpp"
1124 #elif defined(Q_WS_WIN)
1125 #  include "qfontdatabase_win.cpp"
1126 #elif defined(Q_WS_QWS)
1127 #  include "qfontdatabase_qws.cpp"
1128 #elif defined(Q_WS_QPA)
1129 #  include "qfontdatabase_qpa.cpp"
1130 #elif defined(Q_OS_SYMBIAN)
1131 #  include "qfontdatabase_s60.cpp"
1132 #endif
1133 QT_END_INCLUDE_NAMESPACE
1134 #if !defined(Q_WS_X11)
1135 QString QFontDatabase::resolveFontFamilyAlias(const QString &family)
1136 {
1137     return family;
1138 }
1139 #endif
1140
1141 static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &styleKey,
1142                               const QString &styleName = QString())
1143 {
1144     int best = 0;
1145     int dist = 0xffff;
1146
1147     for ( int i = 0; i < foundry->count; i++ ) {
1148         QtFontStyle *style = foundry->styles[i];
1149
1150         if (!styleName.isEmpty() && styleName == style->styleName) {
1151             dist = 0;
1152             best = i;
1153             break;
1154         }
1155
1156         int d = qAbs( styleKey.weight - style->key.weight );
1157
1158         if ( styleKey.stretch != 0 && style->key.stretch != 0 ) {
1159             d += qAbs( styleKey.stretch - style->key.stretch );
1160         }
1161
1162         if (styleKey.style != style->key.style) {
1163             if (styleKey.style != QFont::StyleNormal && style->key.style != QFont::StyleNormal)
1164                 // one is italic, the other oblique
1165                 d += 0x0001;
1166             else
1167                 d += 0x1000;
1168         }
1169
1170         if ( d < dist ) {
1171             best = i;
1172             dist = d;
1173         }
1174     }
1175
1176     FM_DEBUG( "          best style has distance 0x%x", dist );
1177     return foundry->styles[best];
1178 }
1179
1180 #if defined(Q_WS_X11)
1181 static QtFontEncoding *findEncoding(int script, int styleStrategy,
1182                                     QtFontSize *size, int force_encoding_id)
1183 {
1184     QtFontEncoding *encoding = 0;
1185
1186     if (force_encoding_id >= 0) {
1187         encoding = size->encodingID(force_encoding_id);
1188         if (!encoding)
1189             FM_DEBUG("            required encoding_id not available");
1190         return encoding;
1191     }
1192
1193     if (styleStrategy & (QFont::OpenGLCompatible | QFont::PreferBitmap)) {
1194         FM_DEBUG("            PreferBitmap and/or OpenGL set, skipping Freetype");
1195     } else {
1196         encoding = size->encodingID(-1); // -1 == prefer Freetype
1197         if (encoding)
1198             return encoding;
1199     }
1200
1201     // FT not available, find an XLFD font, trying the default encoding first
1202     encoding = size->encodingID(QFontPrivate::defaultEncodingID);
1203     if (encoding) {
1204         // does it support the requested script?
1205         bool supportsScript = false;
1206         for (int ws = 1; !supportsScript && ws < QFontDatabase::WritingSystemsCount; ++ws) {
1207             if (scriptForWritingSystem[ws] != script)
1208                 continue;
1209             supportsScript = writingSystems_for_xlfd_encoding[encoding->encoding][ws];
1210         }
1211         if (!supportsScript)
1212             encoding = 0;
1213     }
1214     // find the first encoding that supports the requested script
1215     for (int ws = 1; !encoding && ws < QFontDatabase::WritingSystemsCount; ++ws) {
1216         if (scriptForWritingSystem[ws] != script)
1217             continue;
1218         for (int x = 0; !encoding && x < size->count; ++x) {
1219             const int enc = size->encodings[x].encoding;
1220             if (writingSystems_for_xlfd_encoding[enc][ws])
1221                 encoding = size->encodings + x;
1222         }
1223     }
1224
1225     return encoding;
1226 }
1227 #endif // Q_WS_X11
1228
1229 #if !defined(Q_WS_MAC)
1230 static
1231 unsigned int bestFoundry(int script, unsigned int score, int styleStrategy,
1232                          const QtFontFamily *family, const QString &foundry_name,
1233                          QtFontStyle::Key styleKey, int pixelSize, char pitch,
1234                          QtFontDesc *desc, int force_encoding_id)
1235 {
1236     Q_UNUSED(force_encoding_id);
1237     Q_UNUSED(script);
1238     Q_UNUSED(pitch);
1239
1240     desc->foundry = 0;
1241     desc->style = 0;
1242     desc->size = 0;
1243     desc->encoding = 0;
1244
1245
1246     FM_DEBUG("  REMARK: looking for best foundry for family '%s' [%d]", family->name.toLatin1().constData(), family->count);
1247
1248     for (int x = 0; x < family->count; ++x) {
1249         QtFontFoundry *foundry = family->foundries[x];
1250         if (!foundry_name.isEmpty() && foundry->name.compare(foundry_name, Qt::CaseInsensitive) != 0)
1251             continue;
1252
1253         FM_DEBUG("          looking for matching style in foundry '%s' %d",
1254                  foundry->name.isEmpty() ? "-- none --" : foundry->name.toLatin1().constData(), foundry->count);
1255
1256         QtFontStyle *style = bestStyle(foundry, styleKey);
1257
1258         if (!style->smoothScalable && (styleStrategy & QFont::ForceOutline)) {
1259             FM_DEBUG("            ForceOutline set, but not smoothly scalable");
1260             continue;
1261         }
1262
1263         int px = -1;
1264         QtFontSize *size = 0;
1265
1266         // 1. see if we have an exact matching size
1267         if (!(styleStrategy & QFont::ForceOutline)) {
1268             size = style->pixelSize(pixelSize);
1269             if (size) {
1270                 FM_DEBUG("          found exact size match (%d pixels)", size->pixelSize);
1271                 px = size->pixelSize;
1272             }
1273         }
1274
1275         // 2. see if we have a smoothly scalable font
1276         if (!size && style->smoothScalable && ! (styleStrategy & QFont::PreferBitmap)) {
1277             size = style->pixelSize(SMOOTH_SCALABLE);
1278             if (size) {
1279                 FM_DEBUG("          found smoothly scalable font (%d pixels)", pixelSize);
1280                 px = pixelSize;
1281             }
1282         }
1283
1284         // 3. see if we have a bitmap scalable font
1285         if (!size && style->bitmapScalable && (styleStrategy & QFont::PreferMatch)) {
1286             size = style->pixelSize(0);
1287             if (size) {
1288                 FM_DEBUG("          found bitmap scalable font (%d pixels)", pixelSize);
1289                 px = pixelSize;
1290             }
1291         }
1292
1293 #ifdef Q_WS_X11
1294         QtFontEncoding *encoding = 0;
1295 #endif
1296
1297         // 4. find closest size match
1298         if (! size) {
1299             unsigned int distance = ~0u;
1300             for (int x = 0; x < style->count; ++x) {
1301 #ifdef Q_WS_X11
1302                 encoding =
1303                     findEncoding(script, styleStrategy, style->pixelSizes + x, force_encoding_id);
1304                 if (!encoding) {
1305                     FM_DEBUG("          size %3d does not support the script we want",
1306                              style->pixelSizes[x].pixelSize);
1307                     continue;
1308                 }
1309 #endif
1310
1311                 unsigned int d;
1312                 if (style->pixelSizes[x].pixelSize < pixelSize) {
1313                     // penalize sizes that are smaller than the
1314                     // requested size, due to truncation from floating
1315                     // point to integer conversions
1316                     d = pixelSize - style->pixelSizes[x].pixelSize + 1;
1317                 } else {
1318                     d = style->pixelSizes[x].pixelSize - pixelSize;
1319                 }
1320
1321                 if (d < distance) {
1322                     distance = d;
1323                     size = style->pixelSizes + x;
1324                     FM_DEBUG("          best size so far: %3d (%d)", size->pixelSize, pixelSize);
1325                 }
1326             }
1327
1328             if (!size) {
1329                 FM_DEBUG("          no size supports the script we want");
1330                 continue;
1331             }
1332
1333             if (style->bitmapScalable && ! (styleStrategy & QFont::PreferQuality) &&
1334                 (distance * 10 / pixelSize) >= 2) {
1335                 // the closest size is not close enough, go ahead and
1336                 // use a bitmap scaled font
1337                 size = style->pixelSize(0);
1338                 px = pixelSize;
1339             } else {
1340                 px = size->pixelSize;
1341             }
1342         }
1343
1344 #ifdef Q_WS_X11
1345         if (size) {
1346             encoding = findEncoding(script, styleStrategy, size, force_encoding_id);
1347             if (!encoding) size = 0;
1348         }
1349         if (! encoding) {
1350             FM_DEBUG("          foundry doesn't support the script we want");
1351             continue;
1352         }
1353 #endif // Q_WS_X11
1354
1355         unsigned int this_score = 0x0000;
1356         enum {
1357             PitchMismatch       = 0x4000,
1358             StyleMismatch       = 0x2000,
1359             BitmapScaledPenalty = 0x1000,
1360             EncodingMismatch    = 0x0002,
1361             XLFDPenalty         = 0x0001
1362         };
1363 #ifdef Q_WS_X11
1364         if (encoding->encoding != -1) {
1365             this_score += XLFDPenalty;
1366             if (encoding->encoding != QFontPrivate::defaultEncodingID)
1367                 this_score += EncodingMismatch;
1368         }
1369         if (pitch != '*') {
1370             if (!(pitch == 'm' && encoding->pitch == 'c') && pitch != encoding->pitch)
1371                 this_score += PitchMismatch;
1372         }
1373 #else
1374         if (pitch != '*') {
1375 #if !defined(QWS) && defined(Q_OS_MAC)
1376             qt_mac_get_fixed_pitch(const_cast<QtFontFamily*>(family));
1377 #endif
1378             if ((pitch == 'm' && !family->fixedPitch)
1379                 || (pitch == 'p' && family->fixedPitch))
1380                 this_score += PitchMismatch;
1381         }
1382 #endif
1383         if (styleKey != style->key)
1384             this_score += StyleMismatch;
1385         if (!style->smoothScalable && px != size->pixelSize) // bitmap scaled
1386             this_score += BitmapScaledPenalty;
1387         if (px != pixelSize) // close, but not exact, size match
1388             this_score += qAbs(px - pixelSize);
1389
1390         if (this_score < score) {
1391             FM_DEBUG("          found a match: score %x best score so far %x",
1392                      this_score, score);
1393
1394             score = this_score;
1395             desc->foundry = foundry;
1396             desc->style = style;
1397             desc->size = size;
1398 #ifdef Q_WS_X11
1399             desc->encoding = encoding;
1400 #endif // Q_WS_X11
1401         } else {
1402             FM_DEBUG("          score %x no better than best %x", this_score, score);
1403         }
1404     }
1405
1406     return score;
1407 }
1408 #endif
1409
1410 #if !defined(Q_WS_MAC)
1411 /*!
1412     \internal
1413
1414     Tries to find the best match for a given request and family/foundry
1415 */
1416 static void match(int script, const QFontDef &request,
1417                   const QString &family_name, const QString &foundry_name, int force_encoding_id,
1418                   QtFontDesc *desc, const QList<int> &blacklistedFamilies, bool forceXLFD)
1419 {
1420     Q_UNUSED(force_encoding_id);
1421
1422     QtFontStyle::Key styleKey;
1423     styleKey.style = request.style;
1424     styleKey.weight = request.weight;
1425     styleKey.stretch = request.stretch;
1426     char pitch = request.ignorePitch ? '*' : request.fixedPitch ? 'm' : 'p';
1427
1428
1429     FM_DEBUG("QFontDatabase::match\n"
1430              "  request:\n"
1431              "    family: %s [%s], script: %d\n"
1432              "    weight: %d, style: %d\n"
1433              "    stretch: %d\n"
1434              "    pixelSize: %g\n"
1435              "    pitch: %c",
1436              family_name.isEmpty() ? "-- first in script --" : family_name.toLatin1().constData(),
1437              foundry_name.isEmpty() ? "-- any --" : foundry_name.toLatin1().constData(),
1438              script, request.weight, request.style, request.stretch, request.pixelSize, pitch);
1439 #if defined(FONT_MATCH_DEBUG) && defined(Q_WS_X11)
1440     if (force_encoding_id >= 0) {
1441         FM_DEBUG("    required encoding: %d", force_encoding_id);
1442     }
1443 #endif
1444
1445     desc->family = 0;
1446     desc->foundry = 0;
1447     desc->style = 0;
1448     desc->size = 0;
1449     desc->encoding = 0;
1450     desc->familyIndex = -1;
1451
1452     unsigned int score = ~0u;
1453
1454 #ifdef Q_WS_X11
1455     load(family_name, script, forceXLFD);
1456 #else
1457     Q_UNUSED(forceXLFD);
1458     load(family_name, script);
1459 #endif
1460
1461     QFontDatabasePrivate *db = privateDb();
1462     for (int x = 0; x < db->count; ++x) {
1463         if (blacklistedFamilies.contains(x))
1464             continue;
1465         QtFontDesc test;
1466         test.family = db->families[x];
1467         test.familyIndex = x;
1468
1469         if (!family_name.isEmpty()
1470             && test.family->name.compare(family_name, Qt::CaseInsensitive) != 0
1471 #ifdef Q_WS_WIN
1472             && test.family->english_name.compare(family_name, Qt::CaseInsensitive) != 0
1473 #endif
1474             )
1475             continue;
1476
1477         if (family_name.isEmpty())
1478             load(test.family->name, script);
1479
1480         uint score_adjust = 0;
1481
1482         bool supported = (script == QUnicodeTables::Common);
1483         for (int ws = 1; !supported && ws < QFontDatabase::WritingSystemsCount; ++ws) {
1484             if (scriptForWritingSystem[ws] != script)
1485                 continue;
1486             if (test.family->writingSystems[ws] & QtFontFamily::Supported)
1487                 supported = true;
1488         }
1489         if (!supported) {
1490             // family not supported in the script we want
1491             continue;
1492         }
1493
1494         // as we know the script is supported, we can be sure
1495         // to find a matching font here.
1496         unsigned int newscore =
1497             bestFoundry(script, score, request.styleStrategy,
1498                         test.family, foundry_name, styleKey, request.pixelSize, pitch,
1499                         &test, force_encoding_id);
1500         if (test.foundry == 0) {
1501             // the specific foundry was not found, so look for
1502             // any foundry matching our requirements
1503             newscore = bestFoundry(script, score, request.styleStrategy, test.family,
1504                                    QString(), styleKey, request.pixelSize,
1505                                    pitch, &test, force_encoding_id);
1506         }
1507         newscore += score_adjust;
1508
1509         if (newscore < score) {
1510             score = newscore;
1511             *desc = test;
1512         }
1513         if (newscore < 10) // xlfd instead of FT... just accept it
1514             break;
1515     }
1516 }
1517 #endif
1518
1519 static QString styleStringHelper(int weight, QFont::Style style)
1520 {
1521     QString result;
1522     if (weight >= QFont::Black)
1523         result = QCoreApplication::translate("QFontDatabase", "Black");
1524     else if (weight >= QFont::Bold)
1525         result = QCoreApplication::translate("QFontDatabase", "Bold");
1526     else if (weight >= QFont::DemiBold)
1527         result = QCoreApplication::translate("QFontDatabase", "Demi Bold");
1528     else if (weight < QFont::Normal)
1529         result = QCoreApplication::translate("QFontDatabase", "Light");
1530
1531     if (style == QFont::StyleItalic)
1532         result += QLatin1Char(' ') + QCoreApplication::translate("QFontDatabase", "Italic");
1533     else if (style == QFont::StyleOblique)
1534         result += QLatin1Char(' ') + QCoreApplication::translate("QFontDatabase", "Oblique");
1535
1536     if (result.isEmpty())
1537         result = QCoreApplication::translate("QFontDatabase", "Normal");
1538
1539     return result.simplified();
1540 }
1541
1542 /*!
1543     Returns a string that describes the style of the \a font. For
1544     example, "Bold Italic", "Bold", "Italic" or "Normal". An empty
1545     string may be returned.
1546 */
1547 QString QFontDatabase::styleString(const QFont &font)
1548 {
1549     return font.styleName().isEmpty() ? styleStringHelper(font.weight(), font.style())
1550                                       : font.styleName();
1551 }
1552
1553 /*!
1554     Returns a string that describes the style of the \a fontInfo. For
1555     example, "Bold Italic", "Bold", "Italic" or "Normal". An empty
1556     string may be returned.
1557 */
1558 QString QFontDatabase::styleString(const QFontInfo &fontInfo)
1559 {
1560     return fontInfo.styleName().isEmpty() ? styleStringHelper(fontInfo.weight(), fontInfo.style())
1561                                           : fontInfo.styleName();
1562 }
1563
1564
1565 /*!
1566     \class QFontDatabase
1567     \threadsafe
1568
1569     \brief The QFontDatabase class provides information about the fonts available in the underlying window system.
1570
1571     \ingroup appearance
1572
1573     The most common uses of this class are to query the database for
1574     the list of font families() and for the pointSizes() and styles()
1575     that are available for each family. An alternative to pointSizes()
1576     is smoothSizes() which returns the sizes at which a given family
1577     and style will look attractive.
1578
1579     If the font family is available from two or more foundries the
1580     foundry name is included in the family name; for example:
1581     "Helvetica [Adobe]" and "Helvetica [Cronyx]". When you specify a
1582     family, you can either use the old hyphenated "foundry-family"
1583     format or the bracketed "family [foundry]" format; for example:
1584     "Cronyx-Helvetica" or "Helvetica [Cronyx]". If the family has a
1585     foundry it is always returned using the bracketed format, as is
1586     the case with the value returned by families().
1587
1588     The font() function returns a QFont given a family, style and
1589     point size.
1590
1591     A family and style combination can be checked to see if it is
1592     italic() or bold(), and to retrieve its weight(). Similarly we can
1593     call isBitmapScalable(), isSmoothlyScalable(), isScalable() and
1594     isFixedPitch().
1595
1596     Use the styleString() to obtain a text version of a style.
1597
1598     The QFontDatabase class also supports some static functions, for
1599     example, standardSizes(). You can retrieve the description of a
1600     writing system using writingSystemName(), and a sample of
1601     characters in a writing system with writingSystemSample().
1602
1603     Example:
1604
1605     \snippet doc/src/snippets/qfontdatabase/main.cpp 0
1606     \snippet doc/src/snippets/qfontdatabase/main.cpp 1
1607
1608     This example gets the list of font families, the list of
1609     styles for each family, and the point sizes that are available for
1610     each combination of family and style, displaying this information
1611     in a tree view.
1612
1613     \sa QFont, QFontInfo, QFontMetrics, QFontComboBox, {Character Map Example}
1614 */
1615
1616 /*!
1617     Creates a font database object.
1618 */
1619 QFontDatabase::QFontDatabase()
1620 {
1621     QMutexLocker locker(fontDatabaseMutex());
1622     createDatabase();
1623     d = privateDb();
1624 }
1625
1626 /*!
1627     \enum QFontDatabase::WritingSystem
1628
1629     \value Any
1630     \value Latin
1631     \value Greek
1632     \value Cyrillic
1633     \value Armenian
1634     \value Hebrew
1635     \value Arabic
1636     \value Syriac
1637     \value Thaana
1638     \value Devanagari
1639     \value Bengali
1640     \value Gurmukhi
1641     \value Gujarati
1642     \value Oriya
1643     \value Tamil
1644     \value Telugu
1645     \value Kannada
1646     \value Malayalam
1647     \value Sinhala
1648     \value Thai
1649     \value Lao
1650     \value Tibetan
1651     \value Myanmar
1652     \value Georgian
1653     \value Khmer
1654     \value SimplifiedChinese
1655     \value TraditionalChinese
1656     \value Japanese
1657     \value Korean
1658     \value Vietnamese
1659     \value Symbol
1660     \value Other (the same as Symbol)
1661     \value Ogham
1662     \value Runic
1663     \value Nko
1664
1665     \omitvalue WritingSystemsCount
1666 */
1667
1668 /*!
1669     Returns a sorted list of the available writing systems. This is
1670     list generated from information about all installed fonts on the
1671     system.
1672
1673     \sa families()
1674 */
1675 QList<QFontDatabase::WritingSystem> QFontDatabase::writingSystems() const
1676 {
1677     QMutexLocker locker(fontDatabaseMutex());
1678
1679     QT_PREPEND_NAMESPACE(load)();
1680 #ifdef Q_WS_X11
1681     checkSymbolFonts();
1682 #endif
1683
1684     QList<WritingSystem> list;
1685     for (int i = 0; i < d->count; ++i) {
1686         QtFontFamily *family = d->families[i];
1687         if (family->count == 0)
1688             continue;
1689         for (int x = Latin; x < WritingSystemsCount; ++x) {
1690             const WritingSystem writingSystem = WritingSystem(x);
1691             if (!(family->writingSystems[writingSystem] & QtFontFamily::Supported))
1692                 continue;
1693             if (!list.contains(writingSystem))
1694                 list.append(writingSystem);
1695         }
1696     }
1697     qSort(list);
1698     return list;
1699 }
1700
1701
1702 /*!
1703     Returns a sorted list of the writing systems supported by a given
1704     font \a family.
1705
1706     \sa families()
1707 */
1708 QList<QFontDatabase::WritingSystem> QFontDatabase::writingSystems(const QString &family) const
1709 {
1710     QString familyName, foundryName;
1711     parseFontName(family, foundryName, familyName);
1712
1713     QMutexLocker locker(fontDatabaseMutex());
1714
1715     QT_PREPEND_NAMESPACE(load)();
1716 #ifdef Q_WS_X11
1717     checkSymbolFonts(familyName);
1718 #endif
1719
1720     QList<WritingSystem> list;
1721     QtFontFamily *f = d->family(familyName);
1722     if (!f || f->count == 0)
1723         return list;
1724
1725     for (int x = Latin; x < WritingSystemsCount; ++x) {
1726         const WritingSystem writingSystem = WritingSystem(x);
1727         if (f->writingSystems[writingSystem] & QtFontFamily::Supported)
1728             list.append(writingSystem);
1729     }
1730     return list;
1731 }
1732
1733
1734 /*!
1735     Returns a sorted list of the available font families which support
1736     the \a writingSystem.
1737
1738     If a family exists in several foundries, the returned name for
1739     that font is in the form "family [foundry]". Examples: "Times
1740     [Adobe]", "Times [Cronyx]", "Palatino".
1741
1742     \sa writingSystems()
1743 */
1744 QStringList QFontDatabase::families(WritingSystem writingSystem) const
1745 {
1746     QMutexLocker locker(fontDatabaseMutex());
1747
1748     QT_PREPEND_NAMESPACE(load)();
1749 #ifdef Q_WS_X11
1750     if (writingSystem != Any)
1751         checkSymbolFonts();
1752 #endif
1753
1754     QStringList flist;
1755     for (int i = 0; i < d->count; i++) {
1756         QtFontFamily *f = d->families[i];
1757         if (f->count == 0)
1758             continue;
1759         if (writingSystem != Any && (f->writingSystems[writingSystem] != QtFontFamily::Supported))
1760             continue;
1761         if (f->count == 1) {
1762             flist.append(f->name);
1763         } else {
1764             for (int j = 0; j < f->count; j++) {
1765                 QString str = f->name;
1766                 QString foundry = f->foundries[j]->name;
1767                 if (!foundry.isEmpty()) {
1768                     str += QLatin1String(" [");
1769                     str += foundry;
1770                     str += QLatin1Char(']');
1771                 }
1772                 flist.append(str);
1773             }
1774         }
1775     }
1776     return flist;
1777 }
1778
1779 /*!
1780     Returns a list of the styles available for the font family \a
1781     family. Some example styles: "Light", "Light Italic", "Bold",
1782     "Oblique", "Demi". The list may be empty.
1783
1784     \sa families()
1785 */
1786 QStringList QFontDatabase::styles(const QString &family) const
1787 {
1788     QString familyName, foundryName;
1789     parseFontName(family, foundryName, familyName);
1790
1791     QMutexLocker locker(fontDatabaseMutex());
1792
1793     QT_PREPEND_NAMESPACE(load)(familyName);
1794
1795     QStringList l;
1796     QtFontFamily *f = d->family(familyName);
1797     if (!f)
1798         return l;
1799
1800     QtFontFoundry allStyles(foundryName);
1801     for (int j = 0; j < f->count; j++) {
1802         QtFontFoundry *foundry = f->foundries[j];
1803         if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1804             for (int k = 0; k < foundry->count; k++) {
1805                 QtFontStyle::Key ke(foundry->styles[k]->key);
1806                 ke.stretch = 0;
1807                 allStyles.style(ke, foundry->styles[k]->styleName, true);
1808             }
1809         }
1810     }
1811
1812     for (int i = 0; i < allStyles.count; i++) {
1813         l.append(allStyles.styles[i]->styleName.isEmpty() ?
1814                  styleStringHelper(allStyles.styles[i]->key.weight,
1815                                    (QFont::Style)allStyles.styles[i]->key.style) :
1816                  allStyles.styles[i]->styleName);
1817     }
1818     return l;
1819 }
1820
1821 /*!
1822     Returns true if the font that has family \a family and style \a
1823     style is fixed pitch; otherwise returns false.
1824 */
1825
1826 bool QFontDatabase::isFixedPitch(const QString &family,
1827                                  const QString &style) const
1828 {
1829     Q_UNUSED(style);
1830
1831     QString familyName, foundryName;
1832     parseFontName(family, foundryName, familyName);
1833
1834     QMutexLocker locker(fontDatabaseMutex());
1835
1836     QT_PREPEND_NAMESPACE(load)(familyName);
1837
1838     QtFontFamily *f = d->family(familyName);
1839 #if !defined(QWS) && defined(Q_OS_MAC)
1840     qt_mac_get_fixed_pitch(f);
1841 #endif
1842     return (f && f->fixedPitch);
1843 }
1844
1845 /*!
1846     Returns true if the font that has family \a family and style \a
1847     style is a scalable bitmap font; otherwise returns false. Scaling
1848     a bitmap font usually produces an unattractive hardly readable
1849     result, because the pixels of the font are scaled. If you need to
1850     scale a bitmap font it is better to scale it to one of the fixed
1851     sizes returned by smoothSizes().
1852
1853     \sa isScalable(), isSmoothlyScalable()
1854 */
1855 bool QFontDatabase::isBitmapScalable(const QString &family,
1856                                       const QString &style) const
1857 {
1858     bool bitmapScalable = false;
1859     QString familyName, foundryName;
1860     parseFontName(family, foundryName, familyName);
1861
1862     QMutexLocker locker(fontDatabaseMutex());
1863
1864     QT_PREPEND_NAMESPACE(load)(familyName);
1865
1866     QtFontStyle::Key styleKey(style);
1867
1868     QtFontFamily *f = d->family(familyName);
1869     if (!f) return bitmapScalable;
1870
1871     for (int j = 0; j < f->count; j++) {
1872         QtFontFoundry *foundry = f->foundries[j];
1873         if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1874             for (int k = 0; k < foundry->count; k++)
1875                 if ((style.isEmpty() ||
1876                      foundry->styles[k]->styleName == style ||
1877                      foundry->styles[k]->key == styleKey)
1878                     && foundry->styles[k]->bitmapScalable && !foundry->styles[k]->smoothScalable) {
1879                     bitmapScalable = true;
1880                     goto end;
1881                 }
1882         }
1883     }
1884  end:
1885     return bitmapScalable;
1886 }
1887
1888
1889 /*!
1890     Returns true if the font that has family \a family and style \a
1891     style is smoothly scalable; otherwise returns false. If this
1892     function returns true, it's safe to scale this font to any size,
1893     and the result will always look attractive.
1894
1895     \sa isScalable(), isBitmapScalable()
1896 */
1897 bool QFontDatabase::isSmoothlyScalable(const QString &family, const QString &style) const
1898 {
1899     bool smoothScalable = false;
1900     QString familyName, foundryName;
1901     parseFontName(family, foundryName, familyName);
1902
1903     QMutexLocker locker(fontDatabaseMutex());
1904
1905     QT_PREPEND_NAMESPACE(load)(familyName);
1906
1907     QtFontStyle::Key styleKey(style);
1908
1909     QtFontFamily *f = d->family(familyName);
1910     if (!f) return smoothScalable;
1911
1912     for (int j = 0; j < f->count; j++) {
1913         QtFontFoundry *foundry = f->foundries[j];
1914         if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1915             for (int k = 0; k < foundry->count; k++)
1916                 if ((style.isEmpty() ||
1917                      foundry->styles[k]->styleName == style ||
1918                      foundry->styles[k]->key == styleKey) && foundry->styles[k]->smoothScalable) {
1919                     smoothScalable = true;
1920                     goto end;
1921                 }
1922         }
1923     }
1924  end:
1925     return smoothScalable;
1926 }
1927
1928 /*!
1929     Returns true if the font that has family \a family and style \a
1930     style is scalable; otherwise returns false.
1931
1932     \sa isBitmapScalable(), isSmoothlyScalable()
1933 */
1934 bool  QFontDatabase::isScalable(const QString &family,
1935                                  const QString &style) const
1936 {
1937     QMutexLocker locker(fontDatabaseMutex());
1938     if (isSmoothlyScalable(family, style))
1939         return true;
1940     return isBitmapScalable(family, style);
1941 }
1942
1943
1944 /*!
1945     Returns a list of the point sizes available for the font that has
1946     family \a family and style \a style. The list may be empty.
1947
1948     \sa smoothSizes(), standardSizes()
1949 */
1950 QList<int> QFontDatabase::pointSizes(const QString &family,
1951                                            const QString &styleName)
1952 {
1953 #if defined(Q_WS_WIN)
1954     // windows and macosx are always smoothly scalable
1955     Q_UNUSED(family);
1956     Q_UNUSED(styleName);
1957     return standardSizes();
1958 #else
1959     bool smoothScalable = false;
1960     QString familyName, foundryName;
1961     parseFontName(family, foundryName, familyName);
1962
1963     QMutexLocker locker(fontDatabaseMutex());
1964
1965     QT_PREPEND_NAMESPACE(load)(familyName);
1966
1967     QtFontStyle::Key styleKey(styleName);
1968
1969     QList<int> sizes;
1970
1971     QtFontFamily *fam = d->family(familyName);
1972     if (!fam) return sizes;
1973
1974
1975 #ifdef Q_WS_X11
1976     int dpi = QX11Info::appDpiY();
1977 #else
1978     const int dpi = qt_defaultDpiY(); // embedded
1979 #endif
1980
1981     for (int j = 0; j < fam->count; j++) {
1982         QtFontFoundry *foundry = fam->foundries[j];
1983         if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1984             QtFontStyle *style = foundry->style(styleKey, styleName);
1985             if (!style) continue;
1986
1987             if (style->smoothScalable) {
1988                 smoothScalable = true;
1989                 goto end;
1990             }
1991             for (int l = 0; l < style->count; l++) {
1992                 const QtFontSize *size = style->pixelSizes + l;
1993
1994                 if (size->pixelSize != 0 && size->pixelSize != USHRT_MAX) {
1995                     const uint pointSize = qRound(size->pixelSize * 72.0 / dpi);
1996                     if (! sizes.contains(pointSize))
1997                         sizes.append(pointSize);
1998                 }
1999             }
2000         }
2001     }
2002  end:
2003     if (smoothScalable)
2004         return standardSizes();
2005
2006     qSort(sizes);
2007     return sizes;
2008 #endif
2009 }
2010
2011 /*!
2012     Returns a QFont object that has family \a family, style \a style
2013     and point size \a pointSize. If no matching font could be created,
2014     a QFont object that uses the application's default font is
2015     returned.
2016 */
2017 QFont QFontDatabase::font(const QString &family, const QString &style,
2018                            int pointSize) const
2019 {
2020     QString familyName, foundryName;
2021     parseFontName(family, foundryName, familyName);
2022
2023     QMutexLocker locker(fontDatabaseMutex());
2024
2025     QT_PREPEND_NAMESPACE(load)(familyName);
2026
2027     QtFontFoundry allStyles(foundryName);
2028     QtFontFamily *f = d->family(familyName);
2029     if (!f) return QGuiApplication::font();
2030
2031     for (int j = 0; j < f->count; j++) {
2032         QtFontFoundry *foundry = f->foundries[j];
2033         if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
2034             for (int k = 0; k < foundry->count; k++)
2035                 allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true);
2036         }
2037     }
2038
2039     QtFontStyle::Key styleKey(style);
2040     QtFontStyle *s = bestStyle(&allStyles, styleKey, style);
2041
2042     if (!s) // no styles found?
2043         return QGuiApplication::font();
2044
2045     QFont fnt(family, pointSize, s->key.weight);
2046     fnt.setStyle((QFont::Style)s->key.style);
2047     if (!s->styleName.isEmpty())
2048         fnt.setStyleName(s->styleName);
2049     return fnt;
2050 }
2051
2052
2053 /*!
2054     Returns the point sizes of a font that has family \a family and
2055     style \a style that will look attractive. The list may be empty.
2056     For non-scalable fonts and bitmap scalable fonts, this function
2057     is equivalent to pointSizes().
2058
2059   \sa pointSizes(), standardSizes()
2060 */
2061 QList<int> QFontDatabase::smoothSizes(const QString &family,
2062                                             const QString &styleName)
2063 {
2064 #ifdef Q_WS_WIN
2065     Q_UNUSED(family);
2066     Q_UNUSED(styleName);
2067     return QFontDatabase::standardSizes();
2068 #else
2069     bool smoothScalable = false;
2070     QString familyName, foundryName;
2071     parseFontName(family, foundryName, familyName);
2072
2073     QMutexLocker locker(fontDatabaseMutex());
2074
2075     QT_PREPEND_NAMESPACE(load)(familyName);
2076
2077     QtFontStyle::Key styleKey(styleName);
2078
2079     QList<int> sizes;
2080
2081     QtFontFamily *fam = d->family(familyName);
2082     if (!fam)
2083         return sizes;
2084
2085 #ifdef Q_WS_X11
2086     int dpi = QX11Info::appDpiY();
2087 #else
2088     const int dpi = qt_defaultDpiY(); // embedded
2089 #endif
2090
2091     for (int j = 0; j < fam->count; j++) {
2092         QtFontFoundry *foundry = fam->foundries[j];
2093         if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
2094             QtFontStyle *style = foundry->style(styleKey, styleName);
2095             if (!style) continue;
2096
2097             if (style->smoothScalable) {
2098                 smoothScalable = true;
2099                 goto end;
2100             }
2101             for (int l = 0; l < style->count; l++) {
2102                 const QtFontSize *size = style->pixelSizes + l;
2103
2104                 if (size->pixelSize != 0 && size->pixelSize != USHRT_MAX) {
2105                     const uint pointSize = qRound(size->pixelSize * 72.0 / dpi);
2106                     if (! sizes.contains(pointSize))
2107                         sizes.append(pointSize);
2108                 }
2109             }
2110         }
2111     }
2112  end:
2113     if (smoothScalable)
2114         return QFontDatabase::standardSizes();
2115
2116     qSort(sizes);
2117     return sizes;
2118 #endif
2119 }
2120
2121
2122 /*!
2123     Returns a list of standard font sizes.
2124
2125     \sa smoothSizes(), pointSizes()
2126 */
2127 QList<int> QFontDatabase::standardSizes()
2128 {
2129     QList<int> ret;
2130     static const unsigned short standard[] =
2131         { 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72, 0 };
2132     const unsigned short *sizes = standard;
2133     while (*sizes) ret << *sizes++;
2134     return ret;
2135 }
2136
2137
2138 /*!
2139     Returns true if the font that has family \a family and style \a
2140     style is italic; otherwise returns false.
2141
2142     \sa weight(), bold()
2143 */
2144 bool QFontDatabase::italic(const QString &family, const QString &style) const
2145 {
2146     QString familyName, foundryName;
2147     parseFontName(family, foundryName, familyName);
2148
2149     QMutexLocker locker(fontDatabaseMutex());
2150
2151     QT_PREPEND_NAMESPACE(load)(familyName);
2152
2153     QtFontFoundry allStyles(foundryName);
2154     QtFontFamily *f = d->family(familyName);
2155     if (!f) return false;
2156
2157     for (int j = 0; j < f->count; j++) {
2158         QtFontFoundry *foundry = f->foundries[j];
2159         if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
2160             for (int k = 0; k < foundry->count; k++)
2161                 allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true);
2162         }
2163     }
2164
2165     QtFontStyle::Key styleKey(style);
2166     QtFontStyle *s = allStyles.style(styleKey, style);
2167     return s && s->key.style == QFont::StyleItalic;
2168 }
2169
2170
2171 /*!
2172     Returns true if the font that has family \a family and style \a
2173     style is bold; otherwise returns false.
2174
2175     \sa italic(), weight()
2176 */
2177 bool QFontDatabase::bold(const QString &family,
2178                           const QString &style) const
2179 {
2180     QString familyName, foundryName;
2181     parseFontName(family, foundryName, familyName);
2182
2183     QMutexLocker locker(fontDatabaseMutex());
2184
2185     QT_PREPEND_NAMESPACE(load)(familyName);
2186
2187     QtFontFoundry allStyles(foundryName);
2188     QtFontFamily *f = d->family(familyName);
2189     if (!f) return false;
2190
2191     for (int j = 0; j < f->count; j++) {
2192         QtFontFoundry *foundry = f->foundries[j];
2193         if (foundryName.isEmpty() ||
2194             foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
2195             for (int k = 0; k < foundry->count; k++)
2196                 allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true);
2197         }
2198     }
2199
2200     QtFontStyle::Key styleKey(style);
2201     QtFontStyle *s = allStyles.style(styleKey, style);
2202     return s && s->key.weight >= QFont::Bold;
2203 }
2204
2205
2206 /*!
2207     Returns the weight of the font that has family \a family and style
2208     \a style. If there is no such family and style combination,
2209     returns -1.
2210
2211     \sa italic(), bold()
2212 */
2213 int QFontDatabase::weight(const QString &family,
2214                            const QString &style) const
2215 {
2216     QString familyName, foundryName;
2217     parseFontName(family, foundryName, familyName);
2218
2219     QMutexLocker locker(fontDatabaseMutex());
2220
2221     QT_PREPEND_NAMESPACE(load)(familyName);
2222
2223     QtFontFoundry allStyles(foundryName);
2224     QtFontFamily *f = d->family(familyName);
2225     if (!f) return -1;
2226
2227     for (int j = 0; j < f->count; j++) {
2228         QtFontFoundry *foundry = f->foundries[j];
2229         if (foundryName.isEmpty() ||
2230             foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
2231             for (int k = 0; k < foundry->count; k++)
2232                 allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true);
2233         }
2234     }
2235
2236     QtFontStyle::Key styleKey(style);
2237     QtFontStyle *s = allStyles.style(styleKey, style);
2238     return s ? s->key.weight : -1;
2239 }
2240
2241
2242 /*! \internal */
2243 bool QFontDatabase::hasFamily(const QString &family) const
2244 {
2245     QString parsedFamily, foundry;
2246     parseFontName(family, foundry, parsedFamily);
2247     const QString familyAlias = resolveFontFamilyAlias(parsedFamily);
2248     return families().contains(familyAlias, Qt::CaseInsensitive);
2249 }
2250
2251
2252 /*!
2253     Returns the names the \a writingSystem (e.g. for displaying to the
2254     user in a dialog).
2255 */
2256 QString QFontDatabase::writingSystemName(WritingSystem writingSystem)
2257 {
2258     const char *name = 0;
2259     switch (writingSystem) {
2260     case Any:
2261         name = QT_TRANSLATE_NOOP("QFontDatabase", "Any");
2262         break;
2263     case Latin:
2264         name = QT_TRANSLATE_NOOP("QFontDatabase", "Latin");
2265         break;
2266     case Greek:
2267         name = QT_TRANSLATE_NOOP("QFontDatabase", "Greek");
2268         break;
2269     case Cyrillic:
2270         name = QT_TRANSLATE_NOOP("QFontDatabase", "Cyrillic");
2271         break;
2272     case Armenian:
2273         name = QT_TRANSLATE_NOOP("QFontDatabase", "Armenian");
2274         break;
2275     case Hebrew:
2276         name = QT_TRANSLATE_NOOP("QFontDatabase", "Hebrew");
2277         break;
2278     case Arabic:
2279         name = QT_TRANSLATE_NOOP("QFontDatabase", "Arabic");
2280         break;
2281     case Syriac:
2282         name = QT_TRANSLATE_NOOP("QFontDatabase", "Syriac");
2283         break;
2284     case Thaana:
2285         name = QT_TRANSLATE_NOOP("QFontDatabase", "Thaana");
2286         break;
2287     case Devanagari:
2288         name = QT_TRANSLATE_NOOP("QFontDatabase", "Devanagari");
2289         break;
2290     case Bengali:
2291         name = QT_TRANSLATE_NOOP("QFontDatabase", "Bengali");
2292         break;
2293     case Gurmukhi:
2294         name = QT_TRANSLATE_NOOP("QFontDatabase", "Gurmukhi");
2295         break;
2296     case Gujarati:
2297         name = QT_TRANSLATE_NOOP("QFontDatabase", "Gujarati");
2298         break;
2299     case Oriya:
2300         name = QT_TRANSLATE_NOOP("QFontDatabase", "Oriya");
2301         break;
2302     case Tamil:
2303         name = QT_TRANSLATE_NOOP("QFontDatabase", "Tamil");
2304         break;
2305     case Telugu:
2306         name = QT_TRANSLATE_NOOP("QFontDatabase", "Telugu");
2307         break;
2308     case Kannada:
2309         name = QT_TRANSLATE_NOOP("QFontDatabase", "Kannada");
2310         break;
2311     case Malayalam:
2312         name = QT_TRANSLATE_NOOP("QFontDatabase", "Malayalam");
2313         break;
2314     case Sinhala:
2315         name = QT_TRANSLATE_NOOP("QFontDatabase", "Sinhala");
2316         break;
2317     case Thai:
2318         name = QT_TRANSLATE_NOOP("QFontDatabase", "Thai");
2319         break;
2320     case Lao:
2321         name = QT_TRANSLATE_NOOP("QFontDatabase", "Lao");
2322         break;
2323     case Tibetan:
2324         name = QT_TRANSLATE_NOOP("QFontDatabase", "Tibetan");
2325         break;
2326     case Myanmar:
2327         name = QT_TRANSLATE_NOOP("QFontDatabase", "Myanmar");
2328         break;
2329     case Georgian:
2330         name = QT_TRANSLATE_NOOP("QFontDatabase", "Georgian");
2331         break;
2332     case Khmer:
2333         name = QT_TRANSLATE_NOOP("QFontDatabase", "Khmer");
2334         break;
2335     case SimplifiedChinese:
2336         name = QT_TRANSLATE_NOOP("QFontDatabase", "Simplified Chinese");
2337         break;
2338     case TraditionalChinese:
2339         name = QT_TRANSLATE_NOOP("QFontDatabase", "Traditional Chinese");
2340         break;
2341     case Japanese:
2342         name = QT_TRANSLATE_NOOP("QFontDatabase", "Japanese");
2343         break;
2344     case Korean:
2345         name = QT_TRANSLATE_NOOP("QFontDatabase", "Korean");
2346         break;
2347     case Vietnamese:
2348         name = QT_TRANSLATE_NOOP("QFontDatabase", "Vietnamese");
2349         break;
2350     case Symbol:
2351         name = QT_TRANSLATE_NOOP("QFontDatabase", "Symbol");
2352         break;
2353     case Ogham:
2354         name = QT_TRANSLATE_NOOP("QFontDatabase", "Ogham");
2355         break;
2356     case Runic:
2357         name = QT_TRANSLATE_NOOP("QFontDatabase", "Runic");
2358         break;
2359     case Nko:
2360         name = QT_TRANSLATE_NOOP("QFontDatabase", "N'Ko");
2361         break;
2362     default:
2363         Q_ASSERT_X(false, "QFontDatabase::writingSystemName", "invalid 'writingSystem' parameter");
2364         break;
2365     }
2366     return QCoreApplication::translate("QFontDatabase", name);
2367 }
2368
2369
2370 /*!
2371     Returns a string with sample characters from \a writingSystem.
2372 */
2373 QString QFontDatabase::writingSystemSample(WritingSystem writingSystem)
2374 {
2375     QString sample;
2376     switch (writingSystem) {
2377     case Any:
2378     case Symbol:
2379         // show only ascii characters
2380         sample += QLatin1String("AaBbzZ");
2381         break;
2382     case Latin:
2383         // This is cheating... we only show latin-1 characters so that we don't
2384         // end up loading lots of fonts - at least on X11...
2385         sample = QLatin1String("Aa");
2386         sample += QChar(0x00C3);
2387         sample += QChar(0x00E1);
2388         sample += QLatin1String("Zz");
2389         break;
2390     case Greek:
2391         sample += QChar(0x0393);
2392         sample += QChar(0x03B1);
2393         sample += QChar(0x03A9);
2394         sample += QChar(0x03C9);
2395         break;
2396     case Cyrillic:
2397         sample += QChar(0x0414);
2398         sample += QChar(0x0434);
2399         sample += QChar(0x0436);
2400         sample += QChar(0x044f);
2401         break;
2402     case Armenian:
2403         sample += QChar(0x053f);
2404         sample += QChar(0x054f);
2405         sample += QChar(0x056f);
2406         sample += QChar(0x057f);
2407         break;
2408     case Hebrew:
2409         sample += QChar(0x05D0);
2410         sample += QChar(0x05D1);
2411         sample += QChar(0x05D2);
2412         sample += QChar(0x05D3);
2413         break;
2414     case Arabic:
2415         sample += QChar(0x0628);
2416         sample += QChar(0x0629);
2417         sample += QChar(0x062A);
2418         sample += QChar(0x063A);
2419         break;
2420     case Syriac:
2421         sample += QChar(0x0715);
2422         sample += QChar(0x0725);
2423         sample += QChar(0x0716);
2424         sample += QChar(0x0726);
2425         break;
2426     case Thaana:
2427         sample += QChar(0x0784);
2428         sample += QChar(0x0794);
2429         sample += QChar(0x078c);
2430         sample += QChar(0x078d);
2431         break;
2432     case Devanagari:
2433         sample += QChar(0x0905);
2434         sample += QChar(0x0915);
2435         sample += QChar(0x0925);
2436         sample += QChar(0x0935);
2437         break;
2438     case Bengali:
2439         sample += QChar(0x0986);
2440         sample += QChar(0x0996);
2441         sample += QChar(0x09a6);
2442         sample += QChar(0x09b6);
2443         break;
2444     case Gurmukhi:
2445         sample += QChar(0x0a05);
2446         sample += QChar(0x0a15);
2447         sample += QChar(0x0a25);
2448         sample += QChar(0x0a35);
2449         break;
2450     case Gujarati:
2451         sample += QChar(0x0a85);
2452         sample += QChar(0x0a95);
2453         sample += QChar(0x0aa5);
2454         sample += QChar(0x0ab5);
2455         break;
2456     case Oriya:
2457         sample += QChar(0x0b06);
2458         sample += QChar(0x0b16);
2459         sample += QChar(0x0b2b);
2460         sample += QChar(0x0b36);
2461         break;
2462     case Tamil:
2463         sample += QChar(0x0b89);
2464         sample += QChar(0x0b99);
2465         sample += QChar(0x0ba9);
2466         sample += QChar(0x0bb9);
2467         break;
2468     case Telugu:
2469         sample += QChar(0x0c05);
2470         sample += QChar(0x0c15);
2471         sample += QChar(0x0c25);
2472         sample += QChar(0x0c35);
2473         break;
2474     case Kannada:
2475         sample += QChar(0x0c85);
2476         sample += QChar(0x0c95);
2477         sample += QChar(0x0ca5);
2478         sample += QChar(0x0cb5);
2479         break;
2480     case Malayalam:
2481         sample += QChar(0x0d05);
2482         sample += QChar(0x0d15);
2483         sample += QChar(0x0d25);
2484         sample += QChar(0x0d35);
2485         break;
2486     case Sinhala:
2487         sample += QChar(0x0d90);
2488         sample += QChar(0x0da0);
2489         sample += QChar(0x0db0);
2490         sample += QChar(0x0dc0);
2491         break;
2492     case Thai:
2493         sample += QChar(0x0e02);
2494         sample += QChar(0x0e12);
2495         sample += QChar(0x0e22);
2496         sample += QChar(0x0e32);
2497         break;
2498     case Lao:
2499         sample += QChar(0x0e8d);
2500         sample += QChar(0x0e9d);
2501         sample += QChar(0x0ead);
2502         sample += QChar(0x0ebd);
2503         break;
2504     case Tibetan:
2505         sample += QChar(0x0f00);
2506         sample += QChar(0x0f01);
2507         sample += QChar(0x0f02);
2508         sample += QChar(0x0f03);
2509         break;
2510     case Myanmar:
2511         sample += QChar(0x1000);
2512         sample += QChar(0x1001);
2513         sample += QChar(0x1002);
2514         sample += QChar(0x1003);
2515         break;
2516     case Georgian:
2517         sample += QChar(0x10a0);
2518         sample += QChar(0x10b0);
2519         sample += QChar(0x10c0);
2520         sample += QChar(0x10d0);
2521         break;
2522     case Khmer:
2523         sample += QChar(0x1780);
2524         sample += QChar(0x1790);
2525         sample += QChar(0x17b0);
2526         sample += QChar(0x17c0);
2527         break;
2528     case SimplifiedChinese:
2529         sample += QChar(0x4e2d);
2530         sample += QChar(0x6587);
2531         sample += QChar(0x8303);
2532         sample += QChar(0x4f8b);
2533         break;
2534     case TraditionalChinese:
2535         sample += QChar(0x4e2d);
2536         sample += QChar(0x6587);
2537         sample += QChar(0x7bc4);
2538         sample += QChar(0x4f8b);
2539         break;
2540     case Japanese:
2541         sample += QChar(0x30b5);
2542         sample += QChar(0x30f3);
2543         sample += QChar(0x30d7);
2544         sample += QChar(0x30eb);
2545         sample += QChar(0x3067);
2546         sample += QChar(0x3059);
2547         break;
2548     case Korean:
2549         sample += QChar(0xac00);
2550         sample += QChar(0xac11);
2551         sample += QChar(0xac1a);
2552         sample += QChar(0xac2f);
2553         break;
2554     case Vietnamese:
2555     {
2556         static const char vietnameseUtf8[] = {
2557             char(0xef), char(0xbb), char(0xbf), char(0xe1), char(0xbb), char(0x97),
2558             char(0xe1), char(0xbb), char(0x99),
2559             char(0xe1), char(0xbb), char(0x91),
2560             char(0xe1), char(0xbb), char(0x93),
2561         };
2562         sample += QString::fromUtf8(vietnameseUtf8, sizeof(vietnameseUtf8));
2563         break;
2564     }
2565     case Ogham:
2566         sample += QChar(0x1681);
2567         sample += QChar(0x1682);
2568         sample += QChar(0x1683);
2569         sample += QChar(0x1684);
2570         break;
2571     case Runic:
2572         sample += QChar(0x16a0);
2573         sample += QChar(0x16a1);
2574         sample += QChar(0x16a2);
2575         sample += QChar(0x16a3);
2576         break;
2577     case Nko:
2578         sample += QChar(0x7ca);
2579         sample += QChar(0x7cb);
2580         sample += QChar(0x7cc);
2581         sample += QChar(0x7cd);
2582         break;
2583     default:
2584         break;
2585     }
2586     return sample;
2587 }
2588
2589
2590 void QFontDatabase::parseFontName(const QString &name, QString &foundry, QString &family)
2591 {
2592     QT_PREPEND_NAMESPACE(parseFontName)(name, foundry, family);
2593 }
2594
2595 void QFontDatabase::createDatabase()
2596 { initializeDb(); }
2597
2598 // used from qfontengine_ft.cpp
2599 Q_GUI_EXPORT QByteArray qt_fontdata_from_index(int index)
2600 {
2601     QMutexLocker locker(fontDatabaseMutex());
2602     return privateDb()->applicationFonts.value(index).data;
2603 }
2604
2605 int QFontDatabasePrivate::addAppFont(const QByteArray &fontData, const QString &fileName)
2606 {
2607     QFontDatabasePrivate::ApplicationFont font;
2608     font.data = fontData;
2609     font.fileName = fileName;
2610
2611     int i;
2612     for (i = 0; i < applicationFonts.count(); ++i)
2613         if (applicationFonts.at(i).families.isEmpty())
2614             break;
2615     if (i >= applicationFonts.count()) {
2616         applicationFonts.append(ApplicationFont());
2617         i = applicationFonts.count() - 1;
2618     }
2619
2620     if (font.fileName.isEmpty() && !fontData.isEmpty())
2621         font.fileName = QString::fromLatin1(":qmemoryfonts/") + QString::number(i);
2622
2623     registerFont(&font);
2624     if (font.families.isEmpty())
2625         return -1;
2626
2627     applicationFonts[i] = font;
2628
2629     invalidate();
2630     return i;
2631 }
2632
2633 bool QFontDatabasePrivate::isApplicationFont(const QString &fileName)
2634 {
2635     for (int i = 0; i < applicationFonts.count(); ++i)
2636         if (applicationFonts.at(i).fileName == fileName)
2637             return true;
2638     return false;
2639 }
2640
2641 /*!
2642     \since 4.2
2643
2644     Loads the font from the file specified by \a fileName and makes it available to
2645     the application. An ID is returned that can be used to remove the font again
2646     with removeApplicationFont() or to retrieve the list of family names contained
2647     in the font.
2648
2649     The function returns -1 if the font could not be loaded.
2650
2651     Currently only TrueType fonts, TrueType font collections, and OpenType fonts are
2652     supported.
2653
2654     \note Adding application fonts on Unix/X11 platforms without fontconfig is
2655     currently not supported.
2656
2657     \note On Symbian, the font family names get truncated to a length of 20 characters.
2658
2659     \sa addApplicationFontFromData(), applicationFontFamilies(), removeApplicationFont()
2660 */
2661 int QFontDatabase::addApplicationFont(const QString &fileName)
2662 {
2663     QByteArray data;
2664     QFile f(fileName);
2665     if (!(f.fileEngine()->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::LocalDiskFlag)) {
2666         if (!f.open(QIODevice::ReadOnly))
2667             return -1;
2668         data = f.readAll();
2669     }
2670     QMutexLocker locker(fontDatabaseMutex());
2671     return privateDb()->addAppFont(data, fileName);
2672 }
2673
2674 /*!
2675     \since 4.2
2676
2677     Loads the font from binary data specified by \a fontData and makes it available to
2678     the application. An ID is returned that can be used to remove the font again
2679     with removeApplicationFont() or to retrieve the list of family names contained
2680     in the font.
2681
2682     The function returns -1 if the font could not be loaded.
2683
2684     Currently only TrueType fonts and TrueType font collections are supported.
2685
2686     \bold{Note:} Adding application fonts on Unix/X11 platforms without fontconfig is
2687     currently not supported.
2688
2689     \note On Symbian, the font family names get truncated to a length of 20 characters.
2690
2691     \sa addApplicationFont(), applicationFontFamilies(), removeApplicationFont()
2692 */
2693 int QFontDatabase::addApplicationFontFromData(const QByteArray &fontData)
2694 {
2695     QMutexLocker locker(fontDatabaseMutex());
2696     return privateDb()->addAppFont(fontData, QString() /* fileName */);
2697 }
2698
2699 /*!
2700     \since 4.2
2701
2702     Returns a list of font families for the given application font identified by
2703     \a id.
2704
2705     \sa addApplicationFont(), addApplicationFontFromData()
2706 */
2707 QStringList QFontDatabase::applicationFontFamilies(int id)
2708 {
2709     QMutexLocker locker(fontDatabaseMutex());
2710     return privateDb()->applicationFonts.value(id).families;
2711 }
2712
2713 /*!
2714     \fn bool QFontDatabase::removeApplicationFont(int id)
2715     \since 4.2
2716
2717     Removes the previously loaded application font identified by \a
2718     id. Returns true if unloading of the font succeeded; otherwise
2719     returns false.
2720
2721     \sa removeAllApplicationFonts(), addApplicationFont(),
2722         addApplicationFontFromData()
2723 */
2724
2725 /*!
2726     \fn bool QFontDatabase::removeAllApplicationFonts()
2727     \since 4.2
2728
2729     Removes all application-local fonts previously added using addApplicationFont()
2730     and addApplicationFontFromData().
2731
2732     Returns true if unloading of the fonts succeeded; otherwise
2733     returns false.
2734
2735     \sa removeApplicationFont(), addApplicationFont(), addApplicationFontFromData()
2736 */
2737
2738 /*!
2739     \fn bool QFontDatabase::supportsThreadedFontRendering()
2740     \since 4.4
2741
2742     Returns true if font rendering is supported outside the GUI
2743     thread, false otherwise. In other words, a return value of false
2744     means that all QPainter::drawText() calls outside the GUI thread
2745     will not produce readable output.
2746
2747     \sa {Thread-Support in Qt Modules#Painting In Threads}{Painting In Threads}
2748 */
2749
2750
2751 QT_END_NAMESPACE
2752