util/src/gui/text/qfontdatabase_win.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 "qt_windows.h"
       
    43 #include <qmath.h>
       
    44 #include <private/qapplication_p.h>
       
    45 #include "qfont_p.h"
       
    46 #include "qfontengine_p.h"
       
    47 #include "qpaintdevice.h"
       
    48 #include "qlibrary.h"
       
    49 #include "qabstractfileengine.h"
       
    50 #include "qendian.h"
       
    51 
       
    52 #ifdef Q_OS_WINCE
       
    53 #   include <QTemporaryFile>
       
    54 #endif
       
    55 
       
    56 QT_BEGIN_NAMESPACE
       
    57 
       
    58 extern HDC   shared_dc();                // common dc for all fonts
       
    59 
       
    60 #ifdef MAKE_TAG
       
    61 #undef MAKE_TAG
       
    62 #endif
       
    63 // GetFontData expects the tags in little endian ;(
       
    64 #define MAKE_TAG(ch1, ch2, ch3, ch4) (\
       
    65     (((quint32)(ch4)) << 24) | \
       
    66     (((quint32)(ch3)) << 16) | \
       
    67     (((quint32)(ch2)) << 8) | \
       
    68     ((quint32)(ch1)) \
       
    69    )
       
    70 
       
    71 static HFONT stock_sysfont  = 0;
       
    72 
       
    73 static bool localizedName(const QString &name)
       
    74 {
       
    75     const QChar *c = name.unicode();
       
    76     for(int i = 0; i < name.length(); ++i) {
       
    77         if(c[i].unicode() >= 0x100)
       
    78             return true;
       
    79     }
       
    80     return false;
       
    81 }
       
    82 
       
    83 static inline quint16 getUShort(const unsigned char *p)
       
    84 {
       
    85     quint16 val;
       
    86     val = *p++ << 8;
       
    87     val |= *p;
       
    88 
       
    89     return val;
       
    90 }
       
    91 
       
    92 static QString getEnglishName(const uchar *table, quint32 bytes)
       
    93 {
       
    94     QString i18n_name;
       
    95     enum {
       
    96         NameRecordSize = 12,
       
    97         FamilyId = 1,
       
    98         MS_LangIdEnglish = 0x009
       
    99     };
       
   100 
       
   101     // get the name table
       
   102     quint16 count;
       
   103     quint16 string_offset;
       
   104     const unsigned char *names;
       
   105 
       
   106     int microsoft_id = -1;
       
   107     int apple_id = -1;
       
   108     int unicode_id = -1;
       
   109 
       
   110     if(getUShort(table) != 0)
       
   111         goto error;
       
   112 
       
   113     count = getUShort(table+2);
       
   114     string_offset = getUShort(table+4);
       
   115     names = table + 6;
       
   116 
       
   117     if(string_offset >= bytes || 6 + count*NameRecordSize > string_offset)
       
   118         goto error;
       
   119 
       
   120     for(int i = 0; i < count; ++i) {
       
   121         // search for the correct name entry
       
   122 
       
   123         quint16 platform_id = getUShort(names + i*NameRecordSize);
       
   124         quint16 encoding_id = getUShort(names + 2 + i*NameRecordSize);
       
   125         quint16 language_id = getUShort(names + 4 + i*NameRecordSize);
       
   126         quint16 name_id = getUShort(names + 6 + i*NameRecordSize);
       
   127 
       
   128         if(name_id != FamilyId)
       
   129             continue;
       
   130 
       
   131         enum {
       
   132             PlatformId_Unicode = 0,
       
   133             PlatformId_Apple = 1,
       
   134             PlatformId_Microsoft = 3
       
   135         };
       
   136 
       
   137         quint16 length = getUShort(names + 8 + i*NameRecordSize);
       
   138         quint16 offset = getUShort(names + 10 + i*NameRecordSize);
       
   139         if(DWORD(string_offset + offset + length) >= bytes)
       
   140             continue;
       
   141 
       
   142         if ((platform_id == PlatformId_Microsoft
       
   143             && (encoding_id == 0 || encoding_id == 1))
       
   144             && (language_id & 0x3ff) == MS_LangIdEnglish
       
   145             && microsoft_id == -1)
       
   146             microsoft_id = i;
       
   147             // not sure if encoding id 4 for Unicode is utf16 or ucs4...
       
   148         else if(platform_id == PlatformId_Unicode && encoding_id < 4 && unicode_id == -1)
       
   149             unicode_id = i;
       
   150         else if(platform_id == PlatformId_Apple && encoding_id == 0 && language_id == 0)
       
   151             apple_id = i;
       
   152     }
       
   153     {
       
   154         bool unicode = false;
       
   155         int id = -1;
       
   156         if(microsoft_id != -1) {
       
   157             id = microsoft_id;
       
   158             unicode = true;
       
   159         } else if(apple_id != -1) {
       
   160             id = apple_id;
       
   161             unicode = false;
       
   162         } else if (unicode_id != -1) {
       
   163             id = unicode_id;
       
   164             unicode = true;
       
   165         }
       
   166         if(id != -1) {
       
   167             quint16 length = getUShort(names + 8 + id*NameRecordSize);
       
   168             quint16 offset = getUShort(names + 10 + id*NameRecordSize);
       
   169             if(unicode) {
       
   170                 // utf16
       
   171 
       
   172                 length /= 2;
       
   173                 i18n_name.resize(length);
       
   174                 QChar *uc = (QChar *) i18n_name.unicode();
       
   175                 const unsigned char *string = table + string_offset + offset;
       
   176                 for(int i = 0; i < length; ++i)
       
   177                     uc[i] = getUShort(string + 2*i);
       
   178             } else {
       
   179                 // Apple Roman
       
   180 
       
   181                 i18n_name.resize(length);
       
   182                 QChar *uc = (QChar *) i18n_name.unicode();
       
   183                 const unsigned char *string = table + string_offset + offset;
       
   184                 for(int i = 0; i < length; ++i)
       
   185                     uc[i] = QLatin1Char(string[i]);
       
   186             }
       
   187         }
       
   188     }
       
   189   error:
       
   190     //qDebug("got i18n name of '%s' for font '%s'", i18n_name.latin1(), familyName.toLocal8Bit().data());
       
   191     return i18n_name;
       
   192 }
       
   193 
       
   194 static QString getEnglishName(const QString &familyName)
       
   195 {
       
   196     QString i18n_name;
       
   197 
       
   198     HDC hdc = GetDC( 0 );
       
   199     LOGFONT lf;
       
   200     memset(&lf, 0, sizeof(LOGFONT));
       
   201     memcpy(lf.lfFaceName, familyName.utf16(), qMin(LF_FACESIZE, familyName.length()) * sizeof(wchar_t));
       
   202     lf.lfCharSet = DEFAULT_CHARSET;
       
   203     HFONT hfont = CreateFontIndirect(&lf);
       
   204 
       
   205     if(!hfont) {
       
   206         ReleaseDC(0, hdc);
       
   207         return QString();
       
   208     }
       
   209 
       
   210     HGDIOBJ oldobj = SelectObject( hdc, hfont );
       
   211 
       
   212     const DWORD name_tag = MAKE_TAG( 'n', 'a', 'm', 'e' );
       
   213 
       
   214     // get the name table
       
   215     unsigned char *table = 0;
       
   216 
       
   217     DWORD bytes = GetFontData( hdc, name_tag, 0, 0, 0 );
       
   218     if ( bytes == GDI_ERROR ) {
       
   219         // ### Unused variable
       
   220         /* int err = GetLastError(); */
       
   221         goto error;
       
   222     }
       
   223 
       
   224     table = new unsigned char[bytes];
       
   225     GetFontData(hdc, name_tag, 0, table, bytes);
       
   226     if ( bytes == GDI_ERROR )
       
   227         goto error;
       
   228 
       
   229     i18n_name = getEnglishName(table, bytes);
       
   230 error:
       
   231     delete [] table;
       
   232     SelectObject( hdc, oldobj );
       
   233     DeleteObject( hfont );
       
   234     ReleaseDC( 0, hdc );
       
   235 
       
   236     //qDebug("got i18n name of '%s' for font '%s'", i18n_name.latin1(), familyName.toLocal8Bit().data());
       
   237     return i18n_name;
       
   238 }
       
   239 
       
   240 static
       
   241 void addFontToDatabase(QString familyName, const QString &scriptName,
       
   242                        TEXTMETRIC *textmetric,
       
   243                        const FONTSIGNATURE *signature,
       
   244                        int type)
       
   245 {
       
   246     const int script = -1;
       
   247     const QString foundryName;
       
   248     Q_UNUSED(script);
       
   249 
       
   250     bool italic = false;
       
   251     int weight;
       
   252     bool fixed;
       
   253     bool ttf;
       
   254     bool scalable;
       
   255     int size;
       
   256 
       
   257 //    QString escript = QString::fromWCharArray(f->elfScript);
       
   258 //    qDebug("script=%s", escript.latin1());
       
   259 
       
   260     NEWTEXTMETRIC *tm = (NEWTEXTMETRIC *)textmetric;
       
   261     fixed = !(tm->tmPitchAndFamily & TMPF_FIXED_PITCH);
       
   262     ttf = (tm->tmPitchAndFamily & TMPF_TRUETYPE);
       
   263     scalable = tm->tmPitchAndFamily & (TMPF_VECTOR|TMPF_TRUETYPE);
       
   264     size = scalable ? SMOOTH_SCALABLE : tm->tmHeight;
       
   265     italic = tm->tmItalic;
       
   266     weight = tm->tmWeight;
       
   267 
       
   268     // the "@family" fonts are just the same as "family". Ignore them.
       
   269     if (familyName[0] != QLatin1Char('@') && !familyName.startsWith(QLatin1String("WST_"))) {
       
   270         QtFontStyle::Key styleKey;
       
   271         styleKey.style = italic ? QFont::StyleItalic : QFont::StyleNormal;
       
   272         if (weight < 400)
       
   273             styleKey.weight = QFont::Light;
       
   274         else if (weight < 600)
       
   275             styleKey.weight = QFont::Normal;
       
   276         else if (weight < 700)
       
   277             styleKey.weight = QFont::DemiBold;
       
   278         else if (weight < 800)
       
   279             styleKey.weight = QFont::Bold;
       
   280         else
       
   281             styleKey.weight = QFont::Black;
       
   282 
       
   283         QtFontFamily *family = privateDb()->family(familyName, true);
       
   284 
       
   285         if(ttf && localizedName(familyName) && family->english_name.isEmpty())
       
   286             family->english_name = getEnglishName(familyName);
       
   287 
       
   288         QtFontFoundry *foundry = family->foundry(foundryName, true);
       
   289         QtFontStyle *style = foundry->style(styleKey, true);
       
   290         style->smoothScalable = scalable;
       
   291         style->pixelSize( size, TRUE);
       
   292 
       
   293         // add fonts windows can generate for us:
       
   294         if (styleKey.weight <= QFont::DemiBold) {
       
   295             QtFontStyle::Key key(styleKey);
       
   296             key.weight = QFont::Bold;
       
   297             QtFontStyle *style = foundry->style(key, true);
       
   298             style->smoothScalable = scalable;
       
   299             style->pixelSize( size, TRUE);
       
   300         }
       
   301         if (styleKey.style != QFont::StyleItalic) {
       
   302             QtFontStyle::Key key(styleKey);
       
   303             key.style = QFont::StyleItalic;
       
   304             QtFontStyle *style = foundry->style(key, true);
       
   305             style->smoothScalable = scalable;
       
   306             style->pixelSize( size, TRUE);
       
   307         }
       
   308         if (styleKey.weight <= QFont::DemiBold && styleKey.style != QFont::StyleItalic) {
       
   309             QtFontStyle::Key key(styleKey);
       
   310             key.weight = QFont::Bold;
       
   311             key.style = QFont::StyleItalic;
       
   312             QtFontStyle *style = foundry->style(key, true);
       
   313             style->smoothScalable = scalable;
       
   314             style->pixelSize( size, TRUE);
       
   315         }
       
   316 
       
   317         family->fixedPitch = fixed;
       
   318 
       
   319         if (!family->writingSystemCheck && type & TRUETYPE_FONTTYPE) {
       
   320             quint32 unicodeRange[4] = {
       
   321                 signature->fsUsb[0], signature->fsUsb[1],
       
   322                 signature->fsUsb[2], signature->fsUsb[3]
       
   323             };
       
   324 #ifdef Q_WS_WINCE
       
   325             if (signature->fsUsb[0] == 0) {
       
   326                 // If the unicode ranges bit mask is zero then
       
   327                 // EnumFontFamiliesEx failed to determine it properly.
       
   328                 // In this case we just pretend that the font supports all languages.
       
   329                 unicodeRange[0] = 0xbfffffff;   // second most significant bit must be zero
       
   330                 unicodeRange[1] = 0xffffffff;
       
   331                 unicodeRange[2] = 0xffffffff;
       
   332                 unicodeRange[3] = 0xffffffff;
       
   333             }
       
   334 #endif
       
   335             quint32 codePageRange[2] = {
       
   336                 signature->fsCsb[0], signature->fsCsb[1]
       
   337             };
       
   338             QList<QFontDatabase::WritingSystem> systems = determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
       
   339 
       
   340             for (int i = 0; i < systems.count(); ++i) {
       
   341                 QFontDatabase::WritingSystem writingSystem = systems.at(i);
       
   342 
       
   343                 // ### Hack to work around problem with Thai text on Windows 7. Segoe UI contains
       
   344                 // the symbol for Baht, and Windows thus reports that it supports the Thai script.
       
   345                 // Since it's the default UI font on this platform, most widgets will be unable to
       
   346                 // display Thai text by default. As a temporary work around, we special case Segoe UI
       
   347                 // and remove the Thai script from its list of supported writing systems.
       
   348                 if (writingSystem != QFontDatabase::Thai || familyName != QLatin1String("Segoe UI"))
       
   349                     family->writingSystems[writingSystem] = QtFontFamily::Supported;
       
   350             }
       
   351         } else if (!family->writingSystemCheck) {
       
   352             //qDebug("family='%s' script=%s", family->name.latin1(), script.latin1());
       
   353             if (scriptName == QLatin1String("Western")
       
   354                 || scriptName == QLatin1String("Baltic")
       
   355                 || scriptName == QLatin1String("Central European")
       
   356                 || scriptName == QLatin1String("Turkish")
       
   357                 || scriptName == QLatin1String("Vietnamese"))
       
   358                 family->writingSystems[QFontDatabase::Latin] = QtFontFamily::Supported;
       
   359             else if (scriptName == QLatin1String("Thai"))
       
   360                 family->writingSystems[QFontDatabase::Thai] = QtFontFamily::Supported;
       
   361             else if (scriptName == QLatin1String("Symbol")
       
   362                      || scriptName == QLatin1String("Other"))
       
   363                 family->writingSystems[QFontDatabase::Symbol] = QtFontFamily::Supported;
       
   364             else if (scriptName == QLatin1String("OEM/Dos"))
       
   365                 family->writingSystems[QFontDatabase::Latin] = QtFontFamily::Supported;
       
   366             else if (scriptName == QLatin1String("CHINESE_GB2312"))
       
   367                 family->writingSystems[QFontDatabase::SimplifiedChinese] = QtFontFamily::Supported;
       
   368             else if (scriptName == QLatin1String("CHINESE_BIG5"))
       
   369                 family->writingSystems[QFontDatabase::TraditionalChinese] = QtFontFamily::Supported;
       
   370             else if (scriptName == QLatin1String("Cyrillic"))
       
   371                 family->writingSystems[QFontDatabase::Cyrillic] = QtFontFamily::Supported;
       
   372             else if (scriptName == QLatin1String("Hangul"))
       
   373                 family->writingSystems[QFontDatabase::Korean] = QtFontFamily::Supported;
       
   374             else if (scriptName == QLatin1String("Hebrew"))
       
   375                 family->writingSystems[QFontDatabase::Hebrew] = QtFontFamily::Supported;
       
   376             else if (scriptName == QLatin1String("Greek"))
       
   377                 family->writingSystems[QFontDatabase::Greek] = QtFontFamily::Supported;
       
   378             else if (scriptName == QLatin1String("Japanese"))
       
   379                 family->writingSystems[QFontDatabase::Japanese] = QtFontFamily::Supported;
       
   380             else if (scriptName == QLatin1String("Arabic"))
       
   381                 family->writingSystems[QFontDatabase::Arabic] = QtFontFamily::Supported;
       
   382         }
       
   383     }
       
   384 }
       
   385 
       
   386 static
       
   387 int CALLBACK
       
   388 storeFont(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textmetric, int type, LPARAM /*p*/)
       
   389 {
       
   390     QString familyName = QString::fromWCharArray(f->elfLogFont.lfFaceName);
       
   391     QString script = QString::fromWCharArray(f->elfScript);
       
   392 
       
   393     FONTSIGNATURE signature = textmetric->ntmFontSig;
       
   394 
       
   395     // NEWTEXTMETRICEX is a NEWTEXTMETRIC, which according to the documentation is
       
   396     // identical to a TEXTMETRIC except for the last four members, which we don't use
       
   397     // anyway
       
   398     addFontToDatabase(familyName, script, (TEXTMETRIC *)textmetric, &signature, type);
       
   399     // keep on enumerating
       
   400     return 1;
       
   401 }
       
   402 
       
   403 static
       
   404 void populate_database(const QString& fam)
       
   405 {
       
   406     QFontDatabasePrivate *d = privateDb();
       
   407     if (!d)
       
   408         return;
       
   409 
       
   410     QtFontFamily *family = 0;
       
   411     if(!fam.isEmpty()) {
       
   412         family = d->family(fam);
       
   413         if(family && family->loaded)
       
   414             return;
       
   415     } else if (d->count) {
       
   416         return;
       
   417     }
       
   418 
       
   419     HDC dummy = GetDC(0);
       
   420 
       
   421     LOGFONT lf;
       
   422     lf.lfCharSet = DEFAULT_CHARSET;
       
   423     if (fam.isNull()) {
       
   424         lf.lfFaceName[0] = 0;
       
   425     } else {
       
   426         memcpy(lf.lfFaceName, fam.utf16(), sizeof(wchar_t) * qMin(fam.length() + 1, 32));  // 32 = Windows hard-coded
       
   427     }
       
   428     lf.lfPitchAndFamily = 0;
       
   429 
       
   430     EnumFontFamiliesEx(dummy, &lf,
       
   431         (FONTENUMPROC)storeFont, (LPARAM)privateDb(), 0);
       
   432 
       
   433     ReleaseDC(0, dummy);
       
   434 
       
   435     for (int i = 0; i < d->applicationFonts.count(); ++i) {
       
   436         QFontDatabasePrivate::ApplicationFont fnt = d->applicationFonts.at(i);
       
   437         if (!fnt.memoryFont)
       
   438             continue;
       
   439         for (int j = 0; j < fnt.families.count(); ++j) {
       
   440             const QString familyName = fnt.families.at(j);
       
   441             HDC hdc = GetDC(0);
       
   442             LOGFONT lf;
       
   443             memset(&lf, 0, sizeof(LOGFONT));
       
   444             memcpy(lf.lfFaceName, familyName.utf16(), sizeof(wchar_t) * qMin(LF_FACESIZE, familyName.size()));
       
   445             lf.lfCharSet = DEFAULT_CHARSET;
       
   446             HFONT hfont = CreateFontIndirect(&lf);
       
   447             HGDIOBJ oldobj = SelectObject(hdc, hfont);
       
   448 
       
   449             TEXTMETRIC textMetrics;
       
   450             GetTextMetrics(hdc, &textMetrics);
       
   451 
       
   452             addFontToDatabase(familyName, QString(),
       
   453                               &textMetrics,
       
   454                               &fnt.signatures.at(j),
       
   455                               TRUETYPE_FONTTYPE);
       
   456 
       
   457             SelectObject(hdc, oldobj);
       
   458             DeleteObject(hfont);
       
   459             ReleaseDC(0, hdc);
       
   460         }
       
   461     }
       
   462 
       
   463     if(!fam.isEmpty()) {
       
   464         family = d->family(fam);
       
   465         if(family) {
       
   466             if(!family->writingSystemCheck) {
       
   467             }
       
   468             family->loaded = true;
       
   469         }
       
   470     }
       
   471 }
       
   472 
       
   473 static void initializeDb()
       
   474 {
       
   475     QFontDatabasePrivate *db = privateDb();
       
   476     if (!db || db->count)
       
   477         return;
       
   478 
       
   479     populate_database(QString());
       
   480 
       
   481 #ifdef QFONTDATABASE_DEBUG
       
   482     // print the database
       
   483     for (int f = 0; f < db->count; f++) {
       
   484         QtFontFamily *family = db->families[f];
       
   485         qDebug("    %s: %p", qPrintable(family->name), family);
       
   486         populate_database(family->name);
       
   487 
       
   488 #if 0
       
   489         qDebug("        scripts supported:");
       
   490         for (int i = 0; i < QUnicodeTables::ScriptCount; i++)
       
   491             if(family->writingSystems[i] & QtFontFamily::Supported)
       
   492                 qDebug("            %d", i);
       
   493         for (int fd = 0; fd < family->count; fd++) {
       
   494             QtFontFoundry *foundry = family->foundries[fd];
       
   495             qDebug("        %s", foundry->name.latin1());
       
   496             for (int s = 0; s < foundry->count; s++) {
       
   497                 QtFontStyle *style = foundry->styles[s];
       
   498                 qDebug("            style: style=%d weight=%d smooth=%d",  style->key.style,
       
   499                        style->key.weight, style->smoothScalable );
       
   500                 if(!style->smoothScalable) {
       
   501                     for(int i = 0; i < style->count; ++i) {
       
   502                         qDebug("                %d", style->pixelSizes[i].pixelSize);
       
   503                     }
       
   504                 }
       
   505             }
       
   506         }
       
   507 #endif
       
   508     }
       
   509 #endif // QFONTDATABASE_DEBUG
       
   510 
       
   511 }
       
   512 
       
   513 static inline void load(const QString &family = QString(), int = -1)
       
   514 {
       
   515     populate_database(family);
       
   516 }
       
   517 
       
   518 
       
   519 
       
   520 
       
   521 
       
   522 // --------------------------------------------------------------------------------------
       
   523 // font loader
       
   524 // --------------------------------------------------------------------------------------
       
   525 
       
   526 
       
   527 
       
   528 static void initFontInfo(QFontEngineWin *fe, const QFontDef &request, const QFontPrivate *fp)
       
   529 {
       
   530     fe->fontDef = request;                                // most settings are equal
       
   531 
       
   532     HDC dc = ((request.styleStrategy & QFont::PreferDevice) && fp->hdc) ? fp->hdc : shared_dc();
       
   533     SelectObject(dc, fe->hfont);
       
   534     wchar_t n[64];
       
   535     GetTextFace(dc, 64, n);
       
   536     fe->fontDef.family = QString::fromWCharArray(n);
       
   537     fe->fontDef.fixedPitch = !(fe->tm.tmPitchAndFamily & TMPF_FIXED_PITCH);
       
   538     if (fe->fontDef.pointSize < 0) {
       
   539         fe->fontDef.pointSize = fe->fontDef.pixelSize * 72. / fp->dpi;
       
   540     } else if (fe->fontDef.pixelSize == -1) {
       
   541         fe->fontDef.pixelSize = qRound(fe->fontDef.pointSize * fp->dpi / 72.);
       
   542     }
       
   543 }
       
   544 
       
   545 
       
   546 static const char *other_tryFonts[] = {
       
   547     "Arial",
       
   548     "MS UI Gothic",
       
   549     "Gulim",
       
   550     "SimSun",
       
   551     "PMingLiU",
       
   552     "Arial Unicode MS",
       
   553     0
       
   554 };
       
   555 
       
   556 static const char *jp_tryFonts [] = {
       
   557     "MS UI Gothic",
       
   558     "Arial",
       
   559     "Gulim",
       
   560     "SimSun",
       
   561     "PMingLiU",
       
   562     "Arial Unicode MS",
       
   563     0
       
   564 };
       
   565 
       
   566 static const char *ch_CN_tryFonts [] = {
       
   567     "SimSun",
       
   568     "Arial",
       
   569     "PMingLiU",
       
   570     "Gulim",
       
   571     "MS UI Gothic",
       
   572     "Arial Unicode MS",
       
   573     0
       
   574 };
       
   575 
       
   576 static const char *ch_TW_tryFonts [] = {
       
   577     "PMingLiU",
       
   578     "Arial",
       
   579     "SimSun",
       
   580     "Gulim",
       
   581     "MS UI Gothic",
       
   582     "Arial Unicode MS",
       
   583     0
       
   584 };
       
   585 
       
   586 static const char *kr_tryFonts[] = {
       
   587     "Gulim",
       
   588     "Arial",
       
   589     "PMingLiU",
       
   590     "SimSun",
       
   591     "MS UI Gothic",
       
   592     "Arial Unicode MS",
       
   593     0
       
   594 };
       
   595 
       
   596 static const char **tryFonts = 0;
       
   597 
       
   598 
       
   599 static inline HFONT systemFont()
       
   600 {
       
   601     if (stock_sysfont == 0)
       
   602         stock_sysfont = (HFONT)GetStockObject(SYSTEM_FONT);
       
   603     return stock_sysfont;
       
   604 }
       
   605 
       
   606 #if !defined(DEFAULT_GUI_FONT)
       
   607 #define DEFAULT_GUI_FONT 17
       
   608 #endif
       
   609 
       
   610 static
       
   611 QFontEngine *loadEngine(int script, const QFontPrivate *fp, const QFontDef &request, const QtFontDesc *desc,
       
   612                         const QStringList &family_list)
       
   613 {
       
   614     LOGFONT lf;
       
   615     memset(&lf, 0, sizeof(LOGFONT));
       
   616 
       
   617     bool useDevice = (request.styleStrategy & QFont::PreferDevice) && fp->hdc;
       
   618 
       
   619     HDC hdc = shared_dc();
       
   620     QString font_name = desc->family->name;
       
   621 
       
   622     if (useDevice) {
       
   623         hdc = fp->hdc;
       
   624         font_name = request.family;
       
   625     }
       
   626 
       
   627     bool stockFont = false;
       
   628     bool preferClearTypeAA = false;
       
   629 
       
   630     HFONT hfont = 0;
       
   631 
       
   632     if (fp->rawMode) {                        // will choose a stock font
       
   633         int f, deffnt = SYSTEM_FONT;
       
   634         QString fam = desc->family->name.toLower();
       
   635         if (fam == QLatin1String("default"))
       
   636             f = deffnt;
       
   637         else if (fam == QLatin1String("system"))
       
   638             f = SYSTEM_FONT;
       
   639 #ifndef Q_WS_WINCE
       
   640         else if (fam == QLatin1String("system_fixed"))
       
   641             f = SYSTEM_FIXED_FONT;
       
   642         else if (fam == QLatin1String("ansi_fixed"))
       
   643             f = ANSI_FIXED_FONT;
       
   644         else if (fam == QLatin1String("ansi_var"))
       
   645             f = ANSI_VAR_FONT;
       
   646         else if (fam == QLatin1String("device_default"))
       
   647             f = DEVICE_DEFAULT_FONT;
       
   648         else if (fam == QLatin1String("oem_fixed"))
       
   649             f = OEM_FIXED_FONT;
       
   650 #endif
       
   651         else if (fam[0] == QLatin1Char('#'))
       
   652             f = fam.right(fam.length()-1).toInt();
       
   653         else
       
   654             f = deffnt;
       
   655         hfont = (HFONT)GetStockObject(f);
       
   656         if (!hfont) {
       
   657             qErrnoWarning("QFontEngine::loadEngine: GetStockObject failed");
       
   658             hfont = systemFont();
       
   659         }
       
   660         stockFont = true;
       
   661     } else {
       
   662 
       
   663         int hint = FF_DONTCARE;
       
   664         switch (request.styleHint) {
       
   665             case QFont::Helvetica:
       
   666                 hint = FF_SWISS;
       
   667                 break;
       
   668             case QFont::Times:
       
   669                 hint = FF_ROMAN;
       
   670                 break;
       
   671             case QFont::Courier:
       
   672                 hint = FF_MODERN;
       
   673                 break;
       
   674             case QFont::OldEnglish:
       
   675                 hint = FF_DECORATIVE;
       
   676                 break;
       
   677             case QFont::System:
       
   678                 hint = FF_MODERN;
       
   679                 break;
       
   680             default:
       
   681                 break;
       
   682         }
       
   683 
       
   684         lf.lfHeight = -qRound(request.pixelSize);
       
   685         lf.lfWidth                = 0;
       
   686         lf.lfEscapement        = 0;
       
   687         lf.lfOrientation        = 0;
       
   688         if (desc->style->key.weight == 50)
       
   689             lf.lfWeight = FW_DONTCARE;
       
   690         else
       
   691             lf.lfWeight = (desc->style->key.weight*900)/99;
       
   692         lf.lfItalic                = (desc->style->key.style != QFont::StyleNormal);
       
   693         lf.lfCharSet        = DEFAULT_CHARSET;
       
   694 
       
   695         int strat = OUT_DEFAULT_PRECIS;
       
   696         if (request.styleStrategy & QFont::PreferBitmap) {
       
   697             strat = OUT_RASTER_PRECIS;
       
   698 #ifndef Q_WS_WINCE
       
   699         } else if (request.styleStrategy & QFont::PreferDevice) {
       
   700             strat = OUT_DEVICE_PRECIS;
       
   701         } else if (request.styleStrategy & QFont::PreferOutline) {
       
   702             strat = OUT_OUTLINE_PRECIS;
       
   703         } else if (request.styleStrategy & QFont::ForceOutline) {
       
   704             strat = OUT_TT_ONLY_PRECIS;
       
   705 #endif
       
   706         }
       
   707 
       
   708         lf.lfOutPrecision   = strat;
       
   709 
       
   710         int qual = DEFAULT_QUALITY;
       
   711 
       
   712         if (request.styleStrategy & QFont::PreferMatch)
       
   713             qual = DRAFT_QUALITY;
       
   714 #ifndef Q_WS_WINCE
       
   715         else if (request.styleStrategy & QFont::PreferQuality)
       
   716             qual = PROOF_QUALITY;
       
   717 #endif
       
   718 
       
   719         if (request.styleStrategy & QFont::PreferAntialias) {
       
   720             if (QSysInfo::WindowsVersion >= QSysInfo::WV_XP) {
       
   721                 qual = CLEARTYPE_QUALITY;
       
   722                 preferClearTypeAA = true;
       
   723             } else {
       
   724                 qual = ANTIALIASED_QUALITY;
       
   725             }
       
   726         } else if (request.styleStrategy & QFont::NoAntialias) {
       
   727             qual = NONANTIALIASED_QUALITY;
       
   728         }
       
   729 
       
   730         lf.lfQuality        = qual;
       
   731 
       
   732         lf.lfClipPrecision  = CLIP_DEFAULT_PRECIS;
       
   733         lf.lfPitchAndFamily = DEFAULT_PITCH | hint;
       
   734 
       
   735         QString fam = font_name;
       
   736 
       
   737         if(fam.isEmpty())
       
   738             fam = QLatin1String("MS Sans Serif");
       
   739 
       
   740         if ((fam == QLatin1String("MS Sans Serif"))
       
   741             && (request.style == QFont::StyleItalic || (-lf.lfHeight > 18 && -lf.lfHeight != 24))) {
       
   742             fam = QLatin1String("Arial"); // MS Sans Serif has bearing problems in italic, and does not scale
       
   743         }
       
   744         if (fam == QLatin1String("Courier") && !(request.styleStrategy & QFont::PreferBitmap))
       
   745             fam = QLatin1String("Courier New");
       
   746 
       
   747         memcpy(lf.lfFaceName, fam.utf16(), sizeof(wchar_t) * qMin(fam.length() + 1, 32));  // 32 = Windows hard-coded
       
   748         hfont = CreateFontIndirect(&lf);
       
   749         if (!hfont)
       
   750             qErrnoWarning("QFontEngine::loadEngine: CreateFontIndirect failed");
       
   751 
       
   752         stockFont = (hfont == 0);
       
   753         bool ttf = false;
       
   754         int avWidth = 0;
       
   755         BOOL res;
       
   756         HGDIOBJ oldObj = SelectObject(hdc, hfont);
       
   757 
       
   758         TEXTMETRIC tm;
       
   759         res = GetTextMetrics(hdc, &tm);
       
   760         avWidth = tm.tmAveCharWidth;
       
   761         ttf = tm.tmPitchAndFamily & TMPF_TRUETYPE;
       
   762 
       
   763         SelectObject(hdc, oldObj);
       
   764 
       
   765         if (hfont && (!ttf || request.stretch != 100)) {
       
   766             DeleteObject(hfont);
       
   767             if (!res)
       
   768                 qErrnoWarning("QFontEngine::loadEngine: GetTextMetrics failed");
       
   769             lf.lfWidth = avWidth * request.stretch/100;
       
   770             hfont = CreateFontIndirect(&lf);
       
   771             if (!hfont)
       
   772                 qErrnoWarning("QFontEngine::loadEngine: CreateFontIndirect with stretch failed");
       
   773         }
       
   774 
       
   775 #ifndef Q_WS_WINCE
       
   776         if (hfont == 0) {
       
   777             hfont = (HFONT)GetStockObject(ANSI_VAR_FONT);
       
   778             stockFont = true;
       
   779         }
       
   780 #else
       
   781         if (hfont == 0) {
       
   782             hfont = (HFONT)GetStockObject(SYSTEM_FONT);
       
   783             stockFont = true;
       
   784         }
       
   785 #endif
       
   786 
       
   787     }
       
   788     QFontEngineWin *few = new QFontEngineWin(font_name, hfont, stockFont, lf);
       
   789 
       
   790     if (preferClearTypeAA)
       
   791         few->glyphFormat = QFontEngineGlyphCache::Raster_RGBMask;
       
   792 
       
   793     // Also check for OpenType tables when using complex scripts
       
   794     // ### TODO: This only works for scripts that require OpenType. More generally
       
   795     // for scripts that do not require OpenType we should just look at the list of
       
   796     // supported writing systems in the font's OS/2 table.
       
   797     if (scriptRequiresOpenType(script)) {
       
   798         HB_Face hbFace = few->harfbuzzFace();
       
   799         if (!hbFace || !hbFace->supported_scripts[script]) {
       
   800             FM_DEBUG("  OpenType support missing for script\n");
       
   801             delete few;
       
   802             return 0;
       
   803         }
       
   804     }
       
   805 
       
   806     QFontEngine *fe = few;
       
   807     initFontInfo(few, request, fp);
       
   808     if(script == QUnicodeTables::Common
       
   809        && !(request.styleStrategy & QFont::NoFontMerging)
       
   810        && !(desc->family->writingSystems[QFontDatabase::Symbol] & QtFontFamily::Supported)) {
       
   811         if(!tryFonts) {
       
   812             LANGID lid = GetUserDefaultLangID();
       
   813             switch( lid&0xff ) {
       
   814             case LANG_CHINESE: // Chinese (Taiwan)
       
   815                 if ( lid == 0x0804 ) // Taiwan
       
   816                     tryFonts = ch_TW_tryFonts;
       
   817                 else
       
   818                     tryFonts = ch_CN_tryFonts;
       
   819                 break;
       
   820             case LANG_JAPANESE:
       
   821                 tryFonts = jp_tryFonts;
       
   822                 break;
       
   823             case LANG_KOREAN:
       
   824                 tryFonts = kr_tryFonts;
       
   825                 break;
       
   826             default:
       
   827                 tryFonts = other_tryFonts;
       
   828                 break;
       
   829             }
       
   830         }
       
   831         QStringList fm = QFontDatabase().families();
       
   832         QStringList list = family_list;
       
   833         const char **tf = tryFonts;
       
   834         while(tf && *tf) {
       
   835             if(fm.contains(QLatin1String(*tf)))
       
   836                 list << QLatin1String(*tf);
       
   837             ++tf;
       
   838         }
       
   839         QFontEngine *mfe = new QFontEngineMultiWin(few, list);
       
   840         mfe->fontDef = fe->fontDef;
       
   841         fe = mfe;
       
   842     }
       
   843     return fe;
       
   844 }
       
   845 
       
   846 const char *styleHint(const QFontDef &request)
       
   847 {
       
   848     const char *stylehint = 0;
       
   849     switch (request.styleHint) {
       
   850     case QFont::SansSerif:
       
   851         stylehint = "Arial";
       
   852         break;
       
   853     case QFont::Serif:
       
   854         stylehint = "Times New Roman";
       
   855         break;
       
   856     case QFont::TypeWriter:
       
   857         stylehint = "Courier New";
       
   858         break;
       
   859     default:
       
   860         if (request.fixedPitch)
       
   861             stylehint = "Courier New";
       
   862         break;
       
   863     }
       
   864     return stylehint;
       
   865 }
       
   866 
       
   867 static QFontEngine *loadWin(const QFontPrivate *d, int script, const QFontDef &req)
       
   868 {
       
   869     // list of families to try
       
   870     QStringList family_list = familyList(req);
       
   871 
       
   872     const char *stylehint = styleHint(d->request);
       
   873     if (stylehint)
       
   874         family_list << QLatin1String(stylehint);
       
   875 
       
   876     // append the default fallback font for the specified script
       
   877     // family_list << ... ; ###########
       
   878 
       
   879     // add the default family
       
   880     QString defaultFamily = QApplication::font().family();
       
   881     if (! family_list.contains(defaultFamily))
       
   882         family_list << defaultFamily;
       
   883 
       
   884     // add QFont::defaultFamily() to the list, for compatibility with
       
   885     // previous versions
       
   886     family_list << QApplication::font().defaultFamily();
       
   887 
       
   888     // null family means find the first font matching the specified script
       
   889     family_list << QString();
       
   890 
       
   891     QtFontDesc desc;
       
   892     QFontEngine *fe = 0;
       
   893     QList<int> blacklistedFamilies;
       
   894 
       
   895     while (!fe) {
       
   896         for (int i = 0; i < family_list.size(); ++i) {
       
   897             QString family, foundry;
       
   898             parseFontName(family_list.at(i), foundry, family);
       
   899             FM_DEBUG("loadWin: >>>>>>>>>>>>>>trying to match '%s'", family.toLatin1().data());
       
   900             QT_PREPEND_NAMESPACE(match)(script, req, family, foundry, -1, &desc, blacklistedFamilies);
       
   901             if (desc.family)
       
   902                 break;
       
   903         }
       
   904         if (!desc.family)
       
   905             break;
       
   906         fe = loadEngine(script, d, req, &desc, family_list);
       
   907         if (!fe)
       
   908             blacklistedFamilies.append(desc.familyIndex);
       
   909     }
       
   910     return fe;
       
   911 }
       
   912 
       
   913 void QFontDatabase::load(const QFontPrivate *d, int script)
       
   914 {
       
   915     // sanity checks
       
   916     if (!qApp)
       
   917         qWarning("QFontDatabase::load: Must construct QApplication first");
       
   918     Q_ASSERT(script >= 0 && script < QUnicodeTables::ScriptCount);
       
   919 
       
   920     // normalize the request to get better caching
       
   921     QFontDef req = d->request;
       
   922     if (req.pixelSize <= 0)
       
   923         req.pixelSize = qreal((req.pointSize * d->dpi) / 72.);
       
   924     if (req.pixelSize < 1)
       
   925         req.pixelSize = 1;
       
   926     if (req.weight == 0)
       
   927         req.weight = QFont::Normal;
       
   928     if (req.stretch == 0)
       
   929         req.stretch = 100;
       
   930 
       
   931     QFontCache::Key key(req, d->rawMode ? QUnicodeTables::Common : script, d->screen);
       
   932     if (!d->engineData)
       
   933         getEngineData(d, key);
       
   934 
       
   935     // the cached engineData could have already loaded the engine we want
       
   936     if (d->engineData->engines[script])
       
   937         return;
       
   938 
       
   939     QFontEngine *fe = QFontCache::instance()->findEngine(key);
       
   940 
       
   941     // set it to the actual pointsize, so QFontInfo will do the right thing
       
   942     if (req.pointSize < 0)
       
   943         req.pointSize = req.pixelSize*72./d->dpi;
       
   944 
       
   945     if (!fe) {
       
   946         if (qt_enable_test_font && req.family == QLatin1String("__Qt__Box__Engine__")) {
       
   947             fe = new QTestFontEngine(req.pixelSize);
       
   948             fe->fontDef = req;
       
   949         } else {
       
   950             QMutexLocker locker(fontDatabaseMutex());
       
   951             if (!privateDb()->count)
       
   952                 initializeDb();
       
   953             fe = loadWin(d, script, req);
       
   954         }
       
   955         if (!fe) {
       
   956             fe = new QFontEngineBox(req.pixelSize);
       
   957             fe->fontDef = QFontDef();
       
   958         }
       
   959     }
       
   960     d->engineData->engines[script] = fe;
       
   961     fe->ref.ref();
       
   962     QFontCache::instance()->insertEngine(key, fe);
       
   963 }
       
   964 
       
   965 #if !defined(FR_PRIVATE)
       
   966 #define FR_PRIVATE 0x10
       
   967 #endif
       
   968 
       
   969 typedef int (WINAPI *PtrAddFontResourceExW)(LPCWSTR, DWORD, PVOID);
       
   970 typedef HANDLE (WINAPI *PtrAddFontMemResourceEx)(PVOID, DWORD, PVOID, DWORD *);
       
   971 typedef BOOL (WINAPI *PtrRemoveFontResourceExW)(LPCWSTR, DWORD, PVOID);
       
   972 typedef BOOL (WINAPI *PtrRemoveFontMemResourceEx)(HANDLE);
       
   973 
       
   974 static QList<quint32> getTrueTypeFontOffsets(const uchar *fontData)
       
   975 {
       
   976     QList<quint32> offsets;
       
   977     const quint32 headerTag = *reinterpret_cast<const quint32 *>(fontData);
       
   978     if (headerTag != MAKE_TAG('t', 't', 'c', 'f')) {
       
   979         if (headerTag != MAKE_TAG(0, 1, 0, 0)
       
   980             && headerTag != MAKE_TAG('O', 'T', 'T', 'O')
       
   981             && headerTag != MAKE_TAG('t', 'r', 'u', 'e')
       
   982             && headerTag != MAKE_TAG('t', 'y', 'p', '1'))
       
   983             return offsets;
       
   984         offsets << 0;
       
   985         return offsets;
       
   986     }
       
   987     const quint32 numFonts = qFromBigEndian<quint32>(fontData + 8);
       
   988     for (uint i = 0; i < numFonts; ++i) {
       
   989         offsets << qFromBigEndian<quint32>(fontData + 12 + i * 4);
       
   990     }
       
   991     return offsets;
       
   992 }
       
   993 
       
   994 static void getFontTable(const uchar *fileBegin, const uchar *data, quint32 tag, const uchar **table, quint32 *length)
       
   995 {
       
   996     const quint16 numTables = qFromBigEndian<quint16>(data + 4);
       
   997     for (uint i = 0; i < numTables; ++i) {
       
   998         const quint32 offset = 12 + 16 * i;
       
   999         if (*reinterpret_cast<const quint32 *>(data + offset) == tag) {
       
  1000             *table = fileBegin + qFromBigEndian<quint32>(data + offset + 8);
       
  1001             *length = qFromBigEndian<quint32>(data + offset + 12);
       
  1002             return;
       
  1003         }
       
  1004     }
       
  1005     *table = 0;
       
  1006     *length = 0;
       
  1007     return;
       
  1008 }
       
  1009 
       
  1010 static void getFamiliesAndSignatures(const QByteArray &fontData, QFontDatabasePrivate::ApplicationFont *appFont)
       
  1011 {
       
  1012     const uchar *data = reinterpret_cast<const uchar *>(fontData.constData());
       
  1013 
       
  1014     QList<quint32> offsets = getTrueTypeFontOffsets(data);
       
  1015     if (offsets.isEmpty())
       
  1016         return;
       
  1017 
       
  1018     for (int i = 0; i < offsets.count(); ++i) {
       
  1019         const uchar *font = data + offsets.at(i);
       
  1020         const uchar *table;
       
  1021         quint32 length;
       
  1022         getFontTable(data, font, MAKE_TAG('n', 'a', 'm', 'e'), &table, &length);
       
  1023         if (!table)
       
  1024             continue;
       
  1025         QString name = getEnglishName(table, length);
       
  1026         if (name.isEmpty())
       
  1027             continue;
       
  1028 
       
  1029         appFont->families << name;
       
  1030         FONTSIGNATURE signature;
       
  1031         getFontTable(data, font, MAKE_TAG('O', 'S', '/', '2'), &table, &length);
       
  1032         if (table && length >= 86) {
       
  1033             // See also qfontdatabase_mac.cpp, offsets taken from OS/2 table in the TrueType spec
       
  1034             signature.fsUsb[0] = qFromBigEndian<quint32>(table + 42);
       
  1035             signature.fsUsb[1] = qFromBigEndian<quint32>(table + 46);
       
  1036             signature.fsUsb[2] = qFromBigEndian<quint32>(table + 50);
       
  1037             signature.fsUsb[3] = qFromBigEndian<quint32>(table + 54);
       
  1038 
       
  1039             signature.fsCsb[0] = qFromBigEndian<quint32>(table + 78);
       
  1040             signature.fsCsb[1] = qFromBigEndian<quint32>(table + 82);
       
  1041         } else {
       
  1042             memset(&signature, 0, sizeof(signature));
       
  1043         }
       
  1044         appFont->signatures << signature;
       
  1045     }
       
  1046 }
       
  1047 
       
  1048 static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
       
  1049 {
       
  1050     if(!fnt->data.isEmpty()) {
       
  1051 #ifndef Q_OS_WINCE
       
  1052         PtrAddFontMemResourceEx ptrAddFontMemResourceEx = (PtrAddFontMemResourceEx)QLibrary::resolve(QLatin1String("gdi32"),
       
  1053                                                                                                      "AddFontMemResourceEx");
       
  1054         if (!ptrAddFontMemResourceEx)
       
  1055             return;
       
  1056 #endif
       
  1057         getFamiliesAndSignatures(fnt->data, fnt);
       
  1058         if (fnt->families.isEmpty())
       
  1059             return;
       
  1060 
       
  1061 #ifdef Q_OS_WINCE
       
  1062         HANDLE handle = 0;
       
  1063 
       
  1064         {
       
  1065 #ifdef QT_NO_TEMPORARYFILE
       
  1066            wchar_t lpBuffer[MAX_PATH];
       
  1067            GetTempPath(MAX_PATH, lpBuffer);
       
  1068            QString s = QString::fromWCharArray(lpBuffer);
       
  1069            QFile tempfile(s + QLatin1String("/font") + QString::number(GetTickCount()) + QLatin1String(".ttf"));
       
  1070            if (!tempfile.open(QIODevice::ReadWrite))
       
  1071 #else
       
  1072             QTemporaryFile tempfile(QLatin1String("XXXXXXXX.ttf"));
       
  1073             if (!tempfile.open())
       
  1074 #endif // QT_NO_TEMPORARYFILE
       
  1075                 return;
       
  1076             if (tempfile.write(fnt->data) == -1)
       
  1077                 return;
       
  1078 
       
  1079 #ifndef QT_NO_TEMPORARYFILE
       
  1080             tempfile.setAutoRemove(false);
       
  1081 #endif
       
  1082             fnt->fileName = QFileInfo(tempfile.fileName()).absoluteFilePath();
       
  1083         }
       
  1084 
       
  1085         if (AddFontResource((LPCWSTR)fnt->fileName.utf16()) == 0) {
       
  1086             QFile(fnt->fileName).remove();
       
  1087             return;
       
  1088         }
       
  1089 #else
       
  1090         DWORD dummy = 0;
       
  1091         HANDLE handle = ptrAddFontMemResourceEx((void *)fnt->data.constData(), fnt->data.size(), 0,
       
  1092                                                 &dummy);
       
  1093         if (handle == 0)
       
  1094             return;
       
  1095 #endif // Q_OS_WINCE
       
  1096 
       
  1097         fnt->handle = handle;
       
  1098         fnt->data = QByteArray();
       
  1099         fnt->memoryFont = true;
       
  1100     } else {
       
  1101         QFile f(fnt->fileName);
       
  1102         if (!f.open(QIODevice::ReadOnly))
       
  1103             return;
       
  1104         QByteArray data = f.readAll();
       
  1105         f.close();
       
  1106         getFamiliesAndSignatures(data, fnt);
       
  1107 
       
  1108 #ifdef Q_OS_WINCE
       
  1109         QFileInfo fileinfo(fnt->fileName);
       
  1110         fnt->fileName = fileinfo.absoluteFilePath();
       
  1111         if (AddFontResource((LPCWSTR)fnt->fileName.utf16()) == 0)
       
  1112             return;
       
  1113 #else
       
  1114         // supported from 2000 on, so no need to deal with the *A variant
       
  1115         PtrAddFontResourceExW ptrAddFontResourceExW = (PtrAddFontResourceExW)QLibrary::resolve(QLatin1String("gdi32"),
       
  1116                                                                                                "AddFontResourceExW");
       
  1117         if (!ptrAddFontResourceExW
       
  1118             || ptrAddFontResourceExW((wchar_t*)fnt->fileName.utf16(), FR_PRIVATE, 0) == 0)
       
  1119             return;
       
  1120 #endif // Q_OS_WINCE
       
  1121 
       
  1122         fnt->memoryFont = false;
       
  1123     }
       
  1124 }
       
  1125 
       
  1126 bool QFontDatabase::removeApplicationFont(int handle)
       
  1127 {
       
  1128     QMutexLocker locker(fontDatabaseMutex());
       
  1129 
       
  1130     QFontDatabasePrivate *db = privateDb();
       
  1131     if (handle < 0 || handle >= db->applicationFonts.count())
       
  1132         return false;
       
  1133 
       
  1134     const QFontDatabasePrivate::ApplicationFont font = db->applicationFonts.at(handle);
       
  1135     db->applicationFonts[handle] = QFontDatabasePrivate::ApplicationFont();
       
  1136     if (font.memoryFont) {
       
  1137 #ifdef Q_OS_WINCE
       
  1138         bool removeSucceeded = RemoveFontResource((LPCWSTR)font.fileName.utf16());
       
  1139         QFile tempfile(font.fileName);
       
  1140         tempfile.remove();
       
  1141         if (!removeSucceeded)
       
  1142             return false;
       
  1143 #else
       
  1144         PtrRemoveFontMemResourceEx ptrRemoveFontMemResourceEx = (PtrRemoveFontMemResourceEx)QLibrary::resolve(QLatin1String("gdi32"),
       
  1145                                                                                                               "RemoveFontMemResourceEx");
       
  1146         if (!ptrRemoveFontMemResourceEx
       
  1147             || !ptrRemoveFontMemResourceEx(font.handle))
       
  1148             return false;
       
  1149 #endif // Q_OS_WINCE
       
  1150     } else {
       
  1151 #ifdef Q_OS_WINCE
       
  1152         if (!RemoveFontResource((LPCWSTR)font.fileName.utf16()))
       
  1153             return false;
       
  1154 #else
       
  1155         PtrRemoveFontResourceExW ptrRemoveFontResourceExW = (PtrRemoveFontResourceExW)QLibrary::resolve(QLatin1String("gdi32"),
       
  1156                                                                                                         "RemoveFontResourceExW");
       
  1157         if (!ptrRemoveFontResourceExW
       
  1158             || !ptrRemoveFontResourceExW((LPCWSTR)font.fileName.utf16(), FR_PRIVATE, 0))
       
  1159             return false;
       
  1160 #endif // Q_OS_WINCE
       
  1161     }
       
  1162 
       
  1163     db->invalidate();
       
  1164     return true;
       
  1165 }
       
  1166 
       
  1167 bool QFontDatabase::removeAllApplicationFonts()
       
  1168 {
       
  1169     QMutexLocker locker(fontDatabaseMutex());
       
  1170 
       
  1171     QFontDatabasePrivate *db = privateDb();
       
  1172     for (int i = 0; i < db->applicationFonts.count(); ++i)
       
  1173         if (!removeApplicationFont(i))
       
  1174             return false;
       
  1175     return true;
       
  1176 }
       
  1177 
       
  1178 bool QFontDatabase::supportsThreadedFontRendering()
       
  1179 {
       
  1180     return true;
       
  1181 }
       
  1182 
       
  1183 QT_END_NAMESPACE