1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtGui module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qfontdatabase.h"
44 #include "qalgorithms.h"
45 #include "qguiapplication.h"
46 #include "qvarlengtharray.h" // here or earlier - workaround for VC++6
50 #include "qfileinfo.h"
51 #include "private/qunicodetables_p.h"
52 #include "qfontengine_p.h"
53 #include <qpa/qplatformintegration.h>
55 #include <QtGui/private/qguiapplication_p.h>
56 #include <qpa/qplatformfontdatabase.h>
62 // #define QFONTDATABASE_DEBUG
63 #ifdef QFONTDATABASE_DEBUG
64 # define FD_DEBUG qDebug
66 # define FD_DEBUG if (false) qDebug
69 // #define FONT_MATCH_DEBUG
70 #ifdef FONT_MATCH_DEBUG
71 # define FM_DEBUG qDebug
73 # define FM_DEBUG if (false) qDebug
79 #define SMOOTH_SCALABLE 0xffff
81 bool qt_enable_test_font = false;
83 Q_AUTOTEST_EXPORT void qt_setQtEnableTestFont(bool value)
85 qt_enable_test_font = value;
88 static int getFontWeight(const QString &weightString)
90 QString s = weightString.toLower();
92 // Test in decreasing order of commonness
93 if (s == QLatin1String("medium") ||
94 s == QLatin1String("normal")
95 || s.compare(QCoreApplication::translate("QFontDatabase", "Normal"), Qt::CaseInsensitive) == 0)
97 if (s == QLatin1String("bold")
98 || s.compare(QCoreApplication::translate("QFontDatabase", "Bold"), Qt::CaseInsensitive) == 0)
100 if (s == QLatin1String("demibold") || s == QLatin1String("demi bold")
101 || s.compare(QCoreApplication::translate("QFontDatabase", "Demi Bold"), Qt::CaseInsensitive) == 0)
102 return QFont::DemiBold;
103 if (s == QLatin1String("black")
104 || s.compare(QCoreApplication::translate("QFontDatabase", "Black"), Qt::CaseInsensitive) == 0)
106 if (s == QLatin1String("light"))
109 if (s.contains(QLatin1String("bold"))
110 || s.contains(QCoreApplication::translate("QFontDatabase", "Bold"), Qt::CaseInsensitive)) {
111 if (s.contains(QLatin1String("demi"))
112 || s.compare(QCoreApplication::translate("QFontDatabase", "Demi"), Qt::CaseInsensitive) == 0)
113 return (int) QFont::DemiBold;
114 return (int) QFont::Bold;
117 if (s.contains(QLatin1String("light"))
118 || s.compare(QCoreApplication::translate("QFontDatabase", "Light"), Qt::CaseInsensitive) == 0)
119 return (int) QFont::Light;
121 if (s.contains(QLatin1String("black"))
122 || s.compare(QCoreApplication::translate("QFontDatabase", "Black"), Qt::CaseInsensitive) == 0)
123 return (int) QFont::Black;
125 return (int) QFont::Normal;
128 // convert 0 ~ 1000 integer to QFont::Weight
129 QFont::Weight weightFromInteger(int weight)
133 else if (weight < 600)
134 return QFont::Normal;
135 else if (weight < 700)
136 return QFont::DemiBold;
137 else if (weight < 800)
143 struct QtFontEncoding
145 signed int encoding : 16;
159 unsigned short pixelSize : 16;
167 Key(const QString &styleString);
168 Key() : style(QFont::StyleNormal),
169 weight(QFont::Normal), stretch(0) { }
170 Key(const Key &o) : style(o.style), weight(o.weight), stretch(o.stretch) { }
172 signed int weight : 8;
173 signed int stretch : 12;
175 bool operator==(const Key & other) {
176 return (style == other.style && weight == other.weight &&
177 (stretch == 0 || other.stretch == 0 || stretch == other.stretch));
179 bool operator!=(const Key &other) {
180 return !operator==(other);
182 bool operator <(const Key &o) {
183 int x = (style << 12) + (weight << 14) + stretch;
184 int y = (o.style << 12) + (o.weight << 14) + o.stretch;
189 QtFontStyle(const Key &k)
190 : key(k), bitmapScalable(false), smoothScalable(false),
191 count(0), pixelSizes(0)
197 // bitfield count-- in while condition does not work correctly in mwccsym2
199 QPlatformIntegration *integration = QGuiApplicationPrivate::platformIntegration();
201 integration->fontDatabase()->releaseHandle(pixelSizes[count].handle);
208 bool bitmapScalable : 1;
209 bool smoothScalable : 1;
210 signed int count : 30;
211 QtFontSize *pixelSizes;
216 QtFontSize *pixelSize(unsigned short size, bool = false);
219 QtFontStyle::Key::Key(const QString &styleString)
220 : style(QFont::StyleNormal), weight(QFont::Normal), stretch(0)
222 weight = getFontWeight(styleString);
224 if (styleString.contains(QLatin1String("Italic"))
225 || styleString.contains(QCoreApplication::translate("QFontDatabase", "Italic")))
226 style = QFont::StyleItalic;
227 else if (styleString.contains(QLatin1String("Oblique"))
228 || styleString.contains(QCoreApplication::translate("QFontDatabase", "Oblique")))
229 style = QFont::StyleOblique;
232 QtFontSize *QtFontStyle::pixelSize(unsigned short size, bool add)
234 for (int i = 0; i < count; i++) {
235 if (pixelSizes[i].pixelSize == size)
236 return pixelSizes + i;
242 // Most style have only one font size, we avoid waisting memory
243 QtFontSize *newPixelSizes = (QtFontSize *)malloc(sizeof(QtFontSize));
244 Q_CHECK_PTR(newPixelSizes);
245 pixelSizes = newPixelSizes;
246 } else if (!(count % 8) || count == 1) {
247 QtFontSize *newPixelSizes = (QtFontSize *)
249 (((count+8) >> 3) << 3) * sizeof(QtFontSize));
250 Q_CHECK_PTR(newPixelSizes);
251 pixelSizes = newPixelSizes;
253 pixelSizes[count].pixelSize = size;
254 pixelSizes[count].handle = 0;
255 return pixelSizes + (count++);
260 QtFontFoundry(const QString &n) : name(n), count(0), styles(0) {}
263 delete styles[count];
270 QtFontStyle **styles;
271 QtFontStyle *style(const QtFontStyle::Key &, const QString & = QString(), bool = false);
274 QtFontStyle *QtFontFoundry::style(const QtFontStyle::Key &key, const QString &styleName, bool create)
278 // if styleName for searching first if possible
279 if (!styleName.isEmpty()) {
280 for (; pos < count; pos++) {
281 if (styles[pos]->styleName == styleName)
289 if (styles[pos]->key == key)
291 if (styles[pos]->key < key)
295 pos = (high + low) / 2;
302 // qDebug("adding key (weight=%d, style=%d, oblique=%d stretch=%d) at %d", key.weight, key.style, key.oblique, key.stretch, pos);
304 QtFontStyle **newStyles = (QtFontStyle **)
305 realloc(styles, (((count+8) >> 3) << 3) * sizeof(QtFontStyle *));
306 Q_CHECK_PTR(newStyles);
310 QtFontStyle *style = new QtFontStyle(key);
311 style->styleName = styleName;
312 memmove(styles + pos + 1, styles + pos, (count-pos)*sizeof(QtFontStyle *));
321 enum WritingSystemStatus {
326 Unsupported = UnsupportedFT | UnsupportedXLFD
329 QtFontFamily(const QString &n)
332 #if !defined(QWS) && defined(Q_OS_MAC)
333 fixedPitchComputed(false),
335 name(n), count(0), foundries(0)
336 , bogusWritingSystems(false)
337 , askedForFallback(false)
339 memset(writingSystems, 0, sizeof(writingSystems));
343 delete foundries[count];
348 #if !defined(QWS) && defined(Q_OS_MAC)
349 bool fixedPitchComputed : 1;
355 QtFontFoundry **foundries;
357 bool bogusWritingSystems;
358 QStringList fallbackFamilies;
359 bool askedForFallback;
360 unsigned char writingSystems[QFontDatabase::WritingSystemsCount];
362 QtFontFoundry *foundry(const QString &f, bool = false);
365 #if !defined(QWS) && defined(Q_OS_MAC)
366 inline static void qt_mac_get_fixed_pitch(QtFontFamily *f)
368 if(f && !f->fixedPitchComputed) {
369 QFontMetrics fm(f->name);
370 f->fixedPitch = fm.width(QLatin1Char('i')) == fm.width(QLatin1Char('m'));
371 f->fixedPitchComputed = true;
377 QtFontFoundry *QtFontFamily::foundry(const QString &f, bool create)
379 if (f.isNull() && count == 1)
382 for (int i = 0; i < count; i++) {
383 if (foundries[i]->name.compare(f, Qt::CaseInsensitive) == 0)
390 QtFontFoundry **newFoundries = (QtFontFoundry **)
392 (((count+8) >> 3) << 3) * sizeof(QtFontFoundry *));
393 Q_CHECK_PTR(newFoundries);
394 foundries = newFoundries;
397 foundries[count] = new QtFontFoundry(f);
398 return foundries[count++];
401 // ### copied to tools/makeqpf/qpf2.cpp
403 // see the Unicode subset bitfields in the MSDN docs
404 static int requiredUnicodeBits[QFontDatabase::WritingSystemsCount][2] = {
455 // SimplifiedChinese,
457 // TraditionalChinese,
464 { 0, 127 }, // same as latin1
475 #define SimplifiedChineseCsbBit 18
476 #define TraditionalChineseCsbBit 20
477 #define JapaneseCsbBit 17
478 #define KoreanCsbBit 21
480 QList<QFontDatabase::WritingSystem> qt_determine_writing_systems_from_truetype_bits(quint32 unicodeRange[4], quint32 codePageRange[2])
482 QList<QFontDatabase::WritingSystem> writingSystems;
483 bool hasScript = false;
486 for(i = 0; i < QFontDatabase::WritingSystemsCount; i++) {
487 int bit = requiredUnicodeBits[i][0];
489 int flag = 1 << (bit&31);
490 if (bit != 126 && unicodeRange[index] & flag) {
491 bit = requiredUnicodeBits[i][1];
494 flag = 1 << (bit&31);
495 if (bit == 127 || unicodeRange[index] & flag) {
496 writingSystems.append(QFontDatabase::WritingSystem(i));
498 // qDebug("font %s: index=%d, flag=%8x supports script %d", familyName.latin1(), index, flag, i);
502 if(codePageRange[0] & (1 << SimplifiedChineseCsbBit)) {
503 writingSystems.append(QFontDatabase::SimplifiedChinese);
505 //qDebug("font %s supports Simplified Chinese", familyName.latin1());
507 if(codePageRange[0] & (1 << TraditionalChineseCsbBit)) {
508 writingSystems.append(QFontDatabase::TraditionalChinese);
510 //qDebug("font %s supports Traditional Chinese", familyName.latin1());
512 if(codePageRange[0] & (1 << JapaneseCsbBit)) {
513 writingSystems.append(QFontDatabase::Japanese);
515 //qDebug("font %s supports Japanese", familyName.latin1());
517 if(codePageRange[0] & (1 << KoreanCsbBit)) {
518 writingSystems.append(QFontDatabase::Korean);
520 //qDebug("font %s supports Korean", familyName.latin1());
523 writingSystems.append(QFontDatabase::Symbol);
525 return writingSystems;
529 class QFontDatabasePrivate
532 QFontDatabasePrivate()
533 : count(0), families(0), reregisterAppFonts(false)
536 ~QFontDatabasePrivate() {
539 QtFontFamily *family(const QString &f, bool = false);
542 delete families[count];
546 // don't clear the memory fonts!
550 QtFontFamily **families;
554 struct ApplicationFont {
557 QStringList families;
559 QVector<ApplicationFont> applicationFonts;
560 int addAppFont(const QByteArray &fontData, const QString &fileName);
561 bool reregisterAppFonts;
562 bool isApplicationFont(const QString &fileName);
566 QStringList fallbackFamilies;
569 void QFontDatabasePrivate::invalidate()
571 QFontCache::instance()->clear();
573 emit static_cast<QGuiApplication *>(QCoreApplication::instance())->fontDatabaseChanged();
576 QtFontFamily *QFontDatabasePrivate::family(const QString &f, bool create)
583 while ((res = families[pos]->name.compare(f, Qt::CaseInsensitive)) && pos != low) {
588 pos = (high + low) / 2;
591 return families[pos];
599 // qDebug("adding family %s at %d total=%d", f.latin1(), pos, count);
601 QtFontFamily **newFamilies = (QtFontFamily **)
603 (((count+8) >> 3) << 3) * sizeof(QtFontFamily *));
604 Q_CHECK_PTR(newFamilies);
605 families = newFamilies;
608 QtFontFamily *family = new QtFontFamily(f);
609 memmove(families + pos + 1, families + pos, (count-pos)*sizeof(QtFontFamily *));
610 families[pos] = family;
612 return families[pos];
617 static const int scriptForWritingSystem[] = {
618 QUnicodeTables::Common, // Any
619 QUnicodeTables::Latin, // Latin
620 QUnicodeTables::Greek, // Greek
621 QUnicodeTables::Cyrillic, // Cyrillic
622 QUnicodeTables::Armenian, // Armenian
623 QUnicodeTables::Hebrew, // Hebrew
624 QUnicodeTables::Arabic, // Arabic
625 QUnicodeTables::Syriac, // Syriac
626 QUnicodeTables::Thaana, // Thaana
627 QUnicodeTables::Devanagari, // Devanagari
628 QUnicodeTables::Bengali, // Bengali
629 QUnicodeTables::Gurmukhi, // Gurmukhi
630 QUnicodeTables::Gujarati, // Gujarati
631 QUnicodeTables::Oriya, // Oriya
632 QUnicodeTables::Tamil, // Tamil
633 QUnicodeTables::Telugu, // Telugu
634 QUnicodeTables::Kannada, // Kannada
635 QUnicodeTables::Malayalam, // Malayalam
636 QUnicodeTables::Sinhala, // Sinhala
637 QUnicodeTables::Thai, // Thai
638 QUnicodeTables::Lao, // Lao
639 QUnicodeTables::Tibetan, // Tibetan
640 QUnicodeTables::Myanmar, // Myanmar
641 QUnicodeTables::Georgian, // Georgian
642 QUnicodeTables::Khmer, // Khmer
643 QUnicodeTables::Common, // SimplifiedChinese
644 QUnicodeTables::Common, // TraditionalChinese
645 QUnicodeTables::Common, // Japanese
646 QUnicodeTables::Hangul, // Korean
647 QUnicodeTables::Common, // Vietnamese
648 QUnicodeTables::Common, // Yi
649 QUnicodeTables::Common, // Tagalog
650 QUnicodeTables::Common, // Hanunoo
651 QUnicodeTables::Common, // Buhid
652 QUnicodeTables::Common, // Tagbanwa
653 QUnicodeTables::Common, // Limbu
654 QUnicodeTables::Common, // TaiLe
655 QUnicodeTables::Common, // Braille
656 QUnicodeTables::Common, // Symbol
657 QUnicodeTables::Ogham, // Ogham
658 QUnicodeTables::Runic, // Runic
659 QUnicodeTables::Nko // Nko
662 int qt_script_for_writing_system(QFontDatabase::WritingSystem writingSystem)
664 return scriptForWritingSystem[writingSystem];
673 This makes sense of the font family name:
675 if the family name contains a '[' and a ']', then we take the text
676 between the square brackets as the foundry, and the text before the
677 square brackets as the family (ie. "Arial [Monotype]")
679 static void parseFontName(const QString &name, QString &foundry, QString &family)
681 int i = name.indexOf(QLatin1Char('['));
682 int li = name.lastIndexOf(QLatin1Char(']'));
683 if (i >= 0 && li >= 0 && i < li) {
684 foundry = name.mid(i + 1, li - i - 1);
685 if (i > 0 && name[i - 1] == QLatin1Char(' '))
687 family = name.left(i);
693 // capitalize the family/foundry names
695 QChar *s = family.data();
696 int len = family.length();
698 if (space) *s = s->toUpper();
699 space = s->isSpace();
705 len = foundry.length();
707 if (space) *s = s->toUpper();
708 space = s->isSpace();
716 inline QtFontDesc() : family(0), foundry(0), style(0), size(0), encoding(0), familyIndex(-1) {}
717 QtFontFamily *family;
718 QtFontFoundry *foundry;
721 QtFontEncoding *encoding;
725 static void match(int script, const QFontDef &request,
726 const QString &family_name, const QString &foundry_name, int force_encoding_id,
727 QtFontDesc *desc, const QList<int> &blacklistedFamilies = QList<int>(), bool forceXLFD=false);
729 static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDef *fontDef, bool multi)
731 fontDef->family = desc.family->name;
732 if (! desc.foundry->name.isEmpty() && desc.family->count > 1) {
733 fontDef->family += QString::fromLatin1(" [");
734 fontDef->family += desc.foundry->name;
735 fontDef->family += QLatin1Char(']');
738 if (desc.style->smoothScalable
739 || QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fontsAlwaysScalable()
740 || (desc.style->bitmapScalable && (request.styleStrategy & QFont::PreferMatch))) {
741 fontDef->pixelSize = request.pixelSize;
743 fontDef->pixelSize = desc.size->pixelSize;
746 fontDef->styleHint = request.styleHint;
747 fontDef->styleStrategy = request.styleStrategy;
750 fontDef->weight = desc.style->key.weight;
752 fontDef->style = desc.style->key.style;
753 fontDef->fixedPitch = desc.family->fixedPitch;
754 fontDef->stretch = desc.style->key.stretch;
755 fontDef->ignorePitch = false;
758 static void getEngineData(const QFontPrivate *d, const QFontDef &def)
760 // look for the requested font in the engine data cache
761 d->engineData = QFontCache::instance()->findEngineData(def);
762 if (!d->engineData) {
764 d->engineData = new QFontEngineData;
765 QFontCache::instance()->insertEngineData(def, d->engineData);
767 d->engineData->ref.ref();
771 static QStringList familyList(const QFontDef &req)
773 // list of families to try
774 QStringList family_list;
775 if (req.family.isEmpty())
778 QStringList list = req.family.split(QLatin1Char(','));
779 for (int i = 0; i < list.size(); ++i) {
780 QString str = list.at(i).trimmed();
781 if ((str.startsWith(QLatin1Char('"')) && str.endsWith(QLatin1Char('"')))
782 || (str.startsWith(QLatin1Char('\'')) && str.endsWith(QLatin1Char('\''))))
783 str = str.mid(1, str.length() - 2);
787 // append the substitute list for each family in family_list
788 QStringList subs_list;
789 QStringList::ConstIterator it = family_list.constBegin(), end = family_list.constEnd();
790 for (; it != end; ++it)
791 subs_list += QFont::substitutes(*it);
792 // qDebug() << "adding substs: " << subs_list;
794 family_list += subs_list;
799 Q_GLOBAL_STATIC(QFontDatabasePrivate, privateDb)
800 Q_GLOBAL_STATIC_WITH_ARGS(QMutex, fontDatabaseMutex, (QMutex::Recursive))
802 // used in qguiapplication.cpp
803 void qt_cleanupFontDatabase()
805 QFontDatabasePrivate *db = privateDb();
810 // used in qfontengine_x11.cpp
811 QMutex *qt_fontdatabase_mutex()
813 return fontDatabaseMutex();
816 QT_BEGIN_INCLUDE_NAMESPACE
817 # include "qfontdatabase_qpa.cpp"
818 QT_END_INCLUDE_NAMESPACE
820 static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &styleKey,
821 const QString &styleName = QString())
826 for ( int i = 0; i < foundry->count; i++ ) {
827 QtFontStyle *style = foundry->styles[i];
829 if (!styleName.isEmpty() && styleName == style->styleName) {
835 int d = qAbs( styleKey.weight - style->key.weight );
837 if ( styleKey.stretch != 0 && style->key.stretch != 0 ) {
838 d += qAbs( styleKey.stretch - style->key.stretch );
841 if (styleKey.style != style->key.style) {
842 if (styleKey.style != QFont::StyleNormal && style->key.style != QFont::StyleNormal)
843 // one is italic, the other oblique
855 FM_DEBUG( " best style has distance 0x%x", dist );
856 return foundry->styles[best];
861 unsigned int bestFoundry(int script, unsigned int score, int styleStrategy,
862 const QtFontFamily *family, const QString &foundry_name,
863 QtFontStyle::Key styleKey, int pixelSize, char pitch,
864 QtFontDesc *desc, int force_encoding_id)
866 Q_UNUSED(force_encoding_id);
876 FM_DEBUG(" REMARK: looking for best foundry for family '%s' [%d]", family->name.toLatin1().constData(), family->count);
878 for (int x = 0; x < family->count; ++x) {
879 QtFontFoundry *foundry = family->foundries[x];
880 if (!foundry_name.isEmpty() && foundry->name.compare(foundry_name, Qt::CaseInsensitive) != 0)
883 FM_DEBUG(" looking for matching style in foundry '%s' %d",
884 foundry->name.isEmpty() ? "-- none --" : foundry->name.toLatin1().constData(), foundry->count);
886 QtFontStyle *style = bestStyle(foundry, styleKey);
888 if (!style->smoothScalable && (styleStrategy & QFont::ForceOutline)) {
889 FM_DEBUG(" ForceOutline set, but not smoothly scalable");
894 QtFontSize *size = 0;
896 // 1. see if we have an exact matching size
897 if (!(styleStrategy & QFont::ForceOutline)) {
898 size = style->pixelSize(pixelSize);
900 FM_DEBUG(" found exact size match (%d pixels)", size->pixelSize);
901 px = size->pixelSize;
905 // 2. see if we have a smoothly scalable font
906 if (!size && style->smoothScalable && ! (styleStrategy & QFont::PreferBitmap)) {
907 size = style->pixelSize(SMOOTH_SCALABLE);
909 FM_DEBUG(" found smoothly scalable font (%d pixels)", pixelSize);
914 // 3. see if we have a bitmap scalable font
915 if (!size && style->bitmapScalable && (styleStrategy & QFont::PreferMatch)) {
916 size = style->pixelSize(0);
918 FM_DEBUG(" found bitmap scalable font (%d pixels)", pixelSize);
924 // 4. find closest size match
926 unsigned int distance = ~0u;
927 for (int x = 0; x < style->count; ++x) {
930 if (style->pixelSizes[x].pixelSize < pixelSize) {
931 // penalize sizes that are smaller than the
932 // requested size, due to truncation from floating
933 // point to integer conversions
934 d = pixelSize - style->pixelSizes[x].pixelSize + 1;
936 d = style->pixelSizes[x].pixelSize - pixelSize;
941 size = style->pixelSizes + x;
942 FM_DEBUG(" best size so far: %3d (%d)", size->pixelSize, pixelSize);
947 FM_DEBUG(" no size supports the script we want");
951 if (style->bitmapScalable && ! (styleStrategy & QFont::PreferQuality) &&
952 (distance * 10 / pixelSize) >= 2) {
953 // the closest size is not close enough, go ahead and
954 // use a bitmap scaled font
955 size = style->pixelSize(0);
958 px = size->pixelSize;
963 unsigned int this_score = 0x0000;
965 PitchMismatch = 0x4000,
966 StyleMismatch = 0x2000,
967 BitmapScaledPenalty = 0x1000,
968 EncodingMismatch = 0x0002,
972 #if !defined(QWS) && defined(Q_OS_MAC)
973 qt_mac_get_fixed_pitch(const_cast<QtFontFamily*>(family));
975 if ((pitch == 'm' && !family->fixedPitch)
976 || (pitch == 'p' && family->fixedPitch))
977 this_score += PitchMismatch;
979 if (styleKey != style->key)
980 this_score += StyleMismatch;
981 if (!style->smoothScalable && px != size->pixelSize) // bitmap scaled
982 this_score += BitmapScaledPenalty;
983 if (px != pixelSize) // close, but not exact, size match
984 this_score += qAbs(px - pixelSize);
986 if (this_score < score) {
987 FM_DEBUG(" found a match: score %x best score so far %x",
991 desc->foundry = foundry;
995 FM_DEBUG(" score %x no better than best %x", this_score, score);
1002 static bool matchFamilyName(const QString &familyName, QtFontFamily *f)
1004 if (familyName.isEmpty())
1007 if (f->name.compare(familyName, Qt::CaseInsensitive) == 0)
1010 QStringList::const_iterator it = f->aliases.constBegin();
1011 while (it != f->aliases.constEnd()) {
1012 if ((*it).compare(familyName, Qt::CaseInsensitive) == 0)
1024 Tries to find the best match for a given request and family/foundry
1026 static void match(int script, const QFontDef &request,
1027 const QString &family_name, const QString &foundry_name, int force_encoding_id,
1028 QtFontDesc *desc, const QList<int> &blacklistedFamilies, bool forceXLFD)
1030 Q_UNUSED(force_encoding_id);
1032 QtFontStyle::Key styleKey;
1033 styleKey.style = request.style;
1034 styleKey.weight = request.weight;
1035 styleKey.stretch = request.stretch;
1036 char pitch = request.ignorePitch ? '*' : request.fixedPitch ? 'm' : 'p';
1039 FM_DEBUG("QFontDatabase::match\n"
1041 " family: %s [%s], script: %d\n"
1042 " weight: %d, style: %d\n"
1046 family_name.isEmpty() ? "-- first in script --" : family_name.toLatin1().constData(),
1047 foundry_name.isEmpty() ? "-- any --" : foundry_name.toLatin1().constData(),
1048 script, request.weight, request.style, request.stretch, request.pixelSize, pitch);
1055 desc->familyIndex = -1;
1057 unsigned int score = ~0u;
1059 Q_UNUSED(forceXLFD);
1060 load(family_name, script);
1062 QFontDatabasePrivate *db = privateDb();
1063 for (int x = 0; x < db->count; ++x) {
1064 if (blacklistedFamilies.contains(x))
1067 test.family = db->families[x];
1068 test.familyIndex = x;
1070 if (!matchFamilyName(family_name, test.family))
1073 if (family_name.isEmpty())
1074 load(test.family->name, script);
1076 uint score_adjust = 0;
1078 bool supported = (script == QUnicodeTables::Common);
1079 for (int ws = 1; !supported && ws < QFontDatabase::WritingSystemsCount; ++ws) {
1080 if (scriptForWritingSystem[ws] != script)
1082 if (test.family->writingSystems[ws] & QtFontFamily::Supported)
1086 // family not supported in the script we want
1090 // as we know the script is supported, we can be sure
1091 // to find a matching font here.
1092 unsigned int newscore =
1093 bestFoundry(script, score, request.styleStrategy,
1094 test.family, foundry_name, styleKey, request.pixelSize, pitch,
1095 &test, force_encoding_id);
1096 if (test.foundry == 0) {
1097 // the specific foundry was not found, so look for
1098 // any foundry matching our requirements
1099 newscore = bestFoundry(script, score, request.styleStrategy, test.family,
1100 QString(), styleKey, request.pixelSize,
1101 pitch, &test, force_encoding_id);
1103 newscore += score_adjust;
1105 if (newscore < score) {
1109 if (newscore < 10) // xlfd instead of FT... just accept it
1114 static QString styleStringHelper(int weight, QFont::Style style)
1117 if (weight >= QFont::Black)
1118 result = QCoreApplication::translate("QFontDatabase", "Black");
1119 else if (weight >= QFont::Bold)
1120 result = QCoreApplication::translate("QFontDatabase", "Bold");
1121 else if (weight >= QFont::DemiBold)
1122 result = QCoreApplication::translate("QFontDatabase", "Demi Bold");
1123 else if (weight < QFont::Normal)
1124 result = QCoreApplication::translate("QFontDatabase", "Light");
1126 if (style == QFont::StyleItalic)
1127 result += QLatin1Char(' ') + QCoreApplication::translate("QFontDatabase", "Italic");
1128 else if (style == QFont::StyleOblique)
1129 result += QLatin1Char(' ') + QCoreApplication::translate("QFontDatabase", "Oblique");
1131 if (result.isEmpty())
1132 result = QCoreApplication::translate("QFontDatabase", "Normal");
1134 return result.simplified();
1138 Returns a string that describes the style of the \a font. For
1139 example, "Bold Italic", "Bold", "Italic" or "Normal". An empty
1140 string may be returned.
1142 QString QFontDatabase::styleString(const QFont &font)
1144 return font.styleName().isEmpty() ? styleStringHelper(font.weight(), font.style())
1149 Returns a string that describes the style of the \a fontInfo. For
1150 example, "Bold Italic", "Bold", "Italic" or "Normal". An empty
1151 string may be returned.
1153 QString QFontDatabase::styleString(const QFontInfo &fontInfo)
1155 return fontInfo.styleName().isEmpty() ? styleStringHelper(fontInfo.weight(), fontInfo.style())
1156 : fontInfo.styleName();
1161 \class QFontDatabase
1164 \brief The QFontDatabase class provides information about the fonts available in the underlying window system.
1168 The most common uses of this class are to query the database for
1169 the list of font families() and for the pointSizes() and styles()
1170 that are available for each family. An alternative to pointSizes()
1171 is smoothSizes() which returns the sizes at which a given family
1172 and style will look attractive.
1174 If the font family is available from two or more foundries the
1175 foundry name is included in the family name; for example:
1176 "Helvetica [Adobe]" and "Helvetica [Cronyx]". When you specify a
1177 family, you can either use the old hyphenated "foundry-family"
1178 format or the bracketed "family [foundry]" format; for example:
1179 "Cronyx-Helvetica" or "Helvetica [Cronyx]". If the family has a
1180 foundry it is always returned using the bracketed format, as is
1181 the case with the value returned by families().
1183 The font() function returns a QFont given a family, style and
1186 A family and style combination can be checked to see if it is
1187 italic() or bold(), and to retrieve its weight(). Similarly we can
1188 call isBitmapScalable(), isSmoothlyScalable(), isScalable() and
1191 Use the styleString() to obtain a text version of a style.
1193 The QFontDatabase class also supports some static functions, for
1194 example, standardSizes(). You can retrieve the description of a
1195 writing system using writingSystemName(), and a sample of
1196 characters in a writing system with writingSystemSample().
1200 \snippet qfontdatabase/main.cpp 0
1201 \snippet qfontdatabase/main.cpp 1
1203 This example gets the list of font families, the list of
1204 styles for each family, and the point sizes that are available for
1205 each combination of family and style, displaying this information
1208 \sa QFont, QFontInfo, QFontMetrics, QFontComboBox, {Character Map Example}
1212 Creates a font database object.
1214 QFontDatabase::QFontDatabase()
1216 QMutexLocker locker(fontDatabaseMutex());
1222 \enum QFontDatabase::WritingSystem
1249 \value SimplifiedChinese
1250 \value TraditionalChinese
1255 \value Other (the same as Symbol)
1260 \omitvalue WritingSystemsCount
1264 Returns a sorted list of the available writing systems. This is
1265 list generated from information about all installed fonts on the
1270 QList<QFontDatabase::WritingSystem> QFontDatabase::writingSystems() const
1272 QMutexLocker locker(fontDatabaseMutex());
1274 QT_PREPEND_NAMESPACE(load)();
1276 QList<WritingSystem> list;
1277 for (int i = 0; i < d->count; ++i) {
1278 QtFontFamily *family = d->families[i];
1279 if (family->count == 0)
1281 for (int x = Latin; x < WritingSystemsCount; ++x) {
1282 const WritingSystem writingSystem = WritingSystem(x);
1283 if (!(family->writingSystems[writingSystem] & QtFontFamily::Supported))
1285 if (!list.contains(writingSystem))
1286 list.append(writingSystem);
1295 Returns a sorted list of the writing systems supported by a given
1300 QList<QFontDatabase::WritingSystem> QFontDatabase::writingSystems(const QString &family) const
1302 QString familyName, foundryName;
1303 parseFontName(family, foundryName, familyName);
1305 QMutexLocker locker(fontDatabaseMutex());
1307 QT_PREPEND_NAMESPACE(load)();
1309 QList<WritingSystem> list;
1310 QtFontFamily *f = d->family(familyName);
1311 if (!f || f->count == 0)
1314 for (int x = Latin; x < WritingSystemsCount; ++x) {
1315 const WritingSystem writingSystem = WritingSystem(x);
1316 if (f->writingSystems[writingSystem] & QtFontFamily::Supported)
1317 list.append(writingSystem);
1324 Returns a sorted list of the available font families which support
1325 the \a writingSystem.
1327 If a family exists in several foundries, the returned name for
1328 that font is in the form "family [foundry]". Examples: "Times
1329 [Adobe]", "Times [Cronyx]", "Palatino".
1331 \sa writingSystems()
1333 QStringList QFontDatabase::families(WritingSystem writingSystem) const
1335 QMutexLocker locker(fontDatabaseMutex());
1337 QT_PREPEND_NAMESPACE(load)();
1340 for (int i = 0; i < d->count; i++) {
1341 QtFontFamily *f = d->families[i];
1344 if (writingSystem != Any && (f->writingSystems[writingSystem] != QtFontFamily::Supported))
1346 if (f->count == 1) {
1347 flist.append(f->name);
1349 for (int j = 0; j < f->count; j++) {
1350 QString str = f->name;
1351 QString foundry = f->foundries[j]->name;
1352 if (!foundry.isEmpty()) {
1353 str += QLatin1String(" [");
1355 str += QLatin1Char(']');
1365 Returns a list of the styles available for the font family \a
1366 family. Some example styles: "Light", "Light Italic", "Bold",
1367 "Oblique", "Demi". The list may be empty.
1371 QStringList QFontDatabase::styles(const QString &family) const
1373 QString familyName, foundryName;
1374 parseFontName(family, foundryName, familyName);
1376 QMutexLocker locker(fontDatabaseMutex());
1378 QT_PREPEND_NAMESPACE(load)(familyName);
1381 QtFontFamily *f = d->family(familyName);
1385 QtFontFoundry allStyles(foundryName);
1386 for (int j = 0; j < f->count; j++) {
1387 QtFontFoundry *foundry = f->foundries[j];
1388 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1389 for (int k = 0; k < foundry->count; k++) {
1390 QtFontStyle::Key ke(foundry->styles[k]->key);
1392 allStyles.style(ke, foundry->styles[k]->styleName, true);
1397 for (int i = 0; i < allStyles.count; i++) {
1398 l.append(allStyles.styles[i]->styleName.isEmpty() ?
1399 styleStringHelper(allStyles.styles[i]->key.weight,
1400 (QFont::Style)allStyles.styles[i]->key.style) :
1401 allStyles.styles[i]->styleName);
1407 Returns true if the font that has family \a family and style \a
1408 style is fixed pitch; otherwise returns false.
1411 bool QFontDatabase::isFixedPitch(const QString &family,
1412 const QString &style) const
1416 QString familyName, foundryName;
1417 parseFontName(family, foundryName, familyName);
1419 QMutexLocker locker(fontDatabaseMutex());
1421 QT_PREPEND_NAMESPACE(load)(familyName);
1423 QtFontFamily *f = d->family(familyName);
1424 #if !defined(QWS) && defined(Q_OS_MAC)
1425 qt_mac_get_fixed_pitch(f);
1427 return (f && f->fixedPitch);
1431 Returns true if the font that has family \a family and style \a
1432 style is a scalable bitmap font; otherwise returns false. Scaling
1433 a bitmap font usually produces an unattractive hardly readable
1434 result, because the pixels of the font are scaled. If you need to
1435 scale a bitmap font it is better to scale it to one of the fixed
1436 sizes returned by smoothSizes().
1438 \sa isScalable(), isSmoothlyScalable()
1440 bool QFontDatabase::isBitmapScalable(const QString &family,
1441 const QString &style) const
1443 bool bitmapScalable = false;
1444 QString familyName, foundryName;
1445 parseFontName(family, foundryName, familyName);
1447 QMutexLocker locker(fontDatabaseMutex());
1449 QT_PREPEND_NAMESPACE(load)(familyName);
1451 QtFontStyle::Key styleKey(style);
1453 QtFontFamily *f = d->family(familyName);
1454 if (!f) return bitmapScalable;
1456 for (int j = 0; j < f->count; j++) {
1457 QtFontFoundry *foundry = f->foundries[j];
1458 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1459 for (int k = 0; k < foundry->count; k++)
1460 if ((style.isEmpty() ||
1461 foundry->styles[k]->styleName == style ||
1462 foundry->styles[k]->key == styleKey)
1463 && foundry->styles[k]->bitmapScalable && !foundry->styles[k]->smoothScalable) {
1464 bitmapScalable = true;
1470 return bitmapScalable;
1475 Returns true if the font that has family \a family and style \a
1476 style is smoothly scalable; otherwise returns false. If this
1477 function returns true, it's safe to scale this font to any size,
1478 and the result will always look attractive.
1480 \sa isScalable(), isBitmapScalable()
1482 bool QFontDatabase::isSmoothlyScalable(const QString &family, const QString &style) const
1484 bool smoothScalable = false;
1485 QString familyName, foundryName;
1486 parseFontName(family, foundryName, familyName);
1488 QMutexLocker locker(fontDatabaseMutex());
1490 QT_PREPEND_NAMESPACE(load)(familyName);
1492 QtFontStyle::Key styleKey(style);
1494 QtFontFamily *f = d->family(familyName);
1495 if (!f) return smoothScalable;
1497 for (int j = 0; j < f->count; j++) {
1498 QtFontFoundry *foundry = f->foundries[j];
1499 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1500 for (int k = 0; k < foundry->count; k++)
1501 if ((style.isEmpty() ||
1502 foundry->styles[k]->styleName == style ||
1503 foundry->styles[k]->key == styleKey) && foundry->styles[k]->smoothScalable) {
1504 smoothScalable = true;
1510 return smoothScalable;
1514 Returns true if the font that has family \a family and style \a
1515 style is scalable; otherwise returns false.
1517 \sa isBitmapScalable(), isSmoothlyScalable()
1519 bool QFontDatabase::isScalable(const QString &family,
1520 const QString &style) const
1522 QMutexLocker locker(fontDatabaseMutex());
1523 if (isSmoothlyScalable(family, style))
1525 return isBitmapScalable(family, style);
1530 Returns a list of the point sizes available for the font that has
1531 family \a family and style \a style. The list may be empty.
1533 \sa smoothSizes(), standardSizes()
1535 QList<int> QFontDatabase::pointSizes(const QString &family,
1536 const QString &styleName)
1538 if (QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fontsAlwaysScalable())
1539 return standardSizes();
1541 bool smoothScalable = false;
1542 QString familyName, foundryName;
1543 parseFontName(family, foundryName, familyName);
1545 QMutexLocker locker(fontDatabaseMutex());
1547 QT_PREPEND_NAMESPACE(load)(familyName);
1549 QtFontStyle::Key styleKey(styleName);
1553 QtFontFamily *fam = d->family(familyName);
1554 if (!fam) return sizes;
1557 const int dpi = qt_defaultDpiY(); // embedded
1559 for (int j = 0; j < fam->count; j++) {
1560 QtFontFoundry *foundry = fam->foundries[j];
1561 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1562 QtFontStyle *style = foundry->style(styleKey, styleName);
1563 if (!style) continue;
1565 if (style->smoothScalable) {
1566 smoothScalable = true;
1569 for (int l = 0; l < style->count; l++) {
1570 const QtFontSize *size = style->pixelSizes + l;
1572 if (size->pixelSize != 0 && size->pixelSize != USHRT_MAX) {
1573 const uint pointSize = qRound(size->pixelSize * 72.0 / dpi);
1574 if (! sizes.contains(pointSize))
1575 sizes.append(pointSize);
1582 return standardSizes();
1589 Returns a QFont object that has family \a family, style \a style
1590 and point size \a pointSize. If no matching font could be created,
1591 a QFont object that uses the application's default font is
1594 QFont QFontDatabase::font(const QString &family, const QString &style,
1595 int pointSize) const
1597 QString familyName, foundryName;
1598 parseFontName(family, foundryName, familyName);
1600 QMutexLocker locker(fontDatabaseMutex());
1602 QT_PREPEND_NAMESPACE(load)(familyName);
1604 QtFontFoundry allStyles(foundryName);
1605 QtFontFamily *f = d->family(familyName);
1606 if (!f) return QGuiApplication::font();
1608 for (int j = 0; j < f->count; j++) {
1609 QtFontFoundry *foundry = f->foundries[j];
1610 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1611 for (int k = 0; k < foundry->count; k++)
1612 allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true);
1616 QtFontStyle::Key styleKey(style);
1617 QtFontStyle *s = bestStyle(&allStyles, styleKey, style);
1619 if (!s) // no styles found?
1620 return QGuiApplication::font();
1622 QFont fnt(family, pointSize, s->key.weight);
1623 fnt.setStyle((QFont::Style)s->key.style);
1624 if (!s->styleName.isEmpty())
1625 fnt.setStyleName(s->styleName);
1631 Returns the point sizes of a font that has family \a family and
1632 style \a style that will look attractive. The list may be empty.
1633 For non-scalable fonts and bitmap scalable fonts, this function
1634 is equivalent to pointSizes().
1636 \sa pointSizes(), standardSizes()
1638 QList<int> QFontDatabase::smoothSizes(const QString &family,
1639 const QString &styleName)
1641 if (QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fontsAlwaysScalable())
1642 return standardSizes();
1644 bool smoothScalable = false;
1645 QString familyName, foundryName;
1646 parseFontName(family, foundryName, familyName);
1648 QMutexLocker locker(fontDatabaseMutex());
1650 QT_PREPEND_NAMESPACE(load)(familyName);
1652 QtFontStyle::Key styleKey(styleName);
1656 QtFontFamily *fam = d->family(familyName);
1660 const int dpi = qt_defaultDpiY(); // embedded
1662 for (int j = 0; j < fam->count; j++) {
1663 QtFontFoundry *foundry = fam->foundries[j];
1664 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1665 QtFontStyle *style = foundry->style(styleKey, styleName);
1666 if (!style) continue;
1668 if (style->smoothScalable) {
1669 smoothScalable = true;
1672 for (int l = 0; l < style->count; l++) {
1673 const QtFontSize *size = style->pixelSizes + l;
1675 if (size->pixelSize != 0 && size->pixelSize != USHRT_MAX) {
1676 const uint pointSize = qRound(size->pixelSize * 72.0 / dpi);
1677 if (! sizes.contains(pointSize))
1678 sizes.append(pointSize);
1685 return QFontDatabase::standardSizes();
1693 Returns a list of standard font sizes.
1695 \sa smoothSizes(), pointSizes()
1697 QList<int> QFontDatabase::standardSizes()
1699 return QGuiApplicationPrivate::platformIntegration()->fontDatabase()->standardSizes();
1704 Returns true if the font that has family \a family and style \a
1705 style is italic; otherwise returns false.
1707 \sa weight(), bold()
1709 bool QFontDatabase::italic(const QString &family, const QString &style) const
1711 QString familyName, foundryName;
1712 parseFontName(family, foundryName, familyName);
1714 QMutexLocker locker(fontDatabaseMutex());
1716 QT_PREPEND_NAMESPACE(load)(familyName);
1718 QtFontFoundry allStyles(foundryName);
1719 QtFontFamily *f = d->family(familyName);
1720 if (!f) return false;
1722 for (int j = 0; j < f->count; j++) {
1723 QtFontFoundry *foundry = f->foundries[j];
1724 if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1725 for (int k = 0; k < foundry->count; k++)
1726 allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true);
1730 QtFontStyle::Key styleKey(style);
1731 QtFontStyle *s = allStyles.style(styleKey, style);
1732 return s && s->key.style == QFont::StyleItalic;
1737 Returns true if the font that has family \a family and style \a
1738 style is bold; otherwise returns false.
1740 \sa italic(), weight()
1742 bool QFontDatabase::bold(const QString &family,
1743 const QString &style) const
1745 QString familyName, foundryName;
1746 parseFontName(family, foundryName, familyName);
1748 QMutexLocker locker(fontDatabaseMutex());
1750 QT_PREPEND_NAMESPACE(load)(familyName);
1752 QtFontFoundry allStyles(foundryName);
1753 QtFontFamily *f = d->family(familyName);
1754 if (!f) return false;
1756 for (int j = 0; j < f->count; j++) {
1757 QtFontFoundry *foundry = f->foundries[j];
1758 if (foundryName.isEmpty() ||
1759 foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1760 for (int k = 0; k < foundry->count; k++)
1761 allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true);
1765 QtFontStyle::Key styleKey(style);
1766 QtFontStyle *s = allStyles.style(styleKey, style);
1767 return s && s->key.weight >= QFont::Bold;
1772 Returns the weight of the font that has family \a family and style
1773 \a style. If there is no such family and style combination,
1776 \sa italic(), bold()
1778 int QFontDatabase::weight(const QString &family,
1779 const QString &style) const
1781 QString familyName, foundryName;
1782 parseFontName(family, foundryName, familyName);
1784 QMutexLocker locker(fontDatabaseMutex());
1786 QT_PREPEND_NAMESPACE(load)(familyName);
1788 QtFontFoundry allStyles(foundryName);
1789 QtFontFamily *f = d->family(familyName);
1792 for (int j = 0; j < f->count; j++) {
1793 QtFontFoundry *foundry = f->foundries[j];
1794 if (foundryName.isEmpty() ||
1795 foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
1796 for (int k = 0; k < foundry->count; k++)
1797 allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true);
1801 QtFontStyle::Key styleKey(style);
1802 QtFontStyle *s = allStyles.style(styleKey, style);
1803 return s ? s->key.weight : -1;
1808 bool QFontDatabase::hasFamily(const QString &family) const
1810 QString parsedFamily, foundry;
1811 parseFontName(family, foundry, parsedFamily);
1812 const QString familyAlias = resolveFontFamilyAlias(parsedFamily);
1813 return families().contains(familyAlias, Qt::CaseInsensitive);
1818 Returns the names the \a writingSystem (e.g. for displaying to the
1821 QString QFontDatabase::writingSystemName(WritingSystem writingSystem)
1823 const char *name = 0;
1824 switch (writingSystem) {
1826 name = QT_TRANSLATE_NOOP("QFontDatabase", "Any");
1829 name = QT_TRANSLATE_NOOP("QFontDatabase", "Latin");
1832 name = QT_TRANSLATE_NOOP("QFontDatabase", "Greek");
1835 name = QT_TRANSLATE_NOOP("QFontDatabase", "Cyrillic");
1838 name = QT_TRANSLATE_NOOP("QFontDatabase", "Armenian");
1841 name = QT_TRANSLATE_NOOP("QFontDatabase", "Hebrew");
1844 name = QT_TRANSLATE_NOOP("QFontDatabase", "Arabic");
1847 name = QT_TRANSLATE_NOOP("QFontDatabase", "Syriac");
1850 name = QT_TRANSLATE_NOOP("QFontDatabase", "Thaana");
1853 name = QT_TRANSLATE_NOOP("QFontDatabase", "Devanagari");
1856 name = QT_TRANSLATE_NOOP("QFontDatabase", "Bengali");
1859 name = QT_TRANSLATE_NOOP("QFontDatabase", "Gurmukhi");
1862 name = QT_TRANSLATE_NOOP("QFontDatabase", "Gujarati");
1865 name = QT_TRANSLATE_NOOP("QFontDatabase", "Oriya");
1868 name = QT_TRANSLATE_NOOP("QFontDatabase", "Tamil");
1871 name = QT_TRANSLATE_NOOP("QFontDatabase", "Telugu");
1874 name = QT_TRANSLATE_NOOP("QFontDatabase", "Kannada");
1877 name = QT_TRANSLATE_NOOP("QFontDatabase", "Malayalam");
1880 name = QT_TRANSLATE_NOOP("QFontDatabase", "Sinhala");
1883 name = QT_TRANSLATE_NOOP("QFontDatabase", "Thai");
1886 name = QT_TRANSLATE_NOOP("QFontDatabase", "Lao");
1889 name = QT_TRANSLATE_NOOP("QFontDatabase", "Tibetan");
1892 name = QT_TRANSLATE_NOOP("QFontDatabase", "Myanmar");
1895 name = QT_TRANSLATE_NOOP("QFontDatabase", "Georgian");
1898 name = QT_TRANSLATE_NOOP("QFontDatabase", "Khmer");
1900 case SimplifiedChinese:
1901 name = QT_TRANSLATE_NOOP("QFontDatabase", "Simplified Chinese");
1903 case TraditionalChinese:
1904 name = QT_TRANSLATE_NOOP("QFontDatabase", "Traditional Chinese");
1907 name = QT_TRANSLATE_NOOP("QFontDatabase", "Japanese");
1910 name = QT_TRANSLATE_NOOP("QFontDatabase", "Korean");
1913 name = QT_TRANSLATE_NOOP("QFontDatabase", "Vietnamese");
1916 name = QT_TRANSLATE_NOOP("QFontDatabase", "Symbol");
1919 name = QT_TRANSLATE_NOOP("QFontDatabase", "Ogham");
1922 name = QT_TRANSLATE_NOOP("QFontDatabase", "Runic");
1925 name = QT_TRANSLATE_NOOP("QFontDatabase", "N'Ko");
1928 Q_ASSERT_X(false, "QFontDatabase::writingSystemName", "invalid 'writingSystem' parameter");
1931 return QCoreApplication::translate("QFontDatabase", name);
1936 Returns a string with sample characters from \a writingSystem.
1938 QString QFontDatabase::writingSystemSample(WritingSystem writingSystem)
1941 switch (writingSystem) {
1944 // show only ascii characters
1945 sample += QLatin1String("AaBbzZ");
1948 // This is cheating... we only show latin-1 characters so that we don't
1949 // end up loading lots of fonts - at least on X11...
1950 sample = QLatin1String("Aa");
1951 sample += QChar(0x00C3);
1952 sample += QChar(0x00E1);
1953 sample += QLatin1String("Zz");
1956 sample += QChar(0x0393);
1957 sample += QChar(0x03B1);
1958 sample += QChar(0x03A9);
1959 sample += QChar(0x03C9);
1962 sample += QChar(0x0414);
1963 sample += QChar(0x0434);
1964 sample += QChar(0x0436);
1965 sample += QChar(0x044f);
1968 sample += QChar(0x053f);
1969 sample += QChar(0x054f);
1970 sample += QChar(0x056f);
1971 sample += QChar(0x057f);
1974 sample += QChar(0x05D0);
1975 sample += QChar(0x05D1);
1976 sample += QChar(0x05D2);
1977 sample += QChar(0x05D3);
1980 sample += QChar(0x0628);
1981 sample += QChar(0x0629);
1982 sample += QChar(0x062A);
1983 sample += QChar(0x063A);
1986 sample += QChar(0x0715);
1987 sample += QChar(0x0725);
1988 sample += QChar(0x0716);
1989 sample += QChar(0x0726);
1992 sample += QChar(0x0784);
1993 sample += QChar(0x0794);
1994 sample += QChar(0x078c);
1995 sample += QChar(0x078d);
1998 sample += QChar(0x0905);
1999 sample += QChar(0x0915);
2000 sample += QChar(0x0925);
2001 sample += QChar(0x0935);
2004 sample += QChar(0x0986);
2005 sample += QChar(0x0996);
2006 sample += QChar(0x09a6);
2007 sample += QChar(0x09b6);
2010 sample += QChar(0x0a05);
2011 sample += QChar(0x0a15);
2012 sample += QChar(0x0a25);
2013 sample += QChar(0x0a35);
2016 sample += QChar(0x0a85);
2017 sample += QChar(0x0a95);
2018 sample += QChar(0x0aa5);
2019 sample += QChar(0x0ab5);
2022 sample += QChar(0x0b06);
2023 sample += QChar(0x0b16);
2024 sample += QChar(0x0b2b);
2025 sample += QChar(0x0b36);
2028 sample += QChar(0x0b89);
2029 sample += QChar(0x0b99);
2030 sample += QChar(0x0ba9);
2031 sample += QChar(0x0bb9);
2034 sample += QChar(0x0c05);
2035 sample += QChar(0x0c15);
2036 sample += QChar(0x0c25);
2037 sample += QChar(0x0c35);
2040 sample += QChar(0x0c85);
2041 sample += QChar(0x0c95);
2042 sample += QChar(0x0ca5);
2043 sample += QChar(0x0cb5);
2046 sample += QChar(0x0d05);
2047 sample += QChar(0x0d15);
2048 sample += QChar(0x0d25);
2049 sample += QChar(0x0d35);
2052 sample += QChar(0x0d90);
2053 sample += QChar(0x0da0);
2054 sample += QChar(0x0db0);
2055 sample += QChar(0x0dc0);
2058 sample += QChar(0x0e02);
2059 sample += QChar(0x0e12);
2060 sample += QChar(0x0e22);
2061 sample += QChar(0x0e32);
2064 sample += QChar(0x0e8d);
2065 sample += QChar(0x0e9d);
2066 sample += QChar(0x0ead);
2067 sample += QChar(0x0ebd);
2070 sample += QChar(0x0f00);
2071 sample += QChar(0x0f01);
2072 sample += QChar(0x0f02);
2073 sample += QChar(0x0f03);
2076 sample += QChar(0x1000);
2077 sample += QChar(0x1001);
2078 sample += QChar(0x1002);
2079 sample += QChar(0x1003);
2082 sample += QChar(0x10a0);
2083 sample += QChar(0x10b0);
2084 sample += QChar(0x10c0);
2085 sample += QChar(0x10d0);
2088 sample += QChar(0x1780);
2089 sample += QChar(0x1790);
2090 sample += QChar(0x17b0);
2091 sample += QChar(0x17c0);
2093 case SimplifiedChinese:
2094 sample += QChar(0x4e2d);
2095 sample += QChar(0x6587);
2096 sample += QChar(0x8303);
2097 sample += QChar(0x4f8b);
2099 case TraditionalChinese:
2100 sample += QChar(0x4e2d);
2101 sample += QChar(0x6587);
2102 sample += QChar(0x7bc4);
2103 sample += QChar(0x4f8b);
2106 sample += QChar(0x30b5);
2107 sample += QChar(0x30f3);
2108 sample += QChar(0x30d7);
2109 sample += QChar(0x30eb);
2110 sample += QChar(0x3067);
2111 sample += QChar(0x3059);
2114 sample += QChar(0xac00);
2115 sample += QChar(0xac11);
2116 sample += QChar(0xac1a);
2117 sample += QChar(0xac2f);
2121 static const char vietnameseUtf8[] = {
2122 char(0xef), char(0xbb), char(0xbf), char(0xe1), char(0xbb), char(0x97),
2123 char(0xe1), char(0xbb), char(0x99),
2124 char(0xe1), char(0xbb), char(0x91),
2125 char(0xe1), char(0xbb), char(0x93),
2127 sample += QString::fromUtf8(vietnameseUtf8, sizeof(vietnameseUtf8));
2131 sample += QChar(0x1681);
2132 sample += QChar(0x1682);
2133 sample += QChar(0x1683);
2134 sample += QChar(0x1684);
2137 sample += QChar(0x16a0);
2138 sample += QChar(0x16a1);
2139 sample += QChar(0x16a2);
2140 sample += QChar(0x16a3);
2143 sample += QChar(0x7ca);
2144 sample += QChar(0x7cb);
2145 sample += QChar(0x7cc);
2146 sample += QChar(0x7cd);
2155 void QFontDatabase::parseFontName(const QString &name, QString &foundry, QString &family)
2157 QT_PREPEND_NAMESPACE(parseFontName)(name, foundry, family);
2160 void QFontDatabase::createDatabase()
2163 // used from qfontengine_ft.cpp
2164 Q_GUI_EXPORT QByteArray qt_fontdata_from_index(int index)
2166 QMutexLocker locker(fontDatabaseMutex());
2167 return privateDb()->applicationFonts.value(index).data;
2170 int QFontDatabasePrivate::addAppFont(const QByteArray &fontData, const QString &fileName)
2172 QFontDatabasePrivate::ApplicationFont font;
2173 font.data = fontData;
2174 font.fileName = fileName;
2177 for (i = 0; i < applicationFonts.count(); ++i)
2178 if (applicationFonts.at(i).families.isEmpty())
2180 if (i >= applicationFonts.count()) {
2181 applicationFonts.append(ApplicationFont());
2182 i = applicationFonts.count() - 1;
2185 if (font.fileName.isEmpty() && !fontData.isEmpty())
2186 font.fileName = QString::fromLatin1(":qmemoryfonts/") + QString::number(i);
2188 registerFont(&font);
2189 if (font.families.isEmpty())
2192 applicationFonts[i] = font;
2198 bool QFontDatabasePrivate::isApplicationFont(const QString &fileName)
2200 for (int i = 0; i < applicationFonts.count(); ++i)
2201 if (applicationFonts.at(i).fileName == fileName)
2209 Loads the font from the file specified by \a fileName and makes it available to
2210 the application. An ID is returned that can be used to remove the font again
2211 with removeApplicationFont() or to retrieve the list of family names contained
2214 The function returns -1 if the font could not be loaded.
2216 Currently only TrueType fonts, TrueType font collections, and OpenType fonts are
2219 \note Adding application fonts on Unix/X11 platforms without fontconfig is
2220 currently not supported.
2222 \sa addApplicationFontFromData(), applicationFontFamilies(), removeApplicationFont()
2224 int QFontDatabase::addApplicationFont(const QString &fileName)
2227 if (!QFileInfo(fileName).isNativePath()) {
2229 if (!f.open(QIODevice::ReadOnly))
2233 QMutexLocker locker(fontDatabaseMutex());
2234 return privateDb()->addAppFont(data, fileName);
2240 Loads the font from binary data specified by \a fontData and makes it available to
2241 the application. An ID is returned that can be used to remove the font again
2242 with removeApplicationFont() or to retrieve the list of family names contained
2245 The function returns -1 if the font could not be loaded.
2247 Currently only TrueType fonts and TrueType font collections are supported.
2249 \b{Note:} Adding application fonts on Unix/X11 platforms without fontconfig is
2250 currently not supported.
2252 \sa addApplicationFont(), applicationFontFamilies(), removeApplicationFont()
2254 int QFontDatabase::addApplicationFontFromData(const QByteArray &fontData)
2256 QMutexLocker locker(fontDatabaseMutex());
2257 return privateDb()->addAppFont(fontData, QString() /* fileName */);
2263 Returns a list of font families for the given application font identified by
2266 \sa addApplicationFont(), addApplicationFontFromData()
2268 QStringList QFontDatabase::applicationFontFamilies(int id)
2270 QMutexLocker locker(fontDatabaseMutex());
2271 return privateDb()->applicationFonts.value(id).families;
2275 \fn bool QFontDatabase::removeApplicationFont(int id)
2278 Removes the previously loaded application font identified by \a
2279 id. Returns true if unloading of the font succeeded; otherwise
2282 \sa removeAllApplicationFonts(), addApplicationFont(),
2283 addApplicationFontFromData()
2287 \fn bool QFontDatabase::removeAllApplicationFonts()
2290 Removes all application-local fonts previously added using addApplicationFont()
2291 and addApplicationFontFromData().
2293 Returns true if unloading of the fonts succeeded; otherwise
2296 \sa removeApplicationFont(), addApplicationFont(), addApplicationFontFromData()
2300 \fn bool QFontDatabase::supportsThreadedFontRendering()
2303 Returns true if font rendering is supported outside the GUI
2304 thread, false otherwise. In other words, a return value of false
2305 means that all QPainter::drawText() calls outside the GUI thread
2306 will not produce readable output.
2308 \sa {Thread-Support in Qt Modules#Painting In Threads}{Painting In Threads}