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