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