summaryrefslogtreecommitdiffstats
path: root/src/widgets/platforms/win/qrawfont_win.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/platforms/win/qrawfont_win.cpp')
-rw-r--r--src/widgets/platforms/win/qrawfont_win.cpp709
1 files changed, 709 insertions, 0 deletions
diff --git a/src/widgets/platforms/win/qrawfont_win.cpp b/src/widgets/platforms/win/qrawfont_win.cpp
new file mode 100644
index 0000000000..d8aa557975
--- /dev/null
+++ b/src/widgets/platforms/win/qrawfont_win.cpp
@@ -0,0 +1,709 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qrawfont_p.h"
+#include <private/qsystemlibrary_p.h>
+
+#if !defined(QT_NO_DIRECTWRITE)
+# include "qfontenginedirectwrite_p.h"
+# include <dwrite.h>
+#endif
+
+#if !defined(QT_NO_RAWFONT)
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+
+ template<typename T>
+ struct BigEndian
+ {
+ quint8 data[sizeof(T)];
+
+ operator T() const
+ {
+ T littleEndian = 0;
+ for (int i=0; i<sizeof(T); ++i) {
+ littleEndian |= data[i] << ((sizeof(T) - i - 1) * 8);
+ }
+
+ return littleEndian;
+ }
+
+ BigEndian<T> &operator=(const T &t)
+ {
+ for (int i=0; i<sizeof(T); ++i) {
+ data[i] = ((t >> (sizeof(T) - i - 1) * 8) & 0xff);
+ }
+
+ return *this;
+ }
+ };
+
+# pragma pack(1)
+
+ // Common structure for all formats of the "name" table
+ struct NameTable
+ {
+ BigEndian<quint16> format;
+ BigEndian<quint16> count;
+ BigEndian<quint16> stringOffset;
+ };
+
+ struct NameRecord
+ {
+ BigEndian<quint16> platformID;
+ BigEndian<quint16> encodingID;
+ BigEndian<quint16> languageID;
+ BigEndian<quint16> nameID;
+ BigEndian<quint16> length;
+ BigEndian<quint16> offset;
+ };
+
+ struct OffsetSubTable
+ {
+ BigEndian<quint32> scalerType;
+ BigEndian<quint16> numTables;
+ BigEndian<quint16> searchRange;
+ BigEndian<quint16> entrySelector;
+ BigEndian<quint16> rangeShift;
+ };
+
+ struct TableDirectory
+ {
+ BigEndian<quint32> identifier;
+ BigEndian<quint32> checkSum;
+ BigEndian<quint32> offset;
+ BigEndian<quint32> length;
+ };
+
+ struct OS2Table
+ {
+ BigEndian<quint16> version;
+ BigEndian<qint16> avgCharWidth;
+ BigEndian<quint16> weightClass;
+ BigEndian<quint16> widthClass;
+ BigEndian<quint16> type;
+ BigEndian<qint16> subscriptXSize;
+ BigEndian<qint16> subscriptYSize;
+ BigEndian<qint16> subscriptXOffset;
+ BigEndian<qint16> subscriptYOffset;
+ BigEndian<qint16> superscriptXSize;
+ BigEndian<qint16> superscriptYSize;
+ BigEndian<qint16> superscriptXOffset;
+ BigEndian<qint16> superscriptYOffset;
+ BigEndian<qint16> strikeOutSize;
+ BigEndian<qint16> strikeOutPosition;
+ BigEndian<qint16> familyClass;
+ quint8 panose[10];
+ BigEndian<quint32> unicodeRanges[4];
+ quint8 vendorID[4];
+ BigEndian<quint16> selection;
+ BigEndian<quint16> firstCharIndex;
+ BigEndian<quint16> lastCharIndex;
+ BigEndian<qint16> typoAscender;
+ BigEndian<qint16> typoDescender;
+ BigEndian<qint16> typoLineGap;
+ BigEndian<quint16> winAscent;
+ BigEndian<quint16> winDescent;
+ BigEndian<quint32> codepageRanges[2];
+ BigEndian<qint16> height;
+ BigEndian<qint16> capHeight;
+ BigEndian<quint16> defaultChar;
+ BigEndian<quint16> breakChar;
+ BigEndian<quint16> maxContext;
+ };
+
+# pragma pack()
+
+ class EmbeddedFont
+ {
+ public:
+ EmbeddedFont(const QByteArray &fontData);
+
+ QString changeFamilyName(const QString &newFamilyName);
+ QByteArray data() const { return m_fontData; }
+ TableDirectory *tableDirectoryEntry(const QByteArray &tagName);
+ QString familyName(TableDirectory *nameTableDirectory = 0);
+
+ private:
+ QByteArray m_fontData;
+ };
+
+ EmbeddedFont::EmbeddedFont(const QByteArray &fontData) : m_fontData(fontData)
+ {
+ }
+
+ TableDirectory *EmbeddedFont::tableDirectoryEntry(const QByteArray &tagName)
+ {
+ Q_ASSERT(tagName.size() == 4);
+
+ const BigEndian<quint32> *tagIdPtr =
+ reinterpret_cast<const BigEndian<quint32> *>(tagName.constData());
+ quint32 tagId = *tagIdPtr;
+
+ OffsetSubTable *offsetSubTable = reinterpret_cast<OffsetSubTable *>(m_fontData.data());
+ TableDirectory *tableDirectory = reinterpret_cast<TableDirectory *>(offsetSubTable + 1);
+
+ TableDirectory *nameTableDirectoryEntry = 0;
+ for (int i=0; i<offsetSubTable->numTables; ++i, ++tableDirectory) {
+ if (tableDirectory->identifier == tagId) {
+ nameTableDirectoryEntry = tableDirectory;
+ break;
+ }
+ }
+
+ return nameTableDirectoryEntry;
+ }
+
+ QString EmbeddedFont::familyName(TableDirectory *nameTableDirectoryEntry)
+ {
+ QString name;
+
+ if (nameTableDirectoryEntry == 0)
+ nameTableDirectoryEntry = tableDirectoryEntry("name");
+
+ if (nameTableDirectoryEntry != 0) {
+ NameTable *nameTable = reinterpret_cast<NameTable *>(m_fontData.data()
+ + nameTableDirectoryEntry->offset);
+ NameRecord *nameRecord = reinterpret_cast<NameRecord *>(nameTable + 1);
+ for (int i=0; i<nameTable->count; ++i, ++nameRecord) {
+ if (nameRecord->nameID == 1
+ && nameRecord->platformID == 3 // Windows
+ && nameRecord->languageID == 0x0409) { // US English
+ const void *ptr = reinterpret_cast<const quint8 *>(nameTable)
+ + nameTable->stringOffset
+ + nameRecord->offset;
+
+ const BigEndian<quint16> *s = reinterpret_cast<const BigEndian<quint16> *>(ptr);
+ for (int j=0; j<nameRecord->length / sizeof(quint16); ++j)
+ name += QChar(s[j]);
+
+ break;
+ }
+ }
+ }
+
+ return name;
+ }
+
+ QString EmbeddedFont::changeFamilyName(const QString &newFamilyName)
+ {
+ TableDirectory *nameTableDirectoryEntry = tableDirectoryEntry("name");
+ if (nameTableDirectoryEntry == 0)
+ return QString();
+
+ QString oldFamilyName = familyName(nameTableDirectoryEntry);
+
+ // Reserve size for name table header, five required name records and string
+ const int requiredRecordCount = 5;
+ quint16 nameIds[requiredRecordCount] = { 1, 2, 3, 4, 6 };
+
+ int sizeOfHeader = sizeof(NameTable) + sizeof(NameRecord) * requiredRecordCount;
+ int newFamilyNameSize = newFamilyName.size() * sizeof(quint16);
+
+ const QString regularString = QString::fromLatin1("Regular");
+ int regularStringSize = regularString.size() * sizeof(quint16);
+
+ // Align table size of table to 32 bits (pad with 0)
+ int fullSize = ((sizeOfHeader + newFamilyNameSize + regularStringSize) & ~3) + 4;
+
+ QByteArray newNameTable(fullSize, char(0));
+
+ {
+ NameTable *nameTable = reinterpret_cast<NameTable *>(newNameTable.data());
+ nameTable->count = requiredRecordCount;
+ nameTable->stringOffset = sizeOfHeader;
+
+ NameRecord *nameRecord = reinterpret_cast<NameRecord *>(nameTable + 1);
+ for (int i=0; i<requiredRecordCount; ++i, nameRecord++) {
+ nameRecord->nameID = nameIds[i];
+ nameRecord->encodingID = 1;
+ nameRecord->languageID = 0x0409;
+ nameRecord->platformID = 3;
+ nameRecord->length = newFamilyNameSize;
+
+ // Special case for sub-family
+ if (nameIds[i] == 4) {
+ nameRecord->offset = newFamilyNameSize;
+ nameRecord->length = regularStringSize;
+ }
+ }
+
+ // nameRecord now points to string data
+ BigEndian<quint16> *stringStorage = reinterpret_cast<BigEndian<quint16> *>(nameRecord);
+ const quint16 *sourceString = newFamilyName.utf16();
+ for (int i=0; i<newFamilyName.size(); ++i)
+ stringStorage[i] = sourceString[i];
+ stringStorage += newFamilyName.size();
+
+ sourceString = regularString.utf16();
+ for (int i=0; i<regularString.size(); ++i)
+ stringStorage[i] = sourceString[i];
+ }
+
+ quint32 *p = reinterpret_cast<quint32 *>(newNameTable.data());
+ quint32 *tableEnd = reinterpret_cast<quint32 *>(newNameTable.data() + fullSize);
+
+ quint32 checkSum = 0;
+ while (p < tableEnd)
+ checkSum += *(p++);
+
+ nameTableDirectoryEntry->checkSum = checkSum;
+ nameTableDirectoryEntry->offset = m_fontData.size();
+ nameTableDirectoryEntry->length = fullSize;
+
+ m_fontData.append(newNameTable);
+
+ return oldFamilyName;
+ }
+
+#if !defined(QT_NO_DIRECTWRITE)
+
+ class DirectWriteFontFileStream: public IDWriteFontFileStream
+ {
+ public:
+ DirectWriteFontFileStream(const QByteArray &fontData)
+ : m_fontData(fontData)
+ , m_referenceCount(0)
+ {
+ }
+
+ ~DirectWriteFontFileStream()
+ {
+ }
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **object);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ HRESULT STDMETHODCALLTYPE ReadFileFragment(const void **fragmentStart, UINT64 fileOffset,
+ UINT64 fragmentSize, OUT void **fragmentContext);
+ void STDMETHODCALLTYPE ReleaseFileFragment(void *fragmentContext);
+ HRESULT STDMETHODCALLTYPE GetFileSize(OUT UINT64 *fileSize);
+ HRESULT STDMETHODCALLTYPE GetLastWriteTime(OUT UINT64 *lastWriteTime);
+
+ private:
+ QByteArray m_fontData;
+ ULONG m_referenceCount;
+ };
+
+ HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::QueryInterface(REFIID iid, void **object)
+ {
+ if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileStream)) {
+ *object = this;
+ AddRef();
+ return S_OK;
+ } else {
+ *object = NULL;
+ return E_NOINTERFACE;
+ }
+ }
+
+ ULONG STDMETHODCALLTYPE DirectWriteFontFileStream::AddRef()
+ {
+ return InterlockedIncrement(&m_referenceCount);
+ }
+
+ ULONG STDMETHODCALLTYPE DirectWriteFontFileStream::Release()
+ {
+ ULONG newCount = InterlockedDecrement(&m_referenceCount);
+ if (newCount == 0)
+ delete this;
+ return newCount;
+ }
+
+ HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::ReadFileFragment(
+ const void **fragmentStart,
+ UINT64 fileOffset,
+ UINT64 fragmentSize,
+ OUT void **fragmentContext)
+ {
+ *fragmentContext = NULL;
+ if (fragmentSize + fileOffset <= m_fontData.size()) {
+ *fragmentStart = m_fontData.data() + fileOffset;
+ return S_OK;
+ } else {
+ *fragmentStart = NULL;
+ return E_FAIL;
+ }
+ }
+
+ void STDMETHODCALLTYPE DirectWriteFontFileStream::ReleaseFileFragment(void *)
+ {
+ }
+
+ HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::GetFileSize(UINT64 *fileSize)
+ {
+ *fileSize = m_fontData.size();
+ return S_OK;
+ }
+
+ HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::GetLastWriteTime(UINT64 *lastWriteTime)
+ {
+ *lastWriteTime = 0;
+ return E_NOTIMPL;
+ }
+
+ class DirectWriteFontFileLoader: public IDWriteFontFileLoader
+ {
+ public:
+ DirectWriteFontFileLoader() : m_referenceCount(0) {}
+
+ ~DirectWriteFontFileLoader()
+ {
+ }
+
+ inline void addKey(const void *key, const QByteArray &fontData)
+ {
+ Q_ASSERT(!m_fontDatas.contains(key));
+ m_fontDatas.insert(key, fontData);
+ }
+
+ inline void removeKey(const void *key)
+ {
+ m_fontDatas.remove(key);
+ }
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **object);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ HRESULT STDMETHODCALLTYPE CreateStreamFromKey(void const *fontFileReferenceKey,
+ UINT32 fontFileReferenceKeySize,
+ OUT IDWriteFontFileStream **fontFileStream);
+
+ private:
+ ULONG m_referenceCount;
+ QHash<const void *, QByteArray> m_fontDatas;
+ };
+
+ HRESULT STDMETHODCALLTYPE DirectWriteFontFileLoader::QueryInterface(const IID &iid,
+ void **object)
+ {
+ if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) {
+ *object = this;
+ AddRef();
+ return S_OK;
+ } else {
+ *object = NULL;
+ return E_NOINTERFACE;
+ }
+ }
+
+ ULONG STDMETHODCALLTYPE DirectWriteFontFileLoader::AddRef()
+ {
+ return InterlockedIncrement(&m_referenceCount);
+ }
+
+ ULONG STDMETHODCALLTYPE DirectWriteFontFileLoader::Release()
+ {
+ ULONG newCount = InterlockedDecrement(&m_referenceCount);
+ if (newCount == 0)
+ delete this;
+ return newCount;
+ }
+
+ HRESULT STDMETHODCALLTYPE DirectWriteFontFileLoader::CreateStreamFromKey(
+ void const *fontFileReferenceKey,
+ UINT32 fontFileReferenceKeySize,
+ IDWriteFontFileStream **fontFileStream)
+ {
+ Q_UNUSED(fontFileReferenceKeySize);
+
+ if (fontFileReferenceKeySize != sizeof(const void *)) {
+ qWarning("DirectWriteFontFileLoader::CreateStreamFromKey: Wrong key size");
+ return E_FAIL;
+ }
+
+ const void *key = *reinterpret_cast<void * const *>(fontFileReferenceKey);
+ *fontFileStream = NULL;
+ if (!m_fontDatas.contains(key))
+ return E_FAIL;
+
+ QByteArray fontData = m_fontDatas.value(key);
+ DirectWriteFontFileStream *stream = new DirectWriteFontFileStream(fontData);
+ stream->AddRef();
+ *fontFileStream = stream;
+
+ return S_OK;
+ }
+
+ class CustomFontFileLoader
+ {
+ public:
+ CustomFontFileLoader() : m_directWriteFactory(0), m_directWriteFontFileLoader(0)
+ {
+ HRESULT hres = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
+ __uuidof(IDWriteFactory),
+ reinterpret_cast<IUnknown **>(&m_directWriteFactory));
+ if (FAILED(hres)) {
+ qErrnoWarning(hres, "CustomFontFileLoader::CustomFontFileLoader: "
+ "DWriteCreateFactory failed.");
+ } else {
+ m_directWriteFontFileLoader = new DirectWriteFontFileLoader();
+ m_directWriteFactory->RegisterFontFileLoader(m_directWriteFontFileLoader);
+ }
+ }
+
+ ~CustomFontFileLoader()
+ {
+ if (m_directWriteFactory != 0 && m_directWriteFontFileLoader != 0)
+ m_directWriteFactory->UnregisterFontFileLoader(m_directWriteFontFileLoader);
+
+ if (m_directWriteFactory != 0)
+ m_directWriteFactory->Release();
+ }
+
+ void addKey(const void *key, const QByteArray &fontData)
+ {
+ if (m_directWriteFontFileLoader != 0)
+ m_directWriteFontFileLoader->addKey(key, fontData);
+ }
+
+ void removeKey(const void *key)
+ {
+ if (m_directWriteFontFileLoader != 0)
+ m_directWriteFontFileLoader->removeKey(key);
+ }
+
+ IDWriteFontFileLoader *loader() const
+ {
+ return m_directWriteFontFileLoader;
+ }
+
+ private:
+ IDWriteFactory *m_directWriteFactory;
+ DirectWriteFontFileLoader *m_directWriteFontFileLoader;
+ };
+
+#endif
+
+} // Anonymous namespace
+
+
+// From qfontdatabase_win.cpp
+extern QFontEngine *qt_load_font_engine_win(const QFontDef &request);
+// From qfontdatabase.cpp
+extern QFont::Weight weightFromInteger(int weight);
+
+void QRawFontPrivate::platformCleanUp()
+{
+ if (fontHandle != NULL) {
+ if (ptrRemoveFontMemResourceEx == NULL) {
+ QFunctionPointer func =
+ QSystemLibrary::resolve(QLatin1String("gdi32"), "RemoveFontMemResourceEx");
+ ptrRemoveFontMemResourceEx =
+ reinterpret_cast<QRawFontPrivate::PtrRemoveFontMemResourceEx>(func);
+ }
+
+ if (ptrRemoveFontMemResourceEx == NULL) {
+ qWarning("QRawFont::platformCleanUp: Can't find RemoveFontMemResourceEx in gdi32");
+ fontHandle = NULL;
+ } else {
+ ptrRemoveFontMemResourceEx(fontHandle);
+ fontHandle = NULL;
+ }
+ }
+}
+
+void QRawFontPrivate::platformLoadFromData(const QByteArray &_fontData,
+ qreal pixelSize,
+ QFont::HintingPreference hintingPreference)
+{
+ QByteArray fontData(_fontData);
+ EmbeddedFont font(fontData);
+
+#if !defined(QT_NO_DIRECTWRITE)
+ if (hintingPreference == QFont::PreferDefaultHinting
+ || hintingPreference == QFont::PreferFullHinting)
+#endif
+ {
+ GUID guid;
+ CoCreateGuid(&guid);
+
+ QString uniqueFamilyName = QString::fromLatin1("f")
+ + QString::number(guid.Data1, 36) + QLatin1Char('-')
+ + QString::number(guid.Data2, 36) + QLatin1Char('-')
+ + QString::number(guid.Data3, 36) + QLatin1Char('-')
+ + QString::number(*reinterpret_cast<quint64 *>(guid.Data4), 36);
+
+ QString actualFontName = font.changeFamilyName(uniqueFamilyName);
+ if (actualFontName.isEmpty()) {
+ qWarning("QRawFont::platformLoadFromData: Can't change family name of font");
+ return;
+ }
+
+ if (ptrAddFontMemResourceEx == NULL || ptrRemoveFontMemResourceEx == NULL) {
+ QFunctionPointer func =
+ QSystemLibrary::resolve(QLatin1String("gdi32"), "RemoveFontMemResourceEx");
+ ptrRemoveFontMemResourceEx =
+ reinterpret_cast<QRawFontPrivate::PtrRemoveFontMemResourceEx>(func);
+
+ func = QSystemLibrary::resolve(QLatin1String("gdi32"), "AddFontMemResourceEx");
+ ptrAddFontMemResourceEx =
+ reinterpret_cast<QRawFontPrivate::PtrAddFontMemResourceEx>(func);
+ }
+
+ Q_ASSERT(fontHandle == NULL);
+ if (ptrAddFontMemResourceEx != NULL && ptrRemoveFontMemResourceEx != NULL) {
+ DWORD count = 0;
+ fontData = font.data();
+ fontHandle = ptrAddFontMemResourceEx(fontData.data(), fontData.size(), 0, &count);
+
+ if (count == 0 && fontHandle != NULL) {
+ ptrRemoveFontMemResourceEx(fontHandle);
+ fontHandle = NULL;
+ }
+ }
+
+ if (fontHandle == NULL) {
+ qWarning("QRawFont::platformLoadFromData: AddFontMemResourceEx failed");
+ } else {
+ QFontDef request;
+ request.family = uniqueFamilyName;
+ request.pixelSize = pixelSize;
+ request.styleStrategy = QFont::NoFontMerging | QFont::PreferMatch;
+ request.hintingPreference = hintingPreference;
+
+ fontEngine = qt_load_font_engine_win(request);
+ if (request.family != fontEngine->fontDef.family) {
+ qWarning("QRawFont::platformLoadFromData: Failed to load font. "
+ "Got fallback instead: %s", qPrintable(fontEngine->fontDef.family));
+ if (fontEngine->cache_count == 0 && fontEngine->ref == 0)
+ delete fontEngine;
+ fontEngine = 0;
+ } else {
+ Q_ASSERT(fontEngine->cache_count == 0 && fontEngine->ref == 0);
+
+ // Override the generated font name
+ static_cast<QFontEngineWin *>(fontEngine)->uniqueFamilyName = uniqueFamilyName;
+ fontEngine->fontDef.family = actualFontName;
+ fontEngine->ref.ref();
+ }
+ }
+ }
+#if !defined(QT_NO_DIRECTWRITE)
+ else {
+ CustomFontFileLoader fontFileLoader;
+ fontFileLoader.addKey(this, fontData);
+
+ IDWriteFactory *factory = NULL;
+ HRESULT hres = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
+ __uuidof(IDWriteFactory),
+ reinterpret_cast<IUnknown **>(&factory));
+ if (FAILED(hres)) {
+ qErrnoWarning(hres, "QRawFont::platformLoadFromData: DWriteCreateFactory failed");
+ return;
+ }
+
+ IDWriteFontFile *fontFile = NULL;
+ void *key = this;
+
+ hres = factory->CreateCustomFontFileReference(&key, sizeof(void *),
+ fontFileLoader.loader(), &fontFile);
+ if (FAILED(hres)) {
+ qErrnoWarning(hres, "QRawFont::platformLoadFromData: "
+ "CreateCustomFontFileReference failed");
+ factory->Release();
+ return;
+ }
+
+ BOOL isSupportedFontType;
+ DWRITE_FONT_FILE_TYPE fontFileType;
+ DWRITE_FONT_FACE_TYPE fontFaceType;
+ UINT32 numberOfFaces;
+ fontFile->Analyze(&isSupportedFontType, &fontFileType, &fontFaceType, &numberOfFaces);
+ if (!isSupportedFontType) {
+ fontFile->Release();
+ factory->Release();
+ return;
+ }
+
+ IDWriteFontFace *directWriteFontFace = NULL;
+ hres = factory->CreateFontFace(fontFaceType, 1, &fontFile, 0, DWRITE_FONT_SIMULATIONS_NONE,
+ &directWriteFontFace);
+ if (FAILED(hres)) {
+ qErrnoWarning(hres, "QRawFont::platformLoadFromData: CreateFontFace failed");
+ fontFile->Release();
+ factory->Release();
+ return;
+ }
+
+ fontFile->Release();
+
+ fontEngine = new QFontEngineDirectWrite(factory, directWriteFontFace, pixelSize);
+
+ // Get font family from font data
+ fontEngine->fontDef.family = font.familyName();
+ fontEngine->ref.ref();
+
+ directWriteFontFace->Release();
+ factory->Release();
+ }
+#endif
+
+ // Get style and weight info
+ if (fontEngine != 0) {
+ TableDirectory *os2TableEntry = font.tableDirectoryEntry("OS/2");
+ if (os2TableEntry != 0) {
+ const OS2Table *os2Table =
+ reinterpret_cast<const OS2Table *>(fontData.constData()
+ + os2TableEntry->offset);
+
+ bool italic = os2Table->selection & 1;
+ bool oblique = os2Table->selection & 128;
+
+ if (italic)
+ fontEngine->fontDef.style = QFont::StyleItalic;
+ else if (oblique)
+ fontEngine->fontDef.style = QFont::StyleOblique;
+ else
+ fontEngine->fontDef.style = QFont::StyleNormal;
+
+ fontEngine->fontDef.weight = weightFromInteger(os2Table->weightClass);
+ }
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_RAWFONT