Fix uses of qRound on non-floating-point types.
[profile/ivi/qtbase.git] / src / gui / text / qrawfont_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 test suite 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 "qrawfont_p.h"
43 #include <private/qsystemlibrary_p.h>
44
45 #if !defined(QT_NO_DIRECTWRITE)
46 #  include "qfontenginedirectwrite_p.h"
47 #  include <dwrite.h>
48 #endif
49
50 #if !defined(QT_NO_RAWFONT)
51
52 QT_BEGIN_NAMESPACE
53
54 namespace {
55
56     template<typename T>
57     struct BigEndian
58     {
59         quint8 data[sizeof(T)];
60
61         operator T() const
62         {
63             T littleEndian = 0;
64             for (int i=0; i<sizeof(T); ++i) {
65                 littleEndian |= data[i] << ((sizeof(T) - i - 1) * 8);
66             }
67
68             return littleEndian;
69         }
70
71         BigEndian<T> &operator=(const T &t)
72         {
73             for (int i=0; i<sizeof(T); ++i) {
74                 data[i] = ((t >> (sizeof(T) - i - 1) * 8) & 0xff);
75             }
76
77             return *this;
78         }
79     };
80
81 #   pragma pack(1)
82
83     // Common structure for all formats of the "name" table
84     struct NameTable
85     {
86         BigEndian<quint16> format;
87         BigEndian<quint16> count;
88         BigEndian<quint16> stringOffset;
89     };
90
91     struct NameRecord
92     {
93         BigEndian<quint16> platformID;
94         BigEndian<quint16> encodingID;
95         BigEndian<quint16> languageID;
96         BigEndian<quint16> nameID;
97         BigEndian<quint16> length;
98         BigEndian<quint16> offset;
99     };
100
101     struct OffsetSubTable
102     {
103         BigEndian<quint32> scalerType;
104         BigEndian<quint16> numTables;
105         BigEndian<quint16> searchRange;
106         BigEndian<quint16> entrySelector;
107         BigEndian<quint16> rangeShift;
108     };
109
110     struct TableDirectory
111     {
112         BigEndian<quint32> identifier;
113         BigEndian<quint32> checkSum;
114         BigEndian<quint32> offset;
115         BigEndian<quint32> length;
116     };
117
118     struct OS2Table
119     {
120         BigEndian<quint16> version;
121         BigEndian<qint16>  avgCharWidth;
122         BigEndian<quint16> weightClass;
123         BigEndian<quint16> widthClass;
124         BigEndian<quint16> type;
125         BigEndian<qint16>  subscriptXSize;
126         BigEndian<qint16>  subscriptYSize;
127         BigEndian<qint16>  subscriptXOffset;
128         BigEndian<qint16>  subscriptYOffset;
129         BigEndian<qint16>  superscriptXSize;
130         BigEndian<qint16>  superscriptYSize;
131         BigEndian<qint16>  superscriptXOffset;
132         BigEndian<qint16>  superscriptYOffset;
133         BigEndian<qint16>  strikeOutSize;
134         BigEndian<qint16>  strikeOutPosition;
135         BigEndian<qint16>  familyClass;
136         quint8             panose[10];
137         BigEndian<quint32> unicodeRanges[4];
138         quint8             vendorID[4];
139         BigEndian<quint16> selection;
140         BigEndian<quint16> firstCharIndex;
141         BigEndian<quint16> lastCharIndex;
142         BigEndian<qint16>  typoAscender;
143         BigEndian<qint16>  typoDescender;
144         BigEndian<qint16>  typoLineGap;
145         BigEndian<quint16> winAscent;
146         BigEndian<quint16> winDescent;
147         BigEndian<quint32> codepageRanges[2];
148         BigEndian<qint16>  height;
149         BigEndian<qint16>  capHeight;
150         BigEndian<quint16> defaultChar;
151         BigEndian<quint16> breakChar;
152         BigEndian<quint16> maxContext;
153     };
154
155 #   pragma pack()
156
157     class EmbeddedFont
158     {
159     public:
160         EmbeddedFont(const QByteArray &fontData);
161
162         QString changeFamilyName(const QString &newFamilyName);
163         QByteArray data() const { return m_fontData; }
164         TableDirectory *tableDirectoryEntry(const QByteArray &tagName);
165         QString familyName(TableDirectory *nameTableDirectory = 0);
166
167     private:
168         QByteArray m_fontData;
169     };
170
171     EmbeddedFont::EmbeddedFont(const QByteArray &fontData) : m_fontData(fontData)
172     {
173     }
174
175     TableDirectory *EmbeddedFont::tableDirectoryEntry(const QByteArray &tagName)
176     {
177         Q_ASSERT(tagName.size() == 4);
178
179         const BigEndian<quint32> *tagIdPtr =
180                 reinterpret_cast<const BigEndian<quint32> *>(tagName.constData());
181         quint32 tagId = *tagIdPtr;
182
183         OffsetSubTable *offsetSubTable = reinterpret_cast<OffsetSubTable *>(m_fontData.data());
184         TableDirectory *tableDirectory = reinterpret_cast<TableDirectory *>(offsetSubTable + 1);
185
186         TableDirectory *nameTableDirectoryEntry = 0;
187         for (int i=0; i<offsetSubTable->numTables; ++i, ++tableDirectory) {
188             if (tableDirectory->identifier == tagId) {
189                 nameTableDirectoryEntry = tableDirectory;
190                 break;
191             }
192         }
193
194         return nameTableDirectoryEntry;
195     }
196
197     QString EmbeddedFont::familyName(TableDirectory *nameTableDirectoryEntry)
198     {
199         QString name;
200
201         if (nameTableDirectoryEntry == 0)
202             nameTableDirectoryEntry = tableDirectoryEntry("name");
203
204         if (nameTableDirectoryEntry != 0) {
205             NameTable *nameTable = reinterpret_cast<NameTable *>(m_fontData.data()
206                                                                  + nameTableDirectoryEntry->offset);
207             NameRecord *nameRecord = reinterpret_cast<NameRecord *>(nameTable + 1);
208             for (int i=0; i<nameTable->count; ++i, ++nameRecord) {
209                 if (nameRecord->nameID == 1
210                  && nameRecord->platformID == 3 // Windows
211                  && nameRecord->languageID == 0x0409) { // US English
212                     const void *ptr = reinterpret_cast<const quint8 *>(nameTable)
213                                                         + nameTable->stringOffset
214                                                         + nameRecord->offset;
215
216                     const BigEndian<quint16> *s = reinterpret_cast<const BigEndian<quint16> *>(ptr);
217                     for (int j=0; j<nameRecord->length / sizeof(quint16); ++j)
218                         name += QChar(s[j]);
219
220                     break;
221                 }
222             }
223         }
224
225         return name;
226     }
227
228     QString EmbeddedFont::changeFamilyName(const QString &newFamilyName)
229     {
230         TableDirectory *nameTableDirectoryEntry = tableDirectoryEntry("name");
231         if (nameTableDirectoryEntry == 0)
232             return QString();
233
234         QString oldFamilyName = familyName(nameTableDirectoryEntry);
235
236         // Reserve size for name table header, five required name records and string
237         const int requiredRecordCount = 5;
238         quint16 nameIds[requiredRecordCount] = { 1, 2, 3, 4, 6 };
239
240         int sizeOfHeader = sizeof(NameTable) + sizeof(NameRecord) * requiredRecordCount;
241         int newFamilyNameSize = newFamilyName.size() * sizeof(quint16);
242
243         const QString regularString = QString::fromLatin1("Regular");
244         int regularStringSize = regularString.size() * sizeof(quint16);
245
246         // Align table size of table to 32 bits (pad with 0)
247         int fullSize = ((sizeOfHeader + newFamilyNameSize + regularStringSize) & ~3) + 4;
248
249         QByteArray newNameTable(fullSize, char(0));
250
251         {
252             NameTable *nameTable = reinterpret_cast<NameTable *>(newNameTable.data());
253             nameTable->count = requiredRecordCount;
254             nameTable->stringOffset = sizeOfHeader;
255
256             NameRecord *nameRecord = reinterpret_cast<NameRecord *>(nameTable + 1);
257             for (int i=0; i<requiredRecordCount; ++i, nameRecord++) {
258                 nameRecord->nameID = nameIds[i];
259                 nameRecord->encodingID = 1;
260                 nameRecord->languageID = 0x0409;
261                 nameRecord->platformID = 3;
262                 nameRecord->length = newFamilyNameSize;
263
264                 // Special case for sub-family
265                 if (nameIds[i] == 4) {
266                     nameRecord->offset = newFamilyNameSize;
267                     nameRecord->length = regularStringSize;
268                 }
269             }
270
271             // nameRecord now points to string data
272             BigEndian<quint16> *stringStorage = reinterpret_cast<BigEndian<quint16> *>(nameRecord);
273             const quint16 *sourceString = newFamilyName.utf16();
274             for (int i=0; i<newFamilyName.size(); ++i)
275                 stringStorage[i] = sourceString[i];
276             stringStorage += newFamilyName.size();
277
278             sourceString = regularString.utf16();
279             for (int i=0; i<regularString.size(); ++i)
280                 stringStorage[i] = sourceString[i];
281         }
282
283         quint32 *p = reinterpret_cast<quint32 *>(newNameTable.data());
284         quint32 *tableEnd = reinterpret_cast<quint32 *>(newNameTable.data() + fullSize);
285
286         quint32 checkSum = 0;
287         while (p < tableEnd)
288             checkSum += *(p++);
289
290         nameTableDirectoryEntry->checkSum = checkSum;
291         nameTableDirectoryEntry->offset = m_fontData.size();
292         nameTableDirectoryEntry->length = fullSize;
293
294         m_fontData.append(newNameTable);
295
296         return oldFamilyName;
297     }
298
299 #if !defined(QT_NO_DIRECTWRITE)
300
301     class DirectWriteFontFileStream: public IDWriteFontFileStream
302     {
303     public:
304         DirectWriteFontFileStream(const QByteArray &fontData)
305             : m_fontData(fontData)
306             , m_referenceCount(0)
307         {
308         }
309
310         ~DirectWriteFontFileStream()
311         {
312         }
313
314         HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **object);
315         ULONG STDMETHODCALLTYPE AddRef();
316         ULONG STDMETHODCALLTYPE Release();
317
318         HRESULT STDMETHODCALLTYPE ReadFileFragment(const void **fragmentStart, UINT64 fileOffset,
319                                                    UINT64 fragmentSize, OUT void **fragmentContext);
320         void STDMETHODCALLTYPE ReleaseFileFragment(void *fragmentContext);
321         HRESULT STDMETHODCALLTYPE GetFileSize(OUT UINT64 *fileSize);
322         HRESULT STDMETHODCALLTYPE GetLastWriteTime(OUT UINT64 *lastWriteTime);
323
324     private:
325         QByteArray m_fontData;
326         ULONG m_referenceCount;
327     };
328
329     HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::QueryInterface(REFIID iid, void **object)
330     {
331         if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileStream)) {
332             *object = this;
333             AddRef();
334             return S_OK;
335         } else {
336             *object = NULL;
337             return E_NOINTERFACE;
338         }
339     }
340
341     ULONG STDMETHODCALLTYPE DirectWriteFontFileStream::AddRef()
342     {
343         return InterlockedIncrement(&m_referenceCount);
344     }
345
346     ULONG STDMETHODCALLTYPE DirectWriteFontFileStream::Release()
347     {
348         ULONG newCount = InterlockedDecrement(&m_referenceCount);
349         if (newCount == 0)
350             delete this;
351         return newCount;
352     }
353
354     HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::ReadFileFragment(
355         const void **fragmentStart,
356         UINT64 fileOffset,
357         UINT64 fragmentSize,
358         OUT void **fragmentContext)
359     {
360         *fragmentContext = NULL;
361         if (fragmentSize + fileOffset <= m_fontData.size()) {
362             *fragmentStart = m_fontData.data() + fileOffset;
363             return S_OK;
364         } else {
365             *fragmentStart = NULL;
366             return E_FAIL;
367         }
368     }
369
370     void STDMETHODCALLTYPE DirectWriteFontFileStream::ReleaseFileFragment(void *)
371     {
372     }
373
374     HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::GetFileSize(UINT64 *fileSize)
375     {
376         *fileSize = m_fontData.size();
377         return S_OK;
378     }
379
380     HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::GetLastWriteTime(UINT64 *lastWriteTime)
381     {
382         *lastWriteTime = 0;
383         return E_NOTIMPL;
384     }
385
386     class DirectWriteFontFileLoader: public IDWriteFontFileLoader
387     {
388     public:
389         DirectWriteFontFileLoader() : m_referenceCount(0) {}
390
391         ~DirectWriteFontFileLoader()
392         {
393         }
394
395         inline void addKey(const void *key, const QByteArray &fontData)
396         {
397             Q_ASSERT(!m_fontDatas.contains(key));
398             m_fontDatas.insert(key, fontData);
399         }
400
401         inline void removeKey(const void *key)
402         {
403             m_fontDatas.remove(key);
404         }
405
406         HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **object);
407         ULONG STDMETHODCALLTYPE AddRef();
408         ULONG STDMETHODCALLTYPE Release();
409
410         HRESULT STDMETHODCALLTYPE CreateStreamFromKey(void const *fontFileReferenceKey,
411                                                       UINT32 fontFileReferenceKeySize,
412                                                       OUT IDWriteFontFileStream **fontFileStream);
413
414     private:
415         ULONG m_referenceCount;
416         QHash<const void *, QByteArray> m_fontDatas;
417     };
418
419     HRESULT STDMETHODCALLTYPE DirectWriteFontFileLoader::QueryInterface(const IID &iid,
420                                                                         void **object)
421     {
422         if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) {
423             *object = this;
424             AddRef();
425             return S_OK;
426         } else {
427             *object = NULL;
428             return E_NOINTERFACE;
429         }
430     }
431
432     ULONG STDMETHODCALLTYPE DirectWriteFontFileLoader::AddRef()
433     {
434         return InterlockedIncrement(&m_referenceCount);
435     }
436
437     ULONG STDMETHODCALLTYPE DirectWriteFontFileLoader::Release()
438     {
439         ULONG newCount = InterlockedDecrement(&m_referenceCount);
440         if (newCount == 0)
441             delete this;
442         return newCount;
443     }
444
445     HRESULT STDMETHODCALLTYPE DirectWriteFontFileLoader::CreateStreamFromKey(
446         void const *fontFileReferenceKey,
447         UINT32 fontFileReferenceKeySize,
448         IDWriteFontFileStream **fontFileStream)
449     {
450         Q_UNUSED(fontFileReferenceKeySize);
451
452         if (fontFileReferenceKeySize != sizeof(const void *)) {
453             qWarning("DirectWriteFontFileLoader::CreateStreamFromKey: Wrong key size");
454             return E_FAIL;
455         }
456
457         const void *key = *reinterpret_cast<void * const *>(fontFileReferenceKey);
458         *fontFileStream = NULL;
459         if (!m_fontDatas.contains(key))
460             return E_FAIL;
461
462         QByteArray fontData = m_fontDatas.value(key);
463         DirectWriteFontFileStream *stream = new DirectWriteFontFileStream(fontData);
464         stream->AddRef();
465         *fontFileStream = stream;
466
467         return S_OK;
468     }
469
470     class CustomFontFileLoader
471     {
472     public:
473         CustomFontFileLoader() : m_directWriteFactory(0), m_directWriteFontFileLoader(0)
474         {
475             HRESULT hres = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
476                                                __uuidof(IDWriteFactory),
477                                                reinterpret_cast<IUnknown **>(&m_directWriteFactory));
478             if (FAILED(hres)) {
479                 qErrnoWarning(hres, "CustomFontFileLoader::CustomFontFileLoader: "
480                                     "DWriteCreateFactory failed.");
481             } else {
482                 m_directWriteFontFileLoader = new DirectWriteFontFileLoader();
483                 m_directWriteFactory->RegisterFontFileLoader(m_directWriteFontFileLoader);
484             }
485         }
486
487         ~CustomFontFileLoader()
488         {
489             if (m_directWriteFactory != 0 && m_directWriteFontFileLoader != 0)
490                 m_directWriteFactory->UnregisterFontFileLoader(m_directWriteFontFileLoader);
491
492             if (m_directWriteFactory != 0)
493                 m_directWriteFactory->Release();
494         }
495
496         void addKey(const void *key, const QByteArray &fontData)
497         {
498             if (m_directWriteFontFileLoader != 0)
499                 m_directWriteFontFileLoader->addKey(key, fontData);
500         }
501
502         void removeKey(const void *key)
503         {
504             if (m_directWriteFontFileLoader != 0)
505                 m_directWriteFontFileLoader->removeKey(key);
506         }
507
508         IDWriteFontFileLoader *loader() const
509         {
510             return m_directWriteFontFileLoader;
511         }
512
513     private:
514         IDWriteFactory *m_directWriteFactory;
515         DirectWriteFontFileLoader *m_directWriteFontFileLoader;
516     };
517
518 #endif
519
520 } // Anonymous namespace
521
522
523 // From qfontdatabase_win.cpp
524 extern QFontEngine *qt_load_font_engine_win(const QFontDef &request);
525 // From qfontdatabase.cpp
526 extern QFont::Weight weightFromInteger(int weight);
527
528 void QRawFontPrivate::platformCleanUp()
529 {
530     if (fontHandle != NULL) {
531         if (ptrRemoveFontMemResourceEx == NULL) {
532             void *func = QSystemLibrary::resolve(QLatin1String("gdi32"), "RemoveFontMemResourceEx");
533             ptrRemoveFontMemResourceEx =
534                     reinterpret_cast<QRawFontPrivate::PtrRemoveFontMemResourceEx>(func);
535         }
536
537         if (ptrRemoveFontMemResourceEx == NULL) {
538             qWarning("QRawFont::platformCleanUp: Can't find RemoveFontMemResourceEx in gdi32");
539             fontHandle = NULL;
540         } else {
541             ptrRemoveFontMemResourceEx(fontHandle);
542             fontHandle = NULL;
543         }
544     }
545 }
546
547 void QRawFontPrivate::platformLoadFromData(const QByteArray &_fontData,
548                                            int pixelSize,
549                                            QFont::HintingPreference hintingPreference)
550 {
551     QByteArray fontData(_fontData);
552     EmbeddedFont font(fontData);
553
554 #if !defined(QT_NO_DIRECTWRITE)
555     if (hintingPreference == QFont::PreferDefaultHinting
556      || hintingPreference == QFont::PreferFullHinting)
557 #endif
558     {
559         GUID guid;
560         CoCreateGuid(&guid);
561
562         QString uniqueFamilyName = QString::fromLatin1("f")
563                 + QString::number(guid.Data1, 36) + QLatin1Char('-')
564                 + QString::number(guid.Data2, 36) + QLatin1Char('-')
565                 + QString::number(guid.Data3, 36) + QLatin1Char('-')
566                 + QString::number(*reinterpret_cast<quint64 *>(guid.Data4), 36);
567
568         QString actualFontName = font.changeFamilyName(uniqueFamilyName);
569         if (actualFontName.isEmpty()) {
570             qWarning("QRawFont::platformLoadFromData: Can't change family name of font");
571             return;
572         }
573
574         if (ptrAddFontMemResourceEx == NULL || ptrRemoveFontMemResourceEx == NULL) {
575             void *func = QSystemLibrary::resolve(QLatin1String("gdi32"), "RemoveFontMemResourceEx");
576             ptrRemoveFontMemResourceEx =
577                     reinterpret_cast<QRawFontPrivate::PtrRemoveFontMemResourceEx>(func);
578
579             func = QSystemLibrary::resolve(QLatin1String("gdi32"), "AddFontMemResourceEx");
580             ptrAddFontMemResourceEx =
581                     reinterpret_cast<QRawFontPrivate::PtrAddFontMemResourceEx>(func);
582         }
583
584         Q_ASSERT(fontHandle == NULL);
585         if (ptrAddFontMemResourceEx != NULL && ptrRemoveFontMemResourceEx != NULL) {
586             DWORD count = 0;
587             fontData = font.data();
588             fontHandle = ptrAddFontMemResourceEx(fontData.data(), fontData.size(), 0, &count);
589
590             if (count == 0 && fontHandle != NULL) {
591                 ptrRemoveFontMemResourceEx(fontHandle);
592                 fontHandle = NULL;
593             }
594         }
595
596         if (fontHandle == NULL) {
597             qWarning("QRawFont::platformLoadFromData: AddFontMemResourceEx failed");
598         } else {
599             QFontDef request;
600             request.family = uniqueFamilyName;
601             request.pixelSize = pixelSize;
602             request.styleStrategy = QFont::NoFontMerging | QFont::PreferMatch;
603             request.hintingPreference = hintingPreference;
604
605             fontEngine = qt_load_font_engine_win(request);
606             if (request.family != fontEngine->fontDef.family) {
607                 qWarning("QRawFont::platformLoadFromData: Failed to load font. "
608                          "Got fallback instead: %s", qPrintable(fontEngine->fontDef.family));
609                 if (fontEngine->cache_count == 0 && fontEngine->ref == 0)
610                     delete fontEngine;
611                 fontEngine = 0;
612             } else {
613                 Q_ASSERT(fontEngine->cache_count == 0 && fontEngine->ref == 0);
614
615                 // Override the generated font name
616                 static_cast<QFontEngineWin *>(fontEngine)->uniqueFamilyName = uniqueFamilyName;
617                 fontEngine->fontDef.family = actualFontName;
618                 fontEngine->ref.ref();
619             }
620         }
621     }
622 #if !defined(QT_NO_DIRECTWRITE)
623     else {
624         CustomFontFileLoader fontFileLoader;
625         fontFileLoader.addKey(this, fontData);
626
627         IDWriteFactory *factory = NULL;
628         HRESULT hres = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
629                                            __uuidof(IDWriteFactory),
630                                            reinterpret_cast<IUnknown **>(&factory));
631         if (FAILED(hres)) {
632             qErrnoWarning(hres, "QRawFont::platformLoadFromData: DWriteCreateFactory failed");
633             return;
634         }
635
636         IDWriteFontFile *fontFile = NULL;
637         void *key = this;
638
639         hres = factory->CreateCustomFontFileReference(&key, sizeof(void *),
640                                                       fontFileLoader.loader(), &fontFile);
641         if (FAILED(hres)) {
642             qErrnoWarning(hres, "QRawFont::platformLoadFromData: "
643                                 "CreateCustomFontFileReference failed");
644             factory->Release();
645             return;
646         }
647
648         BOOL isSupportedFontType;
649         DWRITE_FONT_FILE_TYPE fontFileType;
650         DWRITE_FONT_FACE_TYPE fontFaceType;
651         UINT32 numberOfFaces;
652         fontFile->Analyze(&isSupportedFontType, &fontFileType, &fontFaceType, &numberOfFaces);
653         if (!isSupportedFontType) {
654             fontFile->Release();
655             factory->Release();
656             return;
657         }
658
659         IDWriteFontFace *directWriteFontFace = NULL;
660         hres = factory->CreateFontFace(fontFaceType, 1, &fontFile, 0, DWRITE_FONT_SIMULATIONS_NONE,
661                                        &directWriteFontFace);
662         if (FAILED(hres)) {
663             qErrnoWarning(hres, "QRawFont::platformLoadFromData: CreateFontFace failed");
664             fontFile->Release();
665             factory->Release();
666             return;
667         }
668
669         fontFile->Release();
670
671         fontEngine = new QFontEngineDirectWrite(factory, directWriteFontFace, pixelSize);
672
673         // Get font family from font data
674         fontEngine->fontDef.family = font.familyName();
675         fontEngine->ref.ref();
676
677         directWriteFontFace->Release();
678         factory->Release();
679     }
680 #endif
681
682     // Get style and weight info
683     if (fontEngine != 0) {
684         TableDirectory *os2TableEntry = font.tableDirectoryEntry("OS/2");
685         if (os2TableEntry != 0) {
686             const OS2Table *os2Table =
687                     reinterpret_cast<const OS2Table *>(fontData.constData()
688                                                        + os2TableEntry->offset);
689
690             bool italic = os2Table->selection & 1;
691             bool oblique = os2Table->selection & 128;
692
693             if (italic)
694                 fontEngine->fontDef.style = QFont::StyleItalic;
695             else if (oblique)
696                 fontEngine->fontDef.style = QFont::StyleOblique;
697             else
698                 fontEngine->fontDef.style = QFont::StyleNormal;
699
700             fontEngine->fontDef.weight = weightFromInteger(os2Table->weightClass);
701         }
702     }
703 }
704
705 QT_END_NAMESPACE
706
707 #endif // QT_NO_RAWFONT