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