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