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