diff options
Diffstat (limited to 'src/gui/text/windows/qwindowsfontdatabasebase.cpp')
-rw-r--r-- | src/gui/text/windows/qwindowsfontdatabasebase.cpp | 284 |
1 files changed, 171 insertions, 113 deletions
diff --git a/src/gui/text/windows/qwindowsfontdatabasebase.cpp b/src/gui/text/windows/qwindowsfontdatabasebase.cpp index 566941eca9..84e619b0d9 100644 --- a/src/gui/text/windows/qwindowsfontdatabasebase.cpp +++ b/src/gui/text/windows/qwindowsfontdatabasebase.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qwindowsfontdatabasebase_p.h" #include "qwindowsfontdatabase_p.h" @@ -55,6 +19,8 @@ QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + // Helper classes for creating font engines directly from font data namespace { @@ -393,10 +359,10 @@ namespace { { } - inline void addKey(const void *key, const QByteArray &fontData) + inline void addKey(const QByteArray &fontData) { - Q_ASSERT(!m_fontDatas.contains(key)); - m_fontDatas.insert(key, fontData); + if (!m_fontDatas.contains(fontData.data())) + m_fontDatas.insert(fontData.data(), fontData); } inline void removeKey(const void *key) @@ -412,6 +378,11 @@ namespace { UINT32 fontFileReferenceKeySize, OUT IDWriteFontFileStream **fontFileStream) override; + void clear() + { + m_fontDatas.clear(); + } + private: ULONG m_referenceCount; QHash<const void *, QByteArray> m_fontDatas; @@ -469,52 +440,62 @@ namespace { return S_OK; } - class CustomFontFileLoader +} // Anonymous namespace + +class QCustomFontFileLoader +{ +public: + QCustomFontFileLoader(IDWriteFactory *factory) { - public: - CustomFontFileLoader(IDWriteFactory *factory) - { - m_directWriteFactory = factory; + m_directWriteFactory = factory; - if (m_directWriteFactory) { - m_directWriteFactory->AddRef(); + if (m_directWriteFactory) { + m_directWriteFactory->AddRef(); - m_directWriteFontFileLoader = new DirectWriteFontFileLoader(); - m_directWriteFactory->RegisterFontFileLoader(m_directWriteFontFileLoader); - } + m_directWriteFontFileLoader = new DirectWriteFontFileLoader(); + m_directWriteFactory->RegisterFontFileLoader(m_directWriteFontFileLoader); } + } - ~CustomFontFileLoader() - { - if (m_directWriteFactory != nullptr && m_directWriteFontFileLoader != nullptr) - m_directWriteFactory->UnregisterFontFileLoader(m_directWriteFontFileLoader); + ~QCustomFontFileLoader() + { + clear(); - if (m_directWriteFactory != nullptr) - m_directWriteFactory->Release(); - } + if (m_directWriteFactory != nullptr && m_directWriteFontFileLoader != nullptr) + m_directWriteFactory->UnregisterFontFileLoader(m_directWriteFontFileLoader); - void addKey(const void *key, const QByteArray &fontData) - { - if (m_directWriteFontFileLoader != nullptr) - m_directWriteFontFileLoader->addKey(key, fontData); - } + if (m_directWriteFactory != nullptr) + m_directWriteFactory->Release(); + } - void removeKey(const void *key) - { - if (m_directWriteFontFileLoader != nullptr) - m_directWriteFontFileLoader->removeKey(key); - } + void addKey(const QByteArray &fontData) + { + if (m_directWriteFontFileLoader != nullptr) + m_directWriteFontFileLoader->addKey(fontData); + } - IDWriteFontFileLoader *loader() const - { - return m_directWriteFontFileLoader; - } + void removeKey(const void *key) + { + if (m_directWriteFontFileLoader != nullptr) + m_directWriteFontFileLoader->removeKey(key); + } + + IDWriteFontFileLoader *loader() const + { + return m_directWriteFontFileLoader; + } + + void clear() + { + if (m_directWriteFontFileLoader != nullptr) + m_directWriteFontFileLoader->clear(); + } + +private: + IDWriteFactory *m_directWriteFactory = nullptr; + DirectWriteFontFileLoader *m_directWriteFontFileLoader = nullptr; +}; - private: - IDWriteFactory *m_directWriteFactory = nullptr; - DirectWriteFontFileLoader *m_directWriteFontFileLoader = nullptr; - }; -} // Anonymous namespace #endif // directwrite && direct2d @@ -584,12 +565,27 @@ void QWindowsFontDatabaseBase::createDirectWriteFactory(IDWriteFactory **factory IUnknown *result = nullptr; # if QT_CONFIG(directwrite3) - DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory3), &result); + qCDebug(lcQpaFonts) << "Trying to create IDWriteFactory6"; + DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory6), &result); + + if (result == nullptr) { + qCDebug(lcQpaFonts) << "Trying to create IDWriteFactory5"; + DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory5), &result); + } + + if (result == nullptr) { + qCDebug(lcQpaFonts) << "Trying to create IDWriteFactory3"; + DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory3), &result); + } # endif - if (result == nullptr) + + if (result == nullptr) { + qCDebug(lcQpaFonts) << "Trying to create IDWriteFactory2"; DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory2), &result); + } if (result == nullptr) { + qCDebug(lcQpaFonts) << "Trying to create plain IDWriteFactory"; if (FAILED(DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), &result))) { qErrnoWarning("DWriteCreateFactory failed"); return; @@ -600,16 +596,9 @@ void QWindowsFontDatabaseBase::createDirectWriteFactory(IDWriteFactory **factory } #endif // directwrite && direct2d -static int s_defaultVerticalDPI = 96; // Native Pixels - int QWindowsFontDatabaseBase::defaultVerticalDPI() { - return s_defaultVerticalDPI; -} - -void QWindowsFontDatabaseBase::setDefaultVerticalDPI(int d) -{ - s_defaultVerticalDPI = d; + return 96; } LOGFONT QWindowsFontDatabaseBase::fontDefToLOGFONT(const QFontDef &request, const QString &faceName) @@ -724,36 +713,55 @@ HFONT QWindowsFontDatabaseBase::systemFont() QFont QWindowsFontDatabaseBase::systemDefaultFont() { // Qt 6: Obtain default GUI font (typically "Segoe UI, 9pt", see QTBUG-58610) - NONCLIENTMETRICS ncm; - ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT); - SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0); + NONCLIENTMETRICS ncm = {}; + ncm.cbSize = sizeof(ncm); + SystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0, defaultVerticalDPI()); const QFont systemFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfMessageFont); qCDebug(lcQpaFonts) << __FUNCTION__ << systemFont; return systemFont; } +void QWindowsFontDatabaseBase::invalidate() +{ +#if QT_CONFIG(directwrite) + m_fontFileLoader.reset(nullptr); +#endif +} + #if QT_CONFIG(directwrite) && QT_CONFIG(direct2d) -IDWriteFontFace *QWindowsFontDatabaseBase::createDirectWriteFace(const QByteArray &fontData) const +IDWriteFontFace *QWindowsFontDatabaseBase::createDirectWriteFace(const QByteArray &fontData) +{ + QList<IDWriteFontFace *> faces = createDirectWriteFaces(fontData, false); + Q_ASSERT(faces.size() <= 1); + + return faces.isEmpty() ? nullptr : faces.first(); +} + +QList<IDWriteFontFace *> QWindowsFontDatabaseBase::createDirectWriteFaces(const QByteArray &fontData, + bool queryVariations) const { + QList<IDWriteFontFace *> ret; QSharedPointer<QWindowsFontEngineData> fontEngineData = data(); if (fontEngineData->directWriteFactory == nullptr) { qCWarning(lcQpaFonts) << "DirectWrite factory not created in QWindowsFontDatabaseBase::createDirectWriteFace()"; - return nullptr; + return ret; } - CustomFontFileLoader fontFileLoader(fontEngineData->directWriteFactory); - fontFileLoader.addKey(this, fontData); + if (m_fontFileLoader == nullptr) + m_fontFileLoader.reset(new QCustomFontFileLoader(fontEngineData->directWriteFactory)); + + m_fontFileLoader->addKey(fontData); IDWriteFontFile *fontFile = nullptr; - const void *key = this; + const void *key = fontData.data(); HRESULT hres = fontEngineData->directWriteFactory->CreateCustomFontFileReference(&key, sizeof(void *), - fontFileLoader.loader(), + m_fontFileLoader->loader(), &fontFile); if (FAILED(hres)) { qErrnoWarning(hres, "%s: CreateCustomFontFileReference failed", __FUNCTION__); - return nullptr; + return ret; } BOOL isSupportedFontType; @@ -763,28 +771,75 @@ IDWriteFontFace *QWindowsFontDatabaseBase::createDirectWriteFace(const QByteArra fontFile->Analyze(&isSupportedFontType, &fontFileType, &fontFaceType, &numberOfFaces); if (!isSupportedFontType) { fontFile->Release(); - return nullptr; + return ret; + } + +#if QT_CONFIG(directwrite3) + IDWriteFactory5 *factory5 = nullptr; + if (queryVariations && SUCCEEDED(fontEngineData->directWriteFactory->QueryInterface(__uuidof(IDWriteFactory5), + reinterpret_cast<void **>(&factory5)))) { + + IDWriteFontSetBuilder1 *builder; + if (SUCCEEDED(factory5->CreateFontSetBuilder(&builder))) { + if (SUCCEEDED(builder->AddFontFile(fontFile))) { + IDWriteFontSet *fontSet; + if (SUCCEEDED(builder->CreateFontSet(&fontSet))) { + int count = fontSet->GetFontCount(); + qCDebug(lcQpaFonts) << "Found" << count << "variations in font file"; + for (int i = 0; i < count; ++i) { + IDWriteFontFaceReference *ref; + if (SUCCEEDED(fontSet->GetFontFaceReference(i, &ref))) { + IDWriteFontFace3 *face; + if (SUCCEEDED(ref->CreateFontFace(&face))) { + ret.append(face); + } + ref->Release(); + } + } + fontSet->Release(); + } + } + + builder->Release(); + } + + factory5->Release(); } +#else + Q_UNUSED(queryVariations); +#endif // ### Currently no support for .ttc, but we could easily return a list here. - IDWriteFontFace *directWriteFontFace = nullptr; - hres = fontEngineData->directWriteFactory->CreateFontFace(fontFaceType, - 1, - &fontFile, - 0, - DWRITE_FONT_SIMULATIONS_NONE, - &directWriteFontFace); - if (FAILED(hres)) { - qErrnoWarning(hres, "%s: CreateFontFace failed", __FUNCTION__); - fontFile->Release(); - return nullptr; + if (ret.isEmpty()) { + IDWriteFontFace *directWriteFontFace = nullptr; + hres = fontEngineData->directWriteFactory->CreateFontFace(fontFaceType, + 1, + &fontFile, + 0, + DWRITE_FONT_SIMULATIONS_NONE, + &directWriteFontFace); + if (FAILED(hres)) { + qErrnoWarning(hres, "%s: CreateFontFace failed", __FUNCTION__); + fontFile->Release(); + return ret; + } else { + ret.append(directWriteFontFace); + } } fontFile->Release(); - return directWriteFontFace; + + return ret; } #endif // directwrite && direct2d +QFontEngine *QWindowsFontDatabaseBase::fontEngine(const QFontDef &fontDef, void *handle) +{ + // This function was apparently not used before, and probably isn't now either, + // call the base implementation which just prints that it's not supported. + return QPlatformFontDatabase::fontEngine(fontDef, handle); +} + QFontEngine *QWindowsFontDatabaseBase::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) { QFontEngine *fontEngine = nullptr; @@ -794,7 +849,10 @@ QFontEngine *QWindowsFontDatabaseBase::fontEngine(const QByteArray &fontData, qr if (fontEngineData->directWriteFactory == nullptr) return nullptr; - IDWriteFontFace *directWriteFontFace = createDirectWriteFace(fontData); + IDWriteFontFace * directWriteFontFace = createDirectWriteFace(fontData); + if (directWriteFontFace == nullptr) + return nullptr; + fontEngine = new QWindowsFontEngineDirectWrite(directWriteFontFace, pixelSize, fontEngineData); @@ -836,7 +894,7 @@ QString QWindowsFontDatabaseBase::familyForStyleHint(QFont::StyleHint styleHint) default: break; } - return QStringLiteral("MS Shell Dlg 2"); + return QStringLiteral("Tahoma"); } // Creation functions @@ -940,7 +998,7 @@ QFontDef QWindowsFontDatabaseBase::sanitizeRequest(QFontDef request) const if (fam.isEmpty()) req.families[0] = QStringLiteral("MS Sans Serif"); - if (fam == QLatin1String("MS Sans Serif")) { + if (fam == "MS Sans Serif"_L1) { int height = -qRound(request.pixelSize); // MS Sans Serif has bearing problems in italic, and does not scale if (request.style == QFont::StyleItalic || (height > 18 && height != 24)) |