Fix font printing on Windows using the native engine.
[profile/ivi/qtbase.git] / src / plugins / platforms / windows / qwindowsfontdatabase.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qwindowsfontdatabase.h"
43 #include "qwindowsfontdatabase_ft.h" // for default font
44 #include "qwindowscontext.h"
45 #include "qwindowsfontengine.h"
46 #include "qwindowsfontenginedirectwrite.h"
47 #include "qtwindows_additional.h"
48
49 #include <QtGui/QFont>
50 #include <QtGui/QGuiApplication>
51
52 #include <QtCore/qmath.h>
53 #include <QtCore/QDebug>
54 #include <QtCore/QtEndian>
55
56 #include <wchar.h>
57
58 #ifdef Q_OS_WINCE
59 #  include "qplatformfunctions_wince.h"
60 #endif
61
62 #if !defined(QT_NO_DIRECTWRITE)
63 #  include <dwrite.h>
64 #  include <d2d1.h>
65 #endif
66
67 QT_BEGIN_NAMESPACE
68
69 // Helper classes for creating font engines directly from font data
70 namespace {
71
72 #   pragma pack(1)
73
74     // Common structure for all formats of the "name" table
75     struct NameTable
76     {
77         quint16 format;
78         quint16 count;
79         quint16 stringOffset;
80     };
81
82     struct NameRecord
83     {
84         quint16 platformID;
85         quint16 encodingID;
86         quint16 languageID;
87         quint16 nameID;
88         quint16 length;
89         quint16 offset;
90     };
91
92     struct OffsetSubTable
93     {
94         quint32 scalerType;
95         quint16 numTables;
96         quint16 searchRange;
97         quint16 entrySelector;
98         quint16 rangeShift;
99     };
100
101     struct TableDirectory
102     {
103         quint32 identifier;
104         quint32 checkSum;
105         quint32 offset;
106         quint32 length;
107     };
108
109     struct OS2Table
110     {
111         quint16 version;
112         qint16  avgCharWidth;
113         quint16 weightClass;
114         quint16 widthClass;
115         quint16 type;
116         qint16  subscriptXSize;
117         qint16  subscriptYSize;
118         qint16  subscriptXOffset;
119         qint16  subscriptYOffset;
120         qint16  superscriptXSize;
121         qint16  superscriptYSize;
122         qint16  superscriptXOffset;
123         qint16  superscriptYOffset;
124         qint16  strikeOutSize;
125         qint16  strikeOutPosition;
126         qint16  familyClass;
127         quint8  panose[10];
128         quint32 unicodeRanges[4];
129         quint8  vendorID[4];
130         quint16 selection;
131         quint16 firstCharIndex;
132         quint16 lastCharIndex;
133         qint16  typoAscender;
134         qint16  typoDescender;
135         qint16  typoLineGap;
136         quint16 winAscent;
137         quint16 winDescent;
138         quint32 codepageRanges[2];
139         qint16  height;
140         qint16  capHeight;
141         quint16 defaultChar;
142         quint16 breakChar;
143         quint16 maxContext;
144     };
145
146 #   pragma pack()
147
148     class EmbeddedFont
149     {
150     public:
151         EmbeddedFont(const QByteArray &fontData) : m_fontData(fontData) {}
152
153         QString changeFamilyName(const QString &newFamilyName);
154         QByteArray data() const { return m_fontData; }
155         TableDirectory *tableDirectoryEntry(const QByteArray &tagName);
156         QString familyName(TableDirectory *nameTableDirectory = 0);
157
158     private:
159         QByteArray m_fontData;
160     };
161
162     TableDirectory *EmbeddedFont::tableDirectoryEntry(const QByteArray &tagName)
163     {
164         Q_ASSERT(tagName.size() == 4);
165         quint32 tagId = *(reinterpret_cast<const quint32 *>(tagName.constData()));
166
167         OffsetSubTable *offsetSubTable = reinterpret_cast<OffsetSubTable *>(m_fontData.data());
168         TableDirectory *tableDirectory = reinterpret_cast<TableDirectory *>(offsetSubTable + 1);
169
170         TableDirectory *nameTableDirectoryEntry = 0;
171         for (int i = 0; i < qFromBigEndian<quint16>(offsetSubTable->numTables); ++i, ++tableDirectory) {
172             if (tableDirectory->identifier == tagId) {
173                 nameTableDirectoryEntry = tableDirectory;
174                 break;
175             }
176         }
177
178         return nameTableDirectoryEntry;
179     }
180
181     QString EmbeddedFont::familyName(TableDirectory *nameTableDirectoryEntry)
182     {
183         QString name;
184
185         if (nameTableDirectoryEntry == 0)
186             nameTableDirectoryEntry = tableDirectoryEntry("name");
187
188         if (nameTableDirectoryEntry != 0) {
189             NameTable *nameTable = reinterpret_cast<NameTable *>(
190                 m_fontData.data() + qFromBigEndian<quint32>(nameTableDirectoryEntry->offset));
191             NameRecord *nameRecord = reinterpret_cast<NameRecord *>(nameTable + 1);
192             for (int i = 0; i < qFromBigEndian<quint16>(nameTable->count); ++i, ++nameRecord) {
193                 if (qFromBigEndian<quint16>(nameRecord->nameID) == 1
194                  && qFromBigEndian<quint16>(nameRecord->platformID) == 3 // Windows
195                  && qFromBigEndian<quint16>(nameRecord->languageID) == 0x0409) { // US English
196                     const void *ptr = reinterpret_cast<const quint8 *>(nameTable)
197                                                         + qFromBigEndian<quint16>(nameTable->stringOffset)
198                                                         + qFromBigEndian<quint16>(nameRecord->offset);
199
200                     const quint16 *s = reinterpret_cast<const quint16 *>(ptr);
201                     const quint16 *e = s + qFromBigEndian<quint16>(nameRecord->length) / sizeof(quint16);
202                     while (s != e)
203                         name += QChar( qFromBigEndian<quint16>(*s++));
204                     break;
205                 }
206             }
207         }
208
209         return name;
210     }
211
212     QString EmbeddedFont::changeFamilyName(const QString &newFamilyName)
213     {
214         TableDirectory *nameTableDirectoryEntry = tableDirectoryEntry("name");
215         if (nameTableDirectoryEntry == 0)
216             return QString();
217
218         QString oldFamilyName = familyName(nameTableDirectoryEntry);
219
220         // Reserve size for name table header, five required name records and string
221         const int requiredRecordCount = 5;
222         quint16 nameIds[requiredRecordCount] = { 1, 2, 3, 4, 6 };
223
224         int sizeOfHeader = sizeof(NameTable) + sizeof(NameRecord) * requiredRecordCount;
225         int newFamilyNameSize = newFamilyName.size() * sizeof(quint16);
226
227         const QString regularString = QString::fromLatin1("Regular");
228         int regularStringSize = regularString.size() * sizeof(quint16);
229
230         // Align table size of table to 32 bits (pad with 0)
231         int fullSize = ((sizeOfHeader + newFamilyNameSize + regularStringSize) & ~3) + 4;
232
233         QByteArray newNameTable(fullSize, char(0));
234
235         {
236             NameTable *nameTable = reinterpret_cast<NameTable *>(newNameTable.data());
237             nameTable->count = qbswap<quint16>(requiredRecordCount);
238             nameTable->stringOffset = qbswap<quint16>(sizeOfHeader);
239
240             NameRecord *nameRecord = reinterpret_cast<NameRecord *>(nameTable + 1);
241             for (int i = 0; i < requiredRecordCount; ++i, nameRecord++) {
242                 nameRecord->nameID = qbswap<quint16>(nameIds[i]);
243                 nameRecord->encodingID = qbswap<quint16>(1);
244                 nameRecord->languageID = qbswap<quint16>(0x0409);
245                 nameRecord->platformID = qbswap<quint16>(3);
246                 nameRecord->length = qbswap<quint16>(newFamilyNameSize);
247
248                 // Special case for sub-family
249                 if (nameIds[i] == 4) {
250                     nameRecord->offset = qbswap<quint16>(newFamilyNameSize);
251                     nameRecord->length = qbswap<quint16>(regularStringSize);
252                 }
253             }
254
255             // nameRecord now points to string data
256             quint16 *stringStorage = reinterpret_cast<quint16 *>(nameRecord);
257             const quint16 *sourceString = newFamilyName.utf16();
258             for (int i = 0; i < newFamilyName.size(); ++i)
259                 stringStorage[i] = qbswap<quint16>(sourceString[i]);
260             stringStorage += newFamilyName.size();
261
262             sourceString = regularString.utf16();
263             for (int i = 0; i < regularString.size(); ++i)
264                 stringStorage[i] = qbswap<quint16>(sourceString[i]);
265         }
266
267         quint32 *p = reinterpret_cast<quint32 *>(newNameTable.data());
268         quint32 *tableEnd = reinterpret_cast<quint32 *>(newNameTable.data() + fullSize);
269
270         quint32 checkSum = 0;
271         while (p < tableEnd)
272             checkSum +=  qFromBigEndian<quint32>(*(p++));
273
274         nameTableDirectoryEntry->checkSum = qbswap<quint32>(checkSum);
275         nameTableDirectoryEntry->offset = qbswap<quint32>(m_fontData.size());
276         nameTableDirectoryEntry->length = qbswap<quint32>(fullSize);
277
278         m_fontData.append(newNameTable);
279
280         return oldFamilyName;
281     }
282
283 #if !defined(QT_NO_DIRECTWRITE)
284
285     class DirectWriteFontFileStream: public IDWriteFontFileStream
286     {
287     public:
288         DirectWriteFontFileStream(const QByteArray &fontData)
289             : m_fontData(fontData)
290             , m_referenceCount(0)
291         {
292         }
293
294         ~DirectWriteFontFileStream()
295         {
296         }
297
298         HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **object);
299         ULONG STDMETHODCALLTYPE AddRef();
300         ULONG STDMETHODCALLTYPE Release();
301
302         HRESULT STDMETHODCALLTYPE ReadFileFragment(const void **fragmentStart, UINT64 fileOffset,
303                                                    UINT64 fragmentSize, OUT void **fragmentContext);
304         void STDMETHODCALLTYPE ReleaseFileFragment(void *fragmentContext);
305         HRESULT STDMETHODCALLTYPE GetFileSize(OUT UINT64 *fileSize);
306         HRESULT STDMETHODCALLTYPE GetLastWriteTime(OUT UINT64 *lastWriteTime);
307
308     private:
309         QByteArray m_fontData;
310         ULONG m_referenceCount;
311     };
312
313     HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::QueryInterface(REFIID iid, void **object)
314     {
315         if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileStream)) {
316             *object = this;
317             AddRef();
318             return S_OK;
319         } else {
320             *object = NULL;
321             return E_NOINTERFACE;
322         }
323     }
324
325     ULONG STDMETHODCALLTYPE DirectWriteFontFileStream::AddRef()
326     {
327         return InterlockedIncrement(&m_referenceCount);
328     }
329
330     ULONG STDMETHODCALLTYPE DirectWriteFontFileStream::Release()
331     {
332         ULONG newCount = InterlockedDecrement(&m_referenceCount);
333         if (newCount == 0)
334             delete this;
335         return newCount;
336     }
337
338     HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::ReadFileFragment(
339         const void **fragmentStart,
340         UINT64 fileOffset,
341         UINT64 fragmentSize,
342         OUT void **fragmentContext)
343     {
344         *fragmentContext = NULL;
345         if (fragmentSize + fileOffset <= m_fontData.size()) {
346             *fragmentStart = m_fontData.data() + fileOffset;
347             return S_OK;
348         } else {
349             *fragmentStart = NULL;
350             return E_FAIL;
351         }
352     }
353
354     void STDMETHODCALLTYPE DirectWriteFontFileStream::ReleaseFileFragment(void *)
355     {
356     }
357
358     HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::GetFileSize(UINT64 *fileSize)
359     {
360         *fileSize = m_fontData.size();
361         return S_OK;
362     }
363
364     HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::GetLastWriteTime(UINT64 *lastWriteTime)
365     {
366         *lastWriteTime = 0;
367         return E_NOTIMPL;
368     }
369
370     class DirectWriteFontFileLoader: public IDWriteFontFileLoader
371     {
372     public:
373         DirectWriteFontFileLoader() : m_referenceCount(0) {}
374
375         ~DirectWriteFontFileLoader()
376         {
377         }
378
379         inline void addKey(const void *key, const QByteArray &fontData)
380         {
381             Q_ASSERT(!m_fontDatas.contains(key));
382             m_fontDatas.insert(key, fontData);
383         }
384
385         inline void removeKey(const void *key)
386         {
387             m_fontDatas.remove(key);
388         }
389
390         HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **object);
391         ULONG STDMETHODCALLTYPE AddRef();
392         ULONG STDMETHODCALLTYPE Release();
393
394         HRESULT STDMETHODCALLTYPE CreateStreamFromKey(void const *fontFileReferenceKey,
395                                                       UINT32 fontFileReferenceKeySize,
396                                                       OUT IDWriteFontFileStream **fontFileStream);
397
398     private:
399         ULONG m_referenceCount;
400         QHash<const void *, QByteArray> m_fontDatas;
401     };
402
403     HRESULT STDMETHODCALLTYPE DirectWriteFontFileLoader::QueryInterface(const IID &iid,
404                                                                         void **object)
405     {
406         if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) {
407             *object = this;
408             AddRef();
409             return S_OK;
410         } else {
411             *object = NULL;
412             return E_NOINTERFACE;
413         }
414     }
415
416     ULONG STDMETHODCALLTYPE DirectWriteFontFileLoader::AddRef()
417     {
418         return InterlockedIncrement(&m_referenceCount);
419     }
420
421     ULONG STDMETHODCALLTYPE DirectWriteFontFileLoader::Release()
422     {
423         ULONG newCount = InterlockedDecrement(&m_referenceCount);
424         if (newCount == 0)
425             delete this;
426         return newCount;
427     }
428
429     HRESULT STDMETHODCALLTYPE DirectWriteFontFileLoader::CreateStreamFromKey(
430         void const *fontFileReferenceKey,
431         UINT32 fontFileReferenceKeySize,
432         IDWriteFontFileStream **fontFileStream)
433     {
434         Q_UNUSED(fontFileReferenceKeySize);
435
436         if (fontFileReferenceKeySize != sizeof(const void *)) {
437             qWarning("%s: Wrong key size", __FUNCTION__);
438             return E_FAIL;
439         }
440
441         const void *key = *reinterpret_cast<void * const *>(fontFileReferenceKey);
442         *fontFileStream = NULL;
443         if (!m_fontDatas.contains(key))
444             return E_FAIL;
445
446         QByteArray fontData = m_fontDatas.value(key);
447         DirectWriteFontFileStream *stream = new DirectWriteFontFileStream(fontData);
448         stream->AddRef();
449         *fontFileStream = stream;
450
451         return S_OK;
452     }
453
454     class CustomFontFileLoader
455     {
456     public:
457         CustomFontFileLoader() : m_directWriteFactory(0), m_directWriteFontFileLoader(0)
458         {
459             HRESULT hres = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
460                                                __uuidof(IDWriteFactory),
461                                                reinterpret_cast<IUnknown **>(&m_directWriteFactory));
462             if (FAILED(hres)) {
463                 qErrnoWarning(hres, "%s: DWriteCreateFactory failed.", __FUNCTION__);
464             } else {
465                 m_directWriteFontFileLoader = new DirectWriteFontFileLoader();
466                 m_directWriteFactory->RegisterFontFileLoader(m_directWriteFontFileLoader);
467             }
468         }
469
470         ~CustomFontFileLoader()
471         {
472             if (m_directWriteFactory != 0 && m_directWriteFontFileLoader != 0)
473                 m_directWriteFactory->UnregisterFontFileLoader(m_directWriteFontFileLoader);
474
475             if (m_directWriteFactory != 0)
476                 m_directWriteFactory->Release();
477         }
478
479         void addKey(const void *key, const QByteArray &fontData)
480         {
481             if (m_directWriteFontFileLoader != 0)
482                 m_directWriteFontFileLoader->addKey(key, fontData);
483         }
484
485         void removeKey(const void *key)
486         {
487             if (m_directWriteFontFileLoader != 0)
488                 m_directWriteFontFileLoader->removeKey(key);
489         }
490
491         IDWriteFontFileLoader *loader() const
492         {
493             return m_directWriteFontFileLoader;
494         }
495
496     private:
497         IDWriteFactory *m_directWriteFactory;
498         DirectWriteFontFileLoader *m_directWriteFontFileLoader;
499     };
500
501 #endif
502
503 } // Anonymous namespace
504
505 /*!
506     \struct QWindowsFontEngineData
507     \brief Static constant data shared by the font engines.
508     \ingroup qt-lighthouse-win
509 */
510
511 QWindowsFontEngineData::QWindowsFontEngineData()
512     : clearTypeEnabled(false)
513     , fontSmoothingGamma(QWindowsFontDatabase::fontSmoothingGamma())
514 #if !defined(QT_NO_DIRECTWRITE)
515     , directWriteFactory(0)
516     , directWriteGdiInterop(0)
517 #endif
518 {
519     // from qapplication_win.cpp
520     UINT result = 0;
521     if (SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0))
522         clearTypeEnabled = (result == FE_FONTSMOOTHINGCLEARTYPE);
523
524     const qreal gray_gamma = 2.31;
525     for (int i=0; i<256; ++i)
526         pow_gamma[i] = uint(qRound(qPow(i / qreal(255.), gray_gamma) * 2047));
527
528     HDC displayDC = GetDC(0);
529     hdc = CreateCompatibleDC(displayDC);
530     ReleaseDC(0, displayDC);
531 }
532
533 QWindowsFontEngineData::~QWindowsFontEngineData()
534 {
535     if (hdc)
536         ReleaseDC(0, hdc);
537 #if !defined(QT_NO_DIRECTWRITE)
538     if (directWriteGdiInterop)
539         directWriteGdiInterop->Release();
540     if (directWriteFactory)
541         directWriteFactory->Release();
542 #endif
543 }
544
545 qreal QWindowsFontDatabase::fontSmoothingGamma()
546 {
547     int winSmooth;
548     qreal result = 1;
549     if (SystemParametersInfo(0x200C /* SPI_GETFONTSMOOTHINGCONTRAST */, 0, &winSmooth, 0))
550         result = qreal(winSmooth) / qreal(1000.0);
551
552     // Safeguard ourselves against corrupt registry values...
553     if (result > 5 || result < 1)
554         result = qreal(1.4);
555     return result;
556 }
557
558 #if !defined(QT_NO_DIRECTWRITE)
559 static inline bool initDirectWrite(QWindowsFontEngineData *d)
560 {
561     if (!d->directWriteFactory) {
562         const HRESULT hr = DWriteCreateFactory(
563                     DWRITE_FACTORY_TYPE_SHARED,
564                     __uuidof(IDWriteFactory),
565                     reinterpret_cast<IUnknown **>(&d->directWriteFactory)
566                     );
567         if (FAILED(hr)) {
568             qErrnoWarning("%s: DWriteCreateFactory failed", __FUNCTION__);
569             return false;
570         }
571     }
572     if (!d->directWriteGdiInterop) {
573         const HRESULT  hr = d->directWriteFactory->GetGdiInterop(&d->directWriteGdiInterop);
574         if (FAILED(hr)) {
575             qErrnoWarning("%s: GetGdiInterop failed", __FUNCTION__);
576             return false;
577         }
578     }
579     return true;
580 }
581
582 #endif // !defined(QT_NO_DIRECTWRITE)
583
584 /*!
585     \class QWindowsFontDatabase
586     \brief Font database for Windows
587
588     \note The Qt 4.8 WIndows font database employed a mechanism of
589     delayed population of the database again passing a font name
590     to EnumFontFamiliesEx(), working around the fact that
591     EnumFontFamiliesEx() does not list all fonts by default.
592     This should be introduced to Lighthouse as well?
593
594     \ingroup qt-lighthouse-win
595 */
596
597 QDebug operator<<(QDebug d, const QFontDef &def)
598 {
599     d.nospace() << "Family=" << def.family << " Stylename=" << def.styleName
600                 << " pointsize=" << def.pointSize << " pixelsize=" << def.pixelSize
601                 << " styleHint=" << def.styleHint << " weight=" << def.weight
602                 << " stretch=" << def.stretch << " hintingPreference="
603                 << def.hintingPreference << ' ';
604     return d;
605 }
606
607 /* From QFontDatabase.cpp, qt_determine_writing_systems_from_truetype_bits().
608  * Fixme: Make public? */
609
610 // see the Unicode subset bitfields in the MSDN docs
611 static int requiredUnicodeBits[QFontDatabase::WritingSystemsCount][2] = {
612         // Any,
613     { 127, 127 },
614         // Latin,
615     { 0, 127 },
616         // Greek,
617     { 7, 127 },
618         // Cyrillic,
619     { 9, 127 },
620         // Armenian,
621     { 10, 127 },
622         // Hebrew,
623     { 11, 127 },
624         // Arabic,
625     { 13, 127 },
626         // Syriac,
627     { 71, 127 },
628     //Thaana,
629     { 72, 127 },
630     //Devanagari,
631     { 15, 127 },
632     //Bengali,
633     { 16, 127 },
634     //Gurmukhi,
635     { 17, 127 },
636     //Gujarati,
637     { 18, 127 },
638     //Oriya,
639     { 19, 127 },
640     //Tamil,
641     { 20, 127 },
642     //Telugu,
643     { 21, 127 },
644     //Kannada,
645     { 22, 127 },
646     //Malayalam,
647     { 23, 127 },
648     //Sinhala,
649     { 73, 127 },
650     //Thai,
651     { 24, 127 },
652     //Lao,
653     { 25, 127 },
654     //Tibetan,
655     { 70, 127 },
656     //Myanmar,
657     { 74, 127 },
658         // Georgian,
659     { 26, 127 },
660         // Khmer,
661     { 80, 127 },
662         // SimplifiedChinese,
663     { 126, 127 },
664         // TraditionalChinese,
665     { 126, 127 },
666         // Japanese,
667     { 126, 127 },
668         // Korean,
669     { 56, 127 },
670         // Vietnamese,
671     { 0, 127 }, // same as latin1
672         // Other,
673     { 126, 127 },
674         // Ogham,
675     { 78, 127 },
676         // Runic,
677     { 79, 127 },
678         // Nko,
679     { 14, 127 },
680 };
681
682 enum
683 {
684     SimplifiedChineseCsbBit = 18,
685     TraditionalChineseCsbBit = 20,
686     JapaneseCsbBit = 17,
687     KoreanCsbBit = 21
688 };
689
690 static inline void writingSystemsFromTrueTypeBits(quint32 unicodeRange[4],
691                                                   quint32 codePageRange[2],
692                                                   QSupportedWritingSystems *ws)
693 {
694     bool hasScript = false;
695     for(int i = 0; i < QFontDatabase::WritingSystemsCount; i++) {
696         int bit = requiredUnicodeBits[i][0];
697         int index = bit/32;
698         int flag =  1 << (bit&31);
699         if (bit != 126 && unicodeRange[index] & flag) {
700             bit = requiredUnicodeBits[i][1];
701             index = bit/32;
702
703             flag =  1 << (bit&31);
704             if (bit == 127 || unicodeRange[index] & flag) {
705                 ws->setSupported(QFontDatabase::WritingSystem(i), true);
706                 hasScript = true;
707             }
708         }
709     }
710     if(codePageRange[0] & (1 << SimplifiedChineseCsbBit)) {
711         ws->setSupported(QFontDatabase::SimplifiedChinese, true);
712         hasScript = true;
713     }
714     if(codePageRange[0] & (1 << TraditionalChineseCsbBit)) {
715         ws->setSupported(QFontDatabase::TraditionalChinese, true);
716         hasScript = true;
717     }
718     if(codePageRange[0] & (1 << JapaneseCsbBit)) {
719         ws->setSupported(QFontDatabase::Japanese, true);
720         hasScript = true;
721         //qDebug("font %s supports Japanese", familyName.latin1());
722     }
723     if(codePageRange[0] & (1 << KoreanCsbBit)) {
724         ws->setSupported(QFontDatabase::Korean, true);
725         hasScript = true;
726     }
727     if (!hasScript)
728         ws->setSupported(QFontDatabase::Symbol, true);
729 }
730
731 // convert 0 ~ 1000 integer to QFont::Weight
732 static inline QFont::Weight weightFromInteger(long weight)
733 {
734     if (weight < 400)
735         return QFont::Light;
736     if (weight < 600)
737         return QFont::Normal;
738     if (weight < 700)
739         return QFont::DemiBold;
740     if (weight < 800)
741         return QFont::Bold;
742     return QFont::Black;
743 }
744
745 static inline QFontDatabase::WritingSystem writingSystemFromScript(const QString &scriptName)
746 {
747     if (scriptName == QStringLiteral("Western")
748             || scriptName == QStringLiteral("Baltic")
749             || scriptName == QStringLiteral("Central European")
750             || scriptName == QStringLiteral("Turkish")
751             || scriptName == QStringLiteral("Vietnamese")
752             || scriptName == QStringLiteral("OEM/Dos"))
753         return QFontDatabase::Latin;
754     if (scriptName == QStringLiteral("Thai"))
755         return QFontDatabase::Thai;
756     if (scriptName == QStringLiteral("Symbol")
757         || scriptName == QStringLiteral("Other"))
758         return QFontDatabase::Symbol;
759     if (scriptName == QStringLiteral("CHINESE_GB2312"))
760         return QFontDatabase::SimplifiedChinese;
761     if (scriptName == QStringLiteral("CHINESE_BIG5"))
762         return QFontDatabase::TraditionalChinese;
763     if (scriptName == QStringLiteral("Cyrillic"))
764         return QFontDatabase::Cyrillic;
765     if (scriptName == QStringLiteral("Hangul"))
766         return QFontDatabase::Korean;
767     if (scriptName == QStringLiteral("Hebrew"))
768         return QFontDatabase::Hebrew;
769     if (scriptName == QStringLiteral("Greek"))
770         return QFontDatabase::Greek;
771     if (scriptName == QStringLiteral("Japanese"))
772         return QFontDatabase::Japanese;
773     if (scriptName == QStringLiteral("Arabic"))
774         return QFontDatabase::Arabic;
775     return QFontDatabase::Any;
776 }
777
778 #ifdef MAKE_TAG
779 #undef MAKE_TAG
780 #endif
781 // GetFontData expects the tags in little endian ;(
782 #define MAKE_TAG(ch1, ch2, ch3, ch4) (\
783     (((quint32)(ch4)) << 24) | \
784     (((quint32)(ch3)) << 16) | \
785     (((quint32)(ch2)) << 8) | \
786     ((quint32)(ch1)) \
787     )
788
789 bool localizedName(const QString &name)
790 {
791     const QChar *c = name.unicode();
792     for (int i = 0; i < name.length(); ++i) {
793         if (c[i].unicode() >= 0x100)
794             return true;
795     }
796     return false;
797 }
798
799 static inline quint16 getUShort(const unsigned char *p)
800 {
801     quint16 val;
802     val = *p++ << 8;
803     val |= *p;
804
805     return val;
806 }
807
808 static QString getEnglishName(const uchar *table, quint32 bytes)
809 {
810     QString i18n_name;
811     enum {
812         NameRecordSize = 12,
813         FamilyId = 1,
814         MS_LangIdEnglish = 0x009
815     };
816
817     // get the name table
818     quint16 count;
819     quint16 string_offset;
820     const unsigned char *names;
821
822     int microsoft_id = -1;
823     int apple_id = -1;
824     int unicode_id = -1;
825
826     if (getUShort(table) != 0)
827         goto error;
828
829     count = getUShort(table+2);
830     string_offset = getUShort(table+4);
831     names = table + 6;
832
833     if (string_offset >= bytes || 6 + count*NameRecordSize > string_offset)
834         goto error;
835
836     for (int i = 0; i < count; ++i) {
837         // search for the correct name entry
838
839         quint16 platform_id = getUShort(names + i*NameRecordSize);
840         quint16 encoding_id = getUShort(names + 2 + i*NameRecordSize);
841         quint16 language_id = getUShort(names + 4 + i*NameRecordSize);
842         quint16 name_id = getUShort(names + 6 + i*NameRecordSize);
843
844         if (name_id != FamilyId)
845             continue;
846
847         enum {
848             PlatformId_Unicode = 0,
849             PlatformId_Apple = 1,
850             PlatformId_Microsoft = 3
851         };
852
853         quint16 length = getUShort(names + 8 + i*NameRecordSize);
854         quint16 offset = getUShort(names + 10 + i*NameRecordSize);
855         if (DWORD(string_offset + offset + length) >= bytes)
856             continue;
857
858         if ((platform_id == PlatformId_Microsoft
859             && (encoding_id == 0 || encoding_id == 1))
860             && (language_id & 0x3ff) == MS_LangIdEnglish
861             && microsoft_id == -1)
862             microsoft_id = i;
863         // not sure if encoding id 4 for Unicode is utf16 or ucs4...
864         else if (platform_id == PlatformId_Unicode && encoding_id < 4 && unicode_id == -1)
865             unicode_id = i;
866         else if (platform_id == PlatformId_Apple && encoding_id == 0 && language_id == 0)
867             apple_id = i;
868     }
869     {
870         bool unicode = false;
871         int id = -1;
872         if (microsoft_id != -1) {
873             id = microsoft_id;
874             unicode = true;
875         } else if (apple_id != -1) {
876             id = apple_id;
877             unicode = false;
878         } else if (unicode_id != -1) {
879             id = unicode_id;
880             unicode = true;
881         }
882         if (id != -1) {
883             quint16 length = getUShort(names + 8 + id*NameRecordSize);
884             quint16 offset = getUShort(names + 10 + id*NameRecordSize);
885             if (unicode) {
886                 // utf16
887
888                 length /= 2;
889                 i18n_name.resize(length);
890                 QChar *uc = (QChar *) i18n_name.unicode();
891                 const unsigned char *string = table + string_offset + offset;
892                 for (int i = 0; i < length; ++i)
893                     uc[i] = getUShort(string + 2*i);
894             } else {
895                 // Apple Roman
896
897                 i18n_name.resize(length);
898                 QChar *uc = (QChar *) i18n_name.unicode();
899                 const unsigned char *string = table + string_offset + offset;
900                 for (int i = 0; i < length; ++i)
901                     uc[i] = QLatin1Char(string[i]);
902             }
903         }
904     }
905 error:
906     //qDebug("got i18n name of '%s' for font '%s'", i18n_name.latin1(), familyName.toLocal8Bit().data());
907     return i18n_name;
908 }
909
910 QString getEnglishName(const QString &familyName)
911 {
912     QString i18n_name;
913
914     HDC hdc = GetDC( 0 );
915     LOGFONT lf;
916     memset(&lf, 0, sizeof(LOGFONT));
917     memcpy(lf.lfFaceName, familyName.utf16(), qMin(LF_FACESIZE, familyName.length()) * sizeof(wchar_t));
918     lf.lfCharSet = DEFAULT_CHARSET;
919     HFONT hfont = CreateFontIndirect(&lf);
920
921     if (!hfont) {
922         ReleaseDC(0, hdc);
923         return QString();
924     }
925
926     HGDIOBJ oldobj = SelectObject( hdc, hfont );
927
928     const DWORD name_tag = MAKE_TAG( 'n', 'a', 'm', 'e' );
929
930     // get the name table
931     unsigned char *table = 0;
932
933     DWORD bytes = GetFontData( hdc, name_tag, 0, 0, 0 );
934     if ( bytes == GDI_ERROR ) {
935         // ### Unused variable
936         // int err = GetLastError();
937         goto error;
938     }
939
940     table = new unsigned char[bytes];
941     GetFontData(hdc, name_tag, 0, table, bytes);
942     if ( bytes == GDI_ERROR )
943         goto error;
944
945     i18n_name = getEnglishName(table, bytes);
946 error:
947     delete [] table;
948     SelectObject( hdc, oldobj );
949     DeleteObject( hfont );
950     ReleaseDC( 0, hdc );
951
952     //qDebug("got i18n name of '%s' for font '%s'", i18n_name.latin1(), familyName.toLocal8Bit().data());
953     return i18n_name;
954 }
955
956 Q_GUI_EXPORT void qt_registerAliasToFontFamily(const QString &familyName, const QString &alias);
957
958 static bool addFontToDatabase(QString familyName, const QString &scriptName,
959                               const TEXTMETRIC *textmetric,
960                               const FONTSIGNATURE *signature,
961                               int type)
962 {
963     // the "@family" fonts are just the same as "family". Ignore them.
964     if (familyName.at(0) == QLatin1Char('@') || familyName.startsWith(QStringLiteral("WST_")))
965         return false;
966
967     static const int SMOOTH_SCALABLE = 0xffff;
968     const QString foundryName; // No such concept.
969     const NEWTEXTMETRIC *tm = (NEWTEXTMETRIC *)textmetric;
970     const bool fixed = !(tm->tmPitchAndFamily & TMPF_FIXED_PITCH);
971     const bool ttf = (tm->tmPitchAndFamily & TMPF_TRUETYPE);
972     const bool scalable = tm->tmPitchAndFamily & (TMPF_VECTOR|TMPF_TRUETYPE);
973     const int size = scalable ? SMOOTH_SCALABLE : tm->tmHeight;
974     const QFont::Style style = tm->tmItalic ? QFont::StyleItalic : QFont::StyleNormal;
975     const bool antialias = false;
976     const QFont::Weight weight = weightFromInteger(tm->tmWeight);
977     const QFont::Stretch stretch = QFont::Unstretched;
978
979 #ifndef QT_NO_DEBUG_OUTPUT
980     if (QWindowsContext::verboseFonts > 2) {
981         QDebug nospace = qDebug().nospace();
982         nospace << __FUNCTION__ << familyName << scriptName
983                  << "TTF=" << ttf;
984         if (type & DEVICE_FONTTYPE)
985             nospace << " DEVICE";
986         if (type & RASTER_FONTTYPE)
987             nospace << " RASTER";
988         if (type & TRUETYPE_FONTTYPE)
989             nospace << " TRUETYPE";
990         nospace << " scalable=" << scalable << " Size=" << size
991                 << " Style=" << style << " Weight=" << weight
992                 << " stretch=" << stretch;
993     }
994 #endif
995
996     QString englishName;
997     if (ttf && localizedName(familyName))
998         englishName = getEnglishName(familyName);
999
1000     QSupportedWritingSystems writingSystems;
1001     if (type & TRUETYPE_FONTTYPE) {
1002         quint32 unicodeRange[4] = {
1003             signature->fsUsb[0], signature->fsUsb[1],
1004             signature->fsUsb[2], signature->fsUsb[3]
1005         };
1006         quint32 codePageRange[2] = {
1007             signature->fsCsb[0], signature->fsCsb[1]
1008         };
1009 #ifdef Q_OS_WINCE
1010         if (signature->fsUsb[0] == 0) {
1011             // If the unicode ranges bit mask is zero then
1012             // EnumFontFamiliesEx failed to determine it properly.
1013             // In this case we just pretend that the font supports all languages.
1014             unicodeRange[0] = 0xbfffffff;   // second most significant bit must be zero
1015             unicodeRange[1] = 0xffffffff;
1016             unicodeRange[2] = 0xffffffff;
1017             unicodeRange[3] = 0xffffffff;
1018         }
1019 #endif
1020         writingSystemsFromTrueTypeBits(unicodeRange, codePageRange, &writingSystems);
1021         // ### Hack to work around problem with Thai text on Windows 7. Segoe UI contains
1022         // the symbol for Baht, and Windows thus reports that it supports the Thai script.
1023         // Since it's the default UI font on this platform, most widgets will be unable to
1024         // display Thai text by default. As a temporary work around, we special case Segoe UI
1025         // and remove the Thai script from its list of supported writing systems.
1026         if (writingSystems.supported(QFontDatabase::Thai) &&
1027                 familyName == QStringLiteral("Segoe UI"))
1028             writingSystems.setSupported(QFontDatabase::Thai, false);
1029     } else {
1030         const QFontDatabase::WritingSystem ws = writingSystemFromScript(scriptName);
1031         if (ws != QFontDatabase::Any)
1032             writingSystems.setSupported(ws);
1033     }
1034
1035     QPlatformFontDatabase::registerFont(familyName, foundryName, weight,
1036                                         style, stretch, antialias, scalable, size, fixed, writingSystems, 0);
1037     // add fonts windows can generate for us:
1038     if (weight <= QFont::DemiBold)
1039         QPlatformFontDatabase::registerFont(familyName, foundryName, QFont::Bold,
1040                                             style, stretch, antialias, scalable, size, fixed, writingSystems, 0);
1041     if (style != QFont::StyleItalic)
1042         QPlatformFontDatabase::registerFont(familyName, foundryName, weight,
1043                                             QFont::StyleItalic, stretch, antialias, scalable, size, fixed, writingSystems, 0);
1044     if (weight <= QFont::DemiBold && style != QFont::StyleItalic)
1045         QPlatformFontDatabase::registerFont(familyName, foundryName, QFont::Bold,
1046                                             QFont::StyleItalic, stretch, antialias, scalable, size, fixed, writingSystems, 0);
1047
1048     if (!englishName.isEmpty())
1049         qt_registerAliasToFontFamily(familyName, englishName);
1050
1051     return true;
1052 }
1053
1054 static int CALLBACK storeFont(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textmetric,
1055                               int type, LPARAM namesSetIn)
1056 {
1057     typedef QSet<QString> StringSet;
1058     const QString familyName = QString::fromWCharArray(f->elfLogFont.lfFaceName);
1059     const QString script = QString::fromWCharArray(f->elfScript);
1060
1061     const FONTSIGNATURE signature = textmetric->ntmFontSig;
1062
1063     // NEWTEXTMETRICEX is a NEWTEXTMETRIC, which according to the documentation is
1064     // identical to a TEXTMETRIC except for the last four members, which we don't use
1065     // anyway
1066     if (addFontToDatabase(familyName, script, (TEXTMETRIC *)textmetric, &signature, type))
1067         reinterpret_cast<StringSet *>(namesSetIn)->insert(familyName);
1068
1069     // keep on enumerating
1070     return 1;
1071 }
1072
1073 void QWindowsFontDatabase::populateFontDatabase()
1074 {
1075     m_families.clear();
1076     removeApplicationFonts();
1077     QPlatformFontDatabase::populateFontDatabase();
1078     populate(); // Called multiple times.
1079     // Work around EnumFontFamiliesEx() not listing the system font, see below.
1080     const QString sysFontFamily = QGuiApplication::font().family();
1081     if (!m_families.contains(sysFontFamily))
1082          populate(sysFontFamily);
1083 }
1084
1085 /*!
1086     \brief Populate font database using EnumFontFamiliesEx().
1087
1088     Normally, leaving the name empty should enumerate
1089     all fonts, however, system fonts like "MS Shell Dlg 2"
1090     are only found when specifying the name explicitly.
1091 */
1092
1093 void QWindowsFontDatabase::populate(const QString &family)
1094     {
1095
1096     if (QWindowsContext::verboseFonts)
1097         qDebug() << __FUNCTION__ << m_families.size() << family;
1098
1099     HDC dummy = GetDC(0);
1100     LOGFONT lf;
1101     lf.lfCharSet = DEFAULT_CHARSET;
1102     if (family.size() >= LF_FACESIZE) {
1103         qWarning("%s: Unable to enumerate family '%s'.",
1104                  __FUNCTION__, qPrintable(family));
1105         return;
1106     }
1107     wmemcpy(lf.lfFaceName, reinterpret_cast<const wchar_t*>(family.utf16()),
1108             family.size() + 1);
1109     lf.lfPitchAndFamily = 0;
1110     EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)storeFont,
1111                        (LPARAM)&m_families, 0);
1112     ReleaseDC(0, dummy);
1113 }
1114
1115 QWindowsFontDatabase::QWindowsFontDatabase() :
1116     m_fontEngineData(new QWindowsFontEngineData)
1117 {
1118     // Properties accessed by QWin32PrintEngine (QtPrintSupport)
1119     static const int hfontMetaTypeId = qRegisterMetaType<HFONT>();
1120     static const int logFontMetaTypeId = qRegisterMetaType<LOGFONT>();
1121     Q_UNUSED(hfontMetaTypeId)
1122     Q_UNUSED(logFontMetaTypeId)
1123
1124     if (QWindowsContext::verboseFonts)
1125         qDebug() << __FUNCTION__ << "Clear type: "
1126                  << m_fontEngineData->clearTypeEnabled << "gamma: "
1127                  << m_fontEngineData->fontSmoothingGamma;
1128 }
1129
1130 QWindowsFontDatabase::~QWindowsFontDatabase()
1131 {
1132     removeApplicationFonts();
1133 }
1134
1135 QFontEngine * QWindowsFontDatabase::fontEngine(const QFontDef &fontDef,
1136                                               QUnicodeTables::Script script,
1137                                               void *handle)
1138 {
1139     QFontEngine *fe = QWindowsFontDatabase::createEngine(script, fontDef,
1140                                               0, QWindowsContext::instance()->defaultDPI(), false,
1141                                               QStringList(), m_fontEngineData);
1142     if (QWindowsContext::verboseFonts)
1143         qDebug() << __FUNCTION__ << "FONTDEF" << fontDef << script << fe << handle;
1144     return fe;
1145 }
1146
1147 QFontEngine *QWindowsFontDatabase::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference)
1148 {
1149     EmbeddedFont font(fontData);
1150     QFontEngine *fontEngine = 0;
1151
1152 #if !defined(QT_NO_DIRECTWRITE)
1153     if (hintingPreference == QFont::PreferDefaultHinting
1154         || hintingPreference == QFont::PreferFullHinting)
1155 #endif
1156     {
1157         GUID guid;
1158         CoCreateGuid(&guid);
1159
1160         QString uniqueFamilyName = QLatin1Char('f')
1161                 + QString::number(guid.Data1, 36) + QLatin1Char('-')
1162                 + QString::number(guid.Data2, 36) + QLatin1Char('-')
1163                 + QString::number(guid.Data3, 36) + QLatin1Char('-')
1164                 + QString::number(*reinterpret_cast<quint64 *>(guid.Data4), 36);
1165
1166         QString actualFontName = font.changeFamilyName(uniqueFamilyName);
1167         if (actualFontName.isEmpty()) {
1168             qWarning("%s: Can't change family name of font", __FUNCTION__);
1169             return 0;
1170         }
1171
1172         DWORD count = 0;
1173         QByteArray newFontData = font.data();
1174         HANDLE fontHandle = AddFontMemResourceEx((void *)newFontData.constData(), newFontData.size(), 0,
1175                                           &count);
1176         if (count == 0 && fontHandle != 0) {
1177             RemoveFontMemResourceEx(fontHandle);
1178             fontHandle = 0;
1179         }
1180
1181         if (fontHandle == 0) {
1182             qWarning("%s: AddFontMemResourceEx failed", __FUNCTION__);
1183         } else {
1184             QFontDef request;
1185             request.family = uniqueFamilyName;
1186             request.pixelSize = pixelSize;
1187             request.styleStrategy = QFont::NoFontMerging | QFont::PreferMatch;
1188             request.hintingPreference = hintingPreference;
1189
1190             fontEngine = QWindowsFontDatabase::createEngine(QUnicodeTables::Common, request, 0,
1191                     QWindowsContext::instance()->defaultDPI(), false, QStringList(),
1192                     m_fontEngineData);
1193
1194             if (fontEngine) {
1195                 if (request.family != fontEngine->fontDef.family) {
1196                     qWarning("%s: Failed to load font. Got fallback instead: %s",
1197                              __FUNCTION__, qPrintable(fontEngine->fontDef.family));
1198                     if (fontEngine->cache_count == 0 && fontEngine->ref.load() == 0)
1199                         delete fontEngine;
1200                     fontEngine = 0;
1201                 } else {
1202                     Q_ASSERT(fontEngine->cache_count == 0 && fontEngine->ref.load() == 0);
1203
1204                     // Override the generated font name
1205                     static_cast<QWindowsFontEngine *>(fontEngine)->setUniqueFamilyName(uniqueFamilyName);
1206                     fontEngine->fontDef.family = actualFontName;
1207                     UniqueFontData uniqueData;
1208                     uniqueData.handle = fontHandle;
1209                     uniqueData.refCount.ref();
1210                     m_uniqueFontData[uniqueFamilyName] = uniqueData;
1211                 }
1212             } else {
1213                 RemoveFontMemResourceEx(fontHandle);
1214             }
1215         }
1216     }
1217 #if !defined(QT_NO_DIRECTWRITE)
1218     else {
1219         CustomFontFileLoader fontFileLoader;
1220         fontFileLoader.addKey(this, fontData);
1221
1222         IDWriteFactory *factory = 0;
1223         HRESULT hres = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1224                                            __uuidof(IDWriteFactory),
1225                                            reinterpret_cast<IUnknown **>(&factory));
1226         if (FAILED(hres)) {
1227             qErrnoWarning(hres, "%s: DWriteCreateFactory failed", __FUNCTION__);
1228             return 0;
1229         }
1230
1231         IDWriteFontFile *fontFile = 0;
1232         void *key = this;
1233
1234         hres = factory->CreateCustomFontFileReference(&key, sizeof(void *),
1235                                                       fontFileLoader.loader(), &fontFile);
1236         if (FAILED(hres)) {
1237             qErrnoWarning(hres, "%s: CreateCustomFontFileReference failed", __FUNCTION__);
1238             factory->Release();
1239             return 0;
1240         }
1241
1242         BOOL isSupportedFontType;
1243         DWRITE_FONT_FILE_TYPE fontFileType;
1244         DWRITE_FONT_FACE_TYPE fontFaceType;
1245         UINT32 numberOfFaces;
1246         fontFile->Analyze(&isSupportedFontType, &fontFileType, &fontFaceType, &numberOfFaces);
1247         if (!isSupportedFontType) {
1248             fontFile->Release();
1249             factory->Release();
1250             return 0;
1251         }
1252
1253         IDWriteFontFace *directWriteFontFace = 0;
1254         hres = factory->CreateFontFace(fontFaceType, 1, &fontFile, 0, DWRITE_FONT_SIMULATIONS_NONE,
1255                                        &directWriteFontFace);
1256         if (FAILED(hres)) {
1257             qErrnoWarning(hres, "%s: CreateFontFace failed", __FUNCTION__);
1258             fontFile->Release();
1259             factory->Release();
1260             return 0;
1261         }
1262
1263         fontFile->Release();
1264
1265         fontEngine = new QWindowsFontEngineDirectWrite(directWriteFontFace, pixelSize,
1266                                                        m_fontEngineData);
1267
1268         // Get font family from font data
1269         fontEngine->fontDef.family = font.familyName();
1270
1271         directWriteFontFace->Release();
1272         factory->Release();
1273     }
1274 #endif
1275
1276     // Get style and weight info
1277     if (fontEngine != 0) {
1278         TableDirectory *os2TableEntry = font.tableDirectoryEntry("OS/2");
1279         if (os2TableEntry != 0) {
1280             const OS2Table *os2Table =
1281                     reinterpret_cast<const OS2Table *>(fontData.constData()
1282                                                        + qFromBigEndian<quint32>(os2TableEntry->offset));
1283
1284             bool italic = qFromBigEndian<quint16>(os2Table->selection) & 1;
1285             bool oblique = qFromBigEndian<quint16>(os2Table->selection) & 128;
1286
1287             if (italic)
1288                 fontEngine->fontDef.style = QFont::StyleItalic;
1289             else if (oblique)
1290                 fontEngine->fontDef.style = QFont::StyleOblique;
1291             else
1292                 fontEngine->fontDef.style = QFont::StyleNormal;
1293
1294             fontEngine->fontDef.weight = weightFromInteger(qFromBigEndian<quint16>(os2Table->weightClass));
1295         }
1296     }
1297
1298     if (QWindowsContext::verboseFonts)
1299         qDebug() << __FUNCTION__ << "FONTDATA" << fontData << pixelSize << hintingPreference << fontEngine;
1300     return fontEngine;
1301 }
1302
1303 QStringList QWindowsFontDatabase::fallbacksForFamily(const QString family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) const
1304 {
1305     QStringList result = QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script);
1306     if (!result.isEmpty())
1307         return result;
1308
1309     switch (styleHint) {
1310         case QFont::Times:
1311             result << QString::fromLatin1("Times New Roman");
1312             break;
1313         case QFont::Courier:
1314             result << QString::fromLatin1("Courier New");
1315             break;
1316         case QFont::Monospace:
1317             result << QString::fromLatin1("Courier New");
1318             break;
1319         case QFont::Cursive:
1320             result << QString::fromLatin1("Comic Sans MS");
1321             break;
1322         case QFont::Fantasy:
1323             result << QString::fromLatin1("Impact");
1324             break;
1325         case QFont::Decorative:
1326             result << QString::fromLatin1("Old English");
1327             break;
1328         case QFont::Helvetica:
1329         case QFont::System:
1330         default:
1331             result << QString::fromLatin1("Arial");
1332     }
1333
1334     if (QWindowsContext::verboseFonts)
1335         qDebug() << __FUNCTION__ << family << style << styleHint
1336                  << script << result << m_families.size();
1337     return result;
1338 }
1339
1340 static QList<quint32> getTrueTypeFontOffsets(const uchar *fontData)
1341 {
1342     QList<quint32> offsets;
1343     const quint32 headerTag = *reinterpret_cast<const quint32 *>(fontData);
1344     if (headerTag != MAKE_TAG('t', 't', 'c', 'f')) {
1345         if (headerTag != MAKE_TAG(0, 1, 0, 0)
1346             && headerTag != MAKE_TAG('O', 'T', 'T', 'O')
1347             && headerTag != MAKE_TAG('t', 'r', 'u', 'e')
1348             && headerTag != MAKE_TAG('t', 'y', 'p', '1'))
1349             return offsets;
1350         offsets << 0;
1351         return offsets;
1352     }
1353     const quint32 numFonts = qFromBigEndian<quint32>(fontData + 8);
1354     for (uint i = 0; i < numFonts; ++i) {
1355         offsets << qFromBigEndian<quint32>(fontData + 12 + i * 4);
1356     }
1357     return offsets;
1358 }
1359
1360 static void getFontTable(const uchar *fileBegin, const uchar *data, quint32 tag, const uchar **table, quint32 *length)
1361 {
1362     const quint16 numTables = qFromBigEndian<quint16>(data + 4);
1363     for (uint i = 0; i < numTables; ++i) {
1364         const quint32 offset = 12 + 16 * i;
1365         if (*reinterpret_cast<const quint32 *>(data + offset) == tag) {
1366             *table = fileBegin + qFromBigEndian<quint32>(data + offset + 8);
1367             *length = qFromBigEndian<quint32>(data + offset + 12);
1368             return;
1369         }
1370     }
1371     *table = 0;
1372     *length = 0;
1373     return;
1374 }
1375
1376 static void getFamiliesAndSignatures(const QByteArray &fontData,
1377                                      QStringList *families,
1378                                      QVector<FONTSIGNATURE> *signatures)
1379 {
1380     const uchar *data = reinterpret_cast<const uchar *>(fontData.constData());
1381
1382     QList<quint32> offsets = getTrueTypeFontOffsets(data);
1383     if (offsets.isEmpty())
1384         return;
1385
1386     for (int i = 0; i < offsets.count(); ++i) {
1387         const uchar *font = data + offsets.at(i);
1388         const uchar *table;
1389         quint32 length;
1390         getFontTable(data, font, MAKE_TAG('n', 'a', 'm', 'e'), &table, &length);
1391         if (!table)
1392             continue;
1393         QString name = getEnglishName(table, length);
1394         if (name.isEmpty())
1395             continue;
1396
1397         families->append(name);
1398
1399         if (signatures) {
1400             FONTSIGNATURE signature;
1401             getFontTable(data, font, MAKE_TAG('O', 'S', '/', '2'), &table, &length);
1402             if (table && length >= 86) {
1403                 // Offsets taken from OS/2 table in the TrueType spec
1404                 signature.fsUsb[0] = qFromBigEndian<quint32>(table + 42);
1405                 signature.fsUsb[1] = qFromBigEndian<quint32>(table + 46);
1406                 signature.fsUsb[2] = qFromBigEndian<quint32>(table + 50);
1407                 signature.fsUsb[3] = qFromBigEndian<quint32>(table + 54);
1408
1409                 signature.fsCsb[0] = qFromBigEndian<quint32>(table + 78);
1410                 signature.fsCsb[1] = qFromBigEndian<quint32>(table + 82);
1411             } else {
1412                 memset(&signature, 0, sizeof(signature));
1413             }
1414             signatures->append(signature);
1415         }
1416     }
1417 }
1418
1419 QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName)
1420 {
1421     WinApplicationFont font;
1422     font.fileName = fileName;
1423     QVector<FONTSIGNATURE> signatures;
1424     QStringList families;
1425
1426     if (!fontData.isEmpty()) {
1427         getFamiliesAndSignatures(fontData, &families, &signatures);
1428         if (families.isEmpty())
1429             return families;
1430
1431         DWORD dummy = 0;
1432         font.handle = AddFontMemResourceEx((void *)fontData.constData(), fontData.size(), 0,
1433                                              &dummy);
1434         if (font.handle == 0)
1435             return QStringList();
1436
1437         // Memory fonts won't show up in enumeration, so do add them the hard way.
1438         for (int j = 0; j < families.count(); ++j) {
1439             const QString familyName = families.at(j);
1440             HDC hdc = GetDC(0);
1441             LOGFONT lf;
1442             memset(&lf, 0, sizeof(LOGFONT));
1443             memcpy(lf.lfFaceName, familyName.utf16(), sizeof(wchar_t) * qMin(LF_FACESIZE, familyName.size()));
1444             lf.lfCharSet = DEFAULT_CHARSET;
1445             HFONT hfont = CreateFontIndirect(&lf);
1446             HGDIOBJ oldobj = SelectObject(hdc, hfont);
1447
1448             TEXTMETRIC textMetrics;
1449             GetTextMetrics(hdc, &textMetrics);
1450
1451             addFontToDatabase(familyName, QString(), &textMetrics, &signatures.at(j),
1452                               TRUETYPE_FONTTYPE);
1453
1454             SelectObject(hdc, oldobj);
1455             DeleteObject(hfont);
1456             ReleaseDC(0, hdc);
1457         }
1458     } else {
1459         QFile f(fileName);
1460         if (!f.open(QIODevice::ReadOnly))
1461             return families;
1462         QByteArray data = f.readAll();
1463         f.close();
1464
1465         getFamiliesAndSignatures(data, &families, 0);
1466         if (families.isEmpty())
1467             return families;
1468
1469         if (AddFontResourceExW((wchar_t*)fileName.utf16(), FR_PRIVATE, 0) == 0)
1470             return QStringList();
1471
1472         font.handle = 0;
1473
1474         // Fonts based on files are added via populate, as they will show up in font enumeration.
1475         for (int j = 0; j < families.count(); ++j)
1476             populate(families.at(j));
1477     }
1478
1479     m_applicationFonts << font;
1480
1481     return families;
1482 }
1483
1484 void QWindowsFontDatabase::removeApplicationFonts()
1485 {
1486     foreach (const WinApplicationFont &font, m_applicationFonts) {
1487         if (font.handle) {
1488             RemoveFontMemResourceEx(font.handle);
1489         } else {
1490             RemoveFontResourceExW((LPCWSTR)font.fileName.utf16(), FR_PRIVATE, 0);
1491         }
1492     }
1493     m_applicationFonts.clear();
1494 }
1495
1496 void QWindowsFontDatabase::releaseHandle(void *handle)
1497 {
1498     if (handle && QWindowsContext::verboseFonts)
1499         qDebug() << __FUNCTION__ << handle;
1500 }
1501
1502 QString QWindowsFontDatabase::fontDir() const
1503 {
1504     const QString result = QPlatformFontDatabase::fontDir();
1505     if (QWindowsContext::verboseFonts)
1506         qDebug() << __FUNCTION__ << result;
1507     return result;
1508 }
1509
1510 bool QWindowsFontDatabase::fontsAlwaysScalable() const
1511 {
1512     return true;
1513 }
1514
1515 void QWindowsFontDatabase::derefUniqueFont(const QString &uniqueFont)
1516 {
1517     if (m_uniqueFontData.contains(uniqueFont)) {
1518         if (!m_uniqueFontData[uniqueFont].refCount.deref()) {
1519             RemoveFontMemResourceEx(m_uniqueFontData[uniqueFont].handle);
1520             m_uniqueFontData.remove(uniqueFont);
1521         }
1522     }
1523 }
1524
1525 void QWindowsFontDatabase::refUniqueFont(const QString &uniqueFont)
1526 {
1527     if (m_uniqueFontData.contains(uniqueFont))
1528         m_uniqueFontData[uniqueFont].refCount.ref();
1529 }
1530
1531 HFONT QWindowsFontDatabase::systemFont()
1532 {
1533     static const HFONT stock_sysfont = (HFONT)GetStockObject(SYSTEM_FONT);
1534     return stock_sysfont;
1535 }
1536
1537 // Creation functions
1538
1539 static inline bool scriptRequiresOpenType(int script)
1540 {
1541     return ((script >= QUnicodeTables::Syriac && script <= QUnicodeTables::Sinhala)
1542             || script == QUnicodeTables::Khmer || script == QUnicodeTables::Nko);
1543 }
1544
1545 static const char *other_tryFonts[] = {
1546     "Arial",
1547     "MS UI Gothic",
1548     "Gulim",
1549     "SimSun",
1550     "PMingLiU",
1551     "Arial Unicode MS",
1552     0
1553 };
1554
1555 static const char *jp_tryFonts [] = {
1556     "MS UI Gothic",
1557     "Arial",
1558     "Gulim",
1559     "SimSun",
1560     "PMingLiU",
1561     "Arial Unicode MS",
1562     0
1563 };
1564
1565 static const char *ch_CN_tryFonts [] = {
1566     "SimSun",
1567     "Arial",
1568     "PMingLiU",
1569     "Gulim",
1570     "MS UI Gothic",
1571     "Arial Unicode MS",
1572     0
1573 };
1574
1575 static const char *ch_TW_tryFonts [] = {
1576     "PMingLiU",
1577     "Arial",
1578     "SimSun",
1579     "Gulim",
1580     "MS UI Gothic",
1581     "Arial Unicode MS",
1582     0
1583 };
1584
1585 static const char *kr_tryFonts[] = {
1586     "Gulim",
1587     "Arial",
1588     "PMingLiU",
1589     "SimSun",
1590     "MS UI Gothic",
1591     "Arial Unicode MS",
1592     0
1593 };
1594
1595 static const char **tryFonts = 0;
1596
1597 QFontEngine *QWindowsFontDatabase::createEngine(int script, const QFontDef &request,
1598                                                 HDC fontHdc, int dpi, bool rawMode,
1599                                                 const QStringList &family_list,
1600                                                 const QSharedPointer<QWindowsFontEngineData> &data)
1601 {
1602     LOGFONT lf;
1603     memset(&lf, 0, sizeof(LOGFONT));
1604
1605     const bool useDevice = (request.styleStrategy & QFont::PreferDevice) && fontHdc;
1606
1607     const HDC hdc = useDevice ? fontHdc : data->hdc;
1608
1609     bool stockFont = false;
1610     bool preferClearTypeAA = false;
1611
1612     HFONT hfont = 0;
1613
1614 #if !defined(QT_NO_DIRECTWRITE)
1615     bool useDirectWrite = (request.hintingPreference == QFont::PreferNoHinting)
1616                        || (request.hintingPreference == QFont::PreferVerticalHinting);
1617     IDWriteFont *directWriteFont = 0;
1618 #else
1619     bool useDirectWrite = false;
1620 #endif
1621
1622     if (rawMode) {                        // will choose a stock font
1623         int f = SYSTEM_FONT;
1624         const QString fam = request.family.toLower();
1625         if (fam == QStringLiteral("default") || fam == QStringLiteral("system"))
1626             f = SYSTEM_FONT;
1627 #ifndef Q_OS_WINCE
1628         else if (fam == QStringLiteral("system_fixed"))
1629             f = SYSTEM_FIXED_FONT;
1630         else if (fam == QStringLiteral("ansi_fixed"))
1631             f = ANSI_FIXED_FONT;
1632         else if (fam == QStringLiteral("ansi_var"))
1633             f = ANSI_VAR_FONT;
1634         else if (fam == QStringLiteral("device_default"))
1635             f = DEVICE_DEFAULT_FONT;
1636         else if (fam == QStringLiteral("oem_fixed"))
1637             f = OEM_FIXED_FONT;
1638 #endif
1639         else if (fam.at(0) == QLatin1Char('#'))
1640             f = fam.right(fam.length()-1).toInt();
1641         hfont = (HFONT)GetStockObject(f);
1642         if (!hfont) {
1643             qErrnoWarning("%s: GetStockObject failed", __FUNCTION__);
1644             hfont = QWindowsFontDatabase::systemFont();
1645         }
1646         stockFont = true;
1647     } else {
1648         int hint = FF_DONTCARE;
1649         switch (request.styleHint) {
1650             case QFont::Helvetica:
1651                 hint = FF_SWISS;
1652                 break;
1653             case QFont::Times:
1654                 hint = FF_ROMAN;
1655                 break;
1656             case QFont::Courier:
1657                 hint = FF_MODERN;
1658                 break;
1659             case QFont::OldEnglish:
1660                 hint = FF_DECORATIVE;
1661                 break;
1662             case QFont::System:
1663                 hint = FF_MODERN;
1664                 break;
1665             default:
1666                 break;
1667         }
1668
1669         lf.lfHeight = -qRound(request.pixelSize);
1670         lf.lfWidth                = 0;
1671         lf.lfEscapement        = 0;
1672         lf.lfOrientation        = 0;
1673         if (request.weight == 50)
1674             lf.lfWeight = FW_DONTCARE;
1675         else
1676             lf.lfWeight = (request.weight*900)/99;
1677         lf.lfItalic         = request.style != QFont::StyleNormal;
1678         lf.lfCharSet        = DEFAULT_CHARSET;
1679
1680         int strat = OUT_DEFAULT_PRECIS;
1681         if (request.styleStrategy & QFont::PreferBitmap) {
1682             strat = OUT_RASTER_PRECIS;
1683 #ifndef Q_OS_WINCE
1684         } else if (request.styleStrategy & QFont::PreferDevice) {
1685             strat = OUT_DEVICE_PRECIS;
1686         } else if (request.styleStrategy & QFont::PreferOutline) {
1687             strat = OUT_OUTLINE_PRECIS;
1688         } else if (request.styleStrategy & QFont::ForceOutline) {
1689             strat = OUT_TT_ONLY_PRECIS;
1690 #endif
1691         }
1692
1693         lf.lfOutPrecision   = strat;
1694
1695         int qual = DEFAULT_QUALITY;
1696
1697         if (request.styleStrategy & QFont::PreferMatch)
1698             qual = DRAFT_QUALITY;
1699 #ifndef Q_OS_WINCE
1700         else if (request.styleStrategy & QFont::PreferQuality)
1701             qual = PROOF_QUALITY;
1702 #endif
1703
1704         if (request.styleStrategy & QFont::PreferAntialias) {
1705             if (QSysInfo::WindowsVersion >= QSysInfo::WV_XP) {
1706                 qual = CLEARTYPE_QUALITY;
1707                 preferClearTypeAA = true;
1708             } else {
1709                 qual = ANTIALIASED_QUALITY;
1710             }
1711         } else if (request.styleStrategy & QFont::NoAntialias) {
1712             qual = NONANTIALIASED_QUALITY;
1713         }
1714
1715         lf.lfQuality        = qual;
1716
1717         lf.lfClipPrecision  = CLIP_DEFAULT_PRECIS;
1718         lf.lfPitchAndFamily = DEFAULT_PITCH | hint;
1719
1720         QString fam = request.family;
1721
1722         if(fam.isEmpty())
1723             fam = QStringLiteral("MS Sans Serif");
1724
1725         if ((fam == QStringLiteral("MS Sans Serif"))
1726             && (request.style == QFont::StyleItalic || (-lf.lfHeight > 18 && -lf.lfHeight != 24))) {
1727             fam = QStringLiteral("Arial"); // MS Sans Serif has bearing problems in italic, and does not scale
1728         }
1729         if (fam == QStringLiteral("Courier") && !(request.styleStrategy & QFont::PreferBitmap))
1730             fam = QStringLiteral("Courier New");
1731
1732         memcpy(lf.lfFaceName, fam.utf16(), sizeof(wchar_t) * qMin(fam.length() + 1, 32));  // 32 = Windows hard-coded
1733
1734         hfont = CreateFontIndirect(&lf);
1735         if (!hfont)
1736             qErrnoWarning("%s: CreateFontIndirect failed", __FUNCTION__);
1737
1738         stockFont = (hfont == 0);
1739         bool ttf = false;
1740         int avWidth = 0;
1741         BOOL res;
1742         HGDIOBJ oldObj = SelectObject(hdc, hfont);
1743
1744         TEXTMETRIC tm;
1745         res = GetTextMetrics(hdc, &tm);
1746         avWidth = tm.tmAveCharWidth;
1747         ttf = tm.tmPitchAndFamily & TMPF_TRUETYPE;
1748         SelectObject(hdc, oldObj);
1749
1750         if (!ttf || !useDirectWrite) {
1751             useDirectWrite = false;
1752
1753             if (hfont && (!ttf || request.stretch != 100)) {
1754                 DeleteObject(hfont);
1755                 if (!res)
1756                     qErrnoWarning("QFontEngine::loadEngine: GetTextMetrics failed");
1757                 lf.lfWidth = avWidth * request.stretch/100;
1758                 hfont = CreateFontIndirect(&lf);
1759                 if (!hfont)
1760                     qErrnoWarning("%s: CreateFontIndirect with stretch failed", __FUNCTION__);
1761             }
1762
1763 #ifndef Q_OS_WINCE
1764             if (hfont == 0) {
1765                 hfont = (HFONT)GetStockObject(ANSI_VAR_FONT);
1766                 stockFont = true;
1767             }
1768 #else
1769             if (hfont == 0) {
1770                 hfont = (HFONT)GetStockObject(SYSTEM_FONT);
1771                 stockFont = true;
1772             }
1773 #endif
1774         }
1775
1776 #if !defined(QT_NO_DIRECTWRITE)
1777         else {
1778             // Default to false for DirectWrite (and re-enable once/if everything
1779             // turns out okay)
1780             useDirectWrite = false;
1781             if (initDirectWrite(data.data())) {
1782                 const QString nameSubstitute = QWindowsFontEngineDirectWrite::fontNameSubstitute(QString::fromWCharArray(lf.lfFaceName));
1783                 memcpy(lf.lfFaceName, nameSubstitute.utf16(),
1784                        sizeof(wchar_t) * qMin(nameSubstitute.length() + 1, LF_FACESIZE));
1785
1786                 HRESULT hr = data->directWriteGdiInterop->CreateFontFromLOGFONT(
1787                             &lf,
1788                             &directWriteFont);
1789                 if (FAILED(hr)) {
1790                     qErrnoWarning("%s: CreateFontFromLOGFONT failed", __FUNCTION__);
1791                 } else {
1792                     DeleteObject(hfont);
1793                     useDirectWrite = true;
1794                 }
1795         }
1796         }
1797 #endif
1798     }
1799
1800     QFontEngine *fe = 0;
1801     if (!useDirectWrite)  {
1802         QWindowsFontEngine *few = new QWindowsFontEngine(request.family, hfont, stockFont, lf, data);
1803         few->setObjectName(QStringLiteral("QWindowsFontEngine_") + request.family);
1804         if (preferClearTypeAA)
1805             few->glyphFormat = QFontEngineGlyphCache::Raster_RGBMask;
1806
1807         // Also check for OpenType tables when using complex scripts
1808         // ### TODO: This only works for scripts that require OpenType. More generally
1809         // for scripts that do not require OpenType we should just look at the list of
1810         // supported writing systems in the font's OS/2 table.
1811         if (scriptRequiresOpenType(script)) {
1812             HB_Face hbFace = few->harfbuzzFace();
1813             if (!hbFace || !hbFace->supported_scripts[script]) {
1814                 qWarning("  OpenType support missing for script\n");
1815                 delete few;
1816                 return 0;
1817             }
1818         }
1819
1820         few->initFontInfo(request, fontHdc, dpi);
1821         fe = few;
1822     }
1823
1824 #if !defined(QT_NO_DIRECTWRITE)
1825     else {
1826         IDWriteFontFace *directWriteFontFace = NULL;
1827         HRESULT hr = directWriteFont->CreateFontFace(&directWriteFontFace);
1828         if (SUCCEEDED(hr)) {
1829             QWindowsFontEngineDirectWrite *fedw = new QWindowsFontEngineDirectWrite(directWriteFontFace,
1830                                                                                     request.pixelSize,
1831                                                                                     data);
1832             fedw->initFontInfo(request, dpi, directWriteFont);
1833             fedw->setObjectName(QStringLiteral("QWindowsFontEngineDirectWrite_") + request.family);
1834             fe = fedw;
1835         } else {
1836             qErrnoWarning("%s: CreateFontFace failed", __FUNCTION__);
1837         }
1838     }
1839
1840     if (directWriteFont != 0)
1841         directWriteFont->Release();
1842 #endif
1843
1844     if(script == QUnicodeTables::Common
1845        && !(request.styleStrategy & QFont::NoFontMerging)) {
1846        QFontDatabase db;
1847        if (!db.writingSystems(request.family).contains(QFontDatabase::Symbol)) {
1848            if(!tryFonts) {
1849                LANGID lid = GetUserDefaultLangID();
1850                switch( lid&0xff ) {
1851                case LANG_CHINESE: // Chinese (Taiwan)
1852                    if ( lid == 0x0804 ) // Taiwan
1853                        tryFonts = ch_TW_tryFonts;
1854                    else
1855                        tryFonts = ch_CN_tryFonts;
1856                    break;
1857                case LANG_JAPANESE:
1858                    tryFonts = jp_tryFonts;
1859                    break;
1860                case LANG_KOREAN:
1861                    tryFonts = kr_tryFonts;
1862                    break;
1863                default:
1864                    tryFonts = other_tryFonts;
1865                    break;
1866                }
1867            }
1868            QStringList fm = QFontDatabase().families();
1869            QStringList list = family_list;
1870            const char **tf = tryFonts;
1871            while(tf && *tf) {
1872                if(fm.contains(QLatin1String(*tf)))
1873                    list << QLatin1String(*tf);
1874                ++tf;
1875            }
1876            QFontEngine *mfe = new QWindowsMultiFontEngine(fe, list);
1877            mfe->setObjectName(QStringLiteral("QWindowsMultiFontEngine_") + request.family);
1878            mfe->fontDef = fe->fontDef;
1879            fe = mfe;
1880        }
1881     }
1882     return fe;
1883 }
1884
1885 static inline int verticalDPI()
1886 {
1887     return GetDeviceCaps(QWindowsContext::instance()->displayContext(), LOGPIXELSY);
1888 }
1889
1890 QFont QWindowsFontDatabase::systemDefaultFont()
1891 {
1892     LOGFONT lf;
1893     GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(lf), &lf);
1894     QFont systemFont =  QWindowsFontDatabase::LOGFONT_to_QFont(lf);
1895     // "MS Shell Dlg 2" is the correct system font >= Win2k
1896     if (systemFont.family() == QStringLiteral("MS Shell Dlg"))
1897         systemFont.setFamily(QStringLiteral("MS Shell Dlg 2"));
1898     if (QWindowsContext::verboseFonts)
1899         qDebug() << __FUNCTION__ << systemFont;
1900     return systemFont;
1901 }
1902
1903 QFont QWindowsFontDatabase::LOGFONT_to_QFont(const LOGFONT& logFont, int verticalDPI_In)
1904 {
1905     if (verticalDPI_In <= 0)
1906         verticalDPI_In = verticalDPI();
1907     QFont qFont(QString::fromWCharArray(logFont.lfFaceName));
1908     qFont.setItalic(logFont.lfItalic);
1909     if (logFont.lfWeight != FW_DONTCARE)
1910         qFont.setWeight(weightFromInteger(logFont.lfWeight));
1911     const qreal logFontHeight = qAbs(logFont.lfHeight);
1912     qFont.setPointSizeF(logFontHeight * 72.0 / qreal(verticalDPI_In));
1913     qFont.setUnderline(false);
1914     qFont.setOverline(false);
1915     qFont.setStrikeOut(false);
1916     return qFont;
1917 }
1918
1919 QT_END_NAMESPACE