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