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