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