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