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