From b3e0732740d8fdace82d91973dac87261402604f Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 28 May 2020 08:20:55 +0200 Subject: Move windows font databases into QtGui Requires adapting a few config checks since cmake currently does not detect directwrite. Task-number: QTBUG-83255 Task-number: QTBUG-83931 Change-Id: I521f1924f701260b41dccbcecf87b19f08df5ccc Reviewed-by: Alexandru Croitor --- .../fontdatabases/.prev_CMakeLists.txt | 61 - src/platformsupport/fontdatabases/CMakeLists.txt | 61 - .../fontdatabases/fontdatabases.pro | 4 - .../windows/qwindowsdirectwritefontdatabase.cpp | 478 -------- .../windows/qwindowsdirectwritefontdatabase_p.h | 96 -- .../fontdatabases/windows/qwindowsfontdatabase.cpp | 1231 -------------------- .../windows/qwindowsfontdatabase_ft.cpp | 444 ------- .../windows/qwindowsfontdatabase_ft_p.h | 79 -- .../fontdatabases/windows/qwindowsfontdatabase_p.h | 174 --- .../windows/qwindowsfontdatabasebase.cpp | 985 ---------------- .../windows/qwindowsfontdatabasebase_p.h | 138 --- .../fontdatabases/windows/qwindowsfontengine.cpp | 1204 ------------------- .../fontdatabases/windows/qwindowsfontengine_p.h | 175 --- .../windows/qwindowsfontenginedirectwrite.cpp | 1030 ---------------- .../windows/qwindowsfontenginedirectwrite_p.h | 152 --- .../fontdatabases/windows/qwindowsnativeimage.cpp | 158 --- .../fontdatabases/windows/qwindowsnativeimage_p.h | 89 -- .../fontdatabases/windows/windows.pri | 43 - 18 files changed, 6602 deletions(-) delete mode 100644 src/platformsupport/fontdatabases/windows/qwindowsdirectwritefontdatabase.cpp delete mode 100644 src/platformsupport/fontdatabases/windows/qwindowsdirectwritefontdatabase_p.h delete mode 100644 src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp delete mode 100644 src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp delete mode 100644 src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft_p.h delete mode 100644 src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h delete mode 100644 src/platformsupport/fontdatabases/windows/qwindowsfontdatabasebase.cpp delete mode 100644 src/platformsupport/fontdatabases/windows/qwindowsfontdatabasebase_p.h delete mode 100644 src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp delete mode 100644 src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h delete mode 100644 src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp delete mode 100644 src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite_p.h delete mode 100644 src/platformsupport/fontdatabases/windows/qwindowsnativeimage.cpp delete mode 100644 src/platformsupport/fontdatabases/windows/qwindowsnativeimage_p.h delete mode 100644 src/platformsupport/fontdatabases/windows/windows.pri (limited to 'src/platformsupport/fontdatabases') diff --git a/src/platformsupport/fontdatabases/.prev_CMakeLists.txt b/src/platformsupport/fontdatabases/.prev_CMakeLists.txt index be84811a9e..a19195bc02 100644 --- a/src/platformsupport/fontdatabases/.prev_CMakeLists.txt +++ b/src/platformsupport/fontdatabases/.prev_CMakeLists.txt @@ -34,64 +34,3 @@ qt_extend_target(FontDatabaseSupport CONDITION QT_FEATURE_fontconfig LIBRARIES Fontconfig::Fontconfig ) - -qt_extend_target(FontDatabaseSupport CONDITION WIN32 - SOURCES - windows/qwindowsfontdatabase.cpp windows/qwindowsfontdatabase_p.h - windows/qwindowsfontdatabasebase.cpp windows/qwindowsfontdatabasebase_p.h - windows/qwindowsfontengine.cpp windows/qwindowsfontengine_p.h - windows/qwindowsnativeimage.cpp windows/qwindowsnativeimage_p.h - LIBRARIES - advapi32 - gdi32 - ole32 - user32 - PUBLIC_LIBRARIES - Qt::GuiPrivate -) - -qt_extend_target(FontDatabaseSupport CONDITION QT_FEATURE_freetype AND WIN32 - SOURCES - windows/qwindowsfontdatabase_ft.cpp windows/qwindowsfontdatabase_ft_p.h - LIBRARIES - WrapFreetype::WrapFreetype -) - -qt_extend_target(FontDatabaseSupport CONDITION QT_FEATURE_direct2d AND QT_FEATURE_directwrite AND WIN32 - SOURCES - windows/qwindowsfontenginedirectwrite.cpp windows/qwindowsfontenginedirectwrite_p.h - LIBRARIES - d2d1 -) - -qt_extend_target(FontDatabaseSupport CONDITION QT_FEATURE_direct2d AND QT_FEATURE_directwrite AND QT_FEATURE_directwrite3 AND WIN32 - SOURCES - windows/qwindowsdirectwritefontdatabase.cpp windows/qwindowsdirectwritefontdatabase_p.h - DEFINES - QT_USE_DIRECTWRITE2 - QT_USE_DIRECTWRITE3 - LIBRARIES - dwrite_3 -) - -qt_extend_target(FontDatabaseSupport CONDITION QT_FEATURE_direct2d AND QT_FEATURE_directwrite AND QT_FEATURE_directwrite2 AND WIN32 AND NOT QT_FEATURE_directwrite3 - DEFINES - QT_USE_DIRECTWRITE2 - LIBRARIES - dwrite_2 -) - -qt_extend_target(FontDatabaseSupport CONDITION QT_FEATURE_direct2d AND QT_FEATURE_directwrite AND WIN32 AND NOT QT_FEATURE_directwrite2 AND NOT QT_FEATURE_directwrite3 - LIBRARIES - dwrite -) - -qt_extend_target(FontDatabaseSupport CONDITION WIN32 AND (NOT QT_FEATURE_direct2d OR NOT QT_FEATURE_directwrite) - DEFINES - QT_NO_DIRECTWRITE -) - -qt_extend_target(FontDatabaseSupport CONDITION MINGW AND WIN32 - LIBRARIES - uuid -) diff --git a/src/platformsupport/fontdatabases/CMakeLists.txt b/src/platformsupport/fontdatabases/CMakeLists.txt index 8b37257ded..2f4519ec30 100644 --- a/src/platformsupport/fontdatabases/CMakeLists.txt +++ b/src/platformsupport/fontdatabases/CMakeLists.txt @@ -46,64 +46,3 @@ if(TARGET WrapFreetype::WrapFreetype) ) endif() # special case end - -qt_extend_target(FontDatabaseSupport CONDITION WIN32 - SOURCES - windows/qwindowsfontdatabase.cpp windows/qwindowsfontdatabase_p.h - windows/qwindowsfontdatabasebase.cpp windows/qwindowsfontdatabasebase_p.h - windows/qwindowsfontengine.cpp windows/qwindowsfontengine_p.h - windows/qwindowsnativeimage.cpp windows/qwindowsnativeimage_p.h - LIBRARIES - advapi32 - gdi32 - ole32 - user32 - PUBLIC_LIBRARIES - Qt::GuiPrivate -) - -qt_extend_target(FontDatabaseSupport CONDITION QT_FEATURE_freetype AND WIN32 - SOURCES - windows/qwindowsfontdatabase_ft.cpp windows/qwindowsfontdatabase_ft_p.h - LIBRARIES - WrapFreetype::WrapFreetype -) - -qt_extend_target(FontDatabaseSupport CONDITION QT_FEATURE_direct2d AND QT_FEATURE_directwrite AND WIN32 - SOURCES - windows/qwindowsfontenginedirectwrite.cpp windows/qwindowsfontenginedirectwrite_p.h - LIBRARIES - d2d1 -) - -qt_extend_target(FontDatabaseSupport CONDITION QT_FEATURE_direct2d AND QT_FEATURE_directwrite AND QT_FEATURE_directwrite3 AND WIN32 - SOURCES - windows/qwindowsdirectwritefontdatabase.cpp windows/qwindowsdirectwritefontdatabase_p.h - DEFINES - QT_USE_DIRECTWRITE2 - QT_USE_DIRECTWRITE3 - LIBRARIES - dwrite_3 -) - -qt_extend_target(FontDatabaseSupport CONDITION QT_FEATURE_direct2d AND QT_FEATURE_directwrite AND QT_FEATURE_directwrite2 AND WIN32 AND NOT QT_FEATURE_directwrite3 - DEFINES - QT_USE_DIRECTWRITE2 - LIBRARIES - dwrite_2 -) - -qt_extend_target(FontDatabaseSupport CONDITION QT_FEATURE_direct2d AND QT_FEATURE_directwrite AND WIN32 AND NOT QT_FEATURE_directwrite2 AND NOT QT_FEATURE_directwrite3 - LIBRARIES - dwrite -) - -qt_extend_target(FontDatabaseSupport CONDITION WIN32 AND (NOT QT_FEATURE_direct2d OR NOT QT_FEATURE_directwrite) - DEFINES - QT_NO_DIRECTWRITE -) - -qt_extend_target(FontDatabaseSupport CONDITION MINGW AND WIN32 - LIBRARIES - uuid -) diff --git a/src/platformsupport/fontdatabases/fontdatabases.pro b/src/platformsupport/fontdatabases/fontdatabases.pro index d597a0d6c2..5406291cea 100644 --- a/src/platformsupport/fontdatabases/fontdatabases.pro +++ b/src/platformsupport/fontdatabases/fontdatabases.pro @@ -15,8 +15,4 @@ qtConfig(fontconfig) { include($$PWD/fontconfig/fontconfig.pri) } -win32 { - include($$PWD/windows/windows.pri) -} - load(qt_module) diff --git a/src/platformsupport/fontdatabases/windows/qwindowsdirectwritefontdatabase.cpp b/src/platformsupport/fontdatabases/windows/qwindowsdirectwritefontdatabase.cpp deleted file mode 100644 index d2fb909dea..0000000000 --- a/src/platformsupport/fontdatabases/windows/qwindowsdirectwritefontdatabase.cpp +++ /dev/null @@ -1,478 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qwindowsdirectwritefontdatabase_p.h" -#include "qwindowsfontenginedirectwrite_p.h" -#include "qwindowsfontdatabase_p.h" - -#include -#include -#include -#include - -#include -#include - -QT_BEGIN_NAMESPACE - -#ifdef QT_USE_DIRECTWRITE3 - -// Defined in gui/text/qfontdatabase.cpp -Q_GUI_EXPORT QFontDatabase::WritingSystem qt_writing_system_for_script(int script); - -QWindowsDirectWriteFontDatabase::QWindowsDirectWriteFontDatabase() -{ - qCDebug(lcQpaFonts) << "Creating DirectWrite database"; -} - -QWindowsDirectWriteFontDatabase::~QWindowsDirectWriteFontDatabase() -{ - for (auto it = m_populatedFonts.begin(); it != m_populatedFonts.end(); ++it) - it.value()->Release(); -} - -QString QWindowsDirectWriteFontDatabase::localeString(IDWriteLocalizedStrings *names, - wchar_t localeName[]) -{ - uint index; - BOOL exists; - if (SUCCEEDED(names->FindLocaleName(localeName, &index, &exists)) && exists) { - uint length; - if (SUCCEEDED(names->GetStringLength(index, &length)) && length > 0) { - QVarLengthArray buffer(int(length) + 1); - if (SUCCEEDED(names->GetString(index, buffer.data(), length + 1))) - return QString::fromWCharArray(buffer.data()); - } - } - - return QString(); -} - -static QFont::Stretch fromDirectWriteStretch(DWRITE_FONT_STRETCH stretch) -{ - switch (stretch) { - case DWRITE_FONT_STRETCH_ULTRA_CONDENSED: return QFont::UltraCondensed; - case DWRITE_FONT_STRETCH_EXTRA_CONDENSED: return QFont::ExtraCondensed; - case DWRITE_FONT_STRETCH_CONDENSED: return QFont::Condensed; - case DWRITE_FONT_STRETCH_SEMI_CONDENSED: return QFont::SemiCondensed; - case DWRITE_FONT_STRETCH_NORMAL: return QFont::Unstretched; - case DWRITE_FONT_STRETCH_SEMI_EXPANDED: return QFont::SemiExpanded; - case DWRITE_FONT_STRETCH_EXPANDED: return QFont::Expanded; - case DWRITE_FONT_STRETCH_EXTRA_EXPANDED: return QFont::ExtraExpanded; - case DWRITE_FONT_STRETCH_ULTRA_EXPANDED: return QFont::UltraExpanded; - default: return QFont::AnyStretch; - } -} - -static QFont::Weight fromDirectWriteWeight(DWRITE_FONT_WEIGHT weight) -{ - return QPlatformFontDatabase::weightFromInteger(int(weight)); -} - -static DWRITE_FONT_STYLE toDirectWriteStyle(QFont::Style style) -{ - switch (style) { - case QFont::StyleNormal: return DWRITE_FONT_STYLE_NORMAL; - case QFont::StyleOblique: return DWRITE_FONT_STYLE_OBLIQUE; - case QFont::StyleItalic: return DWRITE_FONT_STYLE_ITALIC; - default: return DWRITE_FONT_STYLE_NORMAL; - } -} - -static QFont::Style fromDirectWriteStyle(DWRITE_FONT_STYLE style) -{ - switch (style) { - case DWRITE_FONT_STYLE_NORMAL: return QFont::StyleNormal; - case DWRITE_FONT_STYLE_OBLIQUE: return QFont::StyleOblique; - case DWRITE_FONT_STYLE_ITALIC: return QFont::StyleItalic; - default: return QFont::StyleNormal; - } -} - -void QWindowsDirectWriteFontDatabase::populateFamily(const QString &familyName) -{ - auto it = m_populatedFonts.find(familyName); - IDWriteFontFamily *fontFamily = it != m_populatedFonts.end() ? it.value() : nullptr; - if (fontFamily == nullptr) { - qCWarning(lcQpaFonts) << "Cannot find" << familyName << "in list of fonts"; - return; - } - - qCDebug(lcQpaFonts) << "Populate family:" << familyName; - - wchar_t defaultLocale[LOCALE_NAME_MAX_LENGTH]; - bool hasDefaultLocale = GetUserDefaultLocaleName(defaultLocale, LOCALE_NAME_MAX_LENGTH) != 0; - wchar_t englishLocale[] = L"en-us"; - - static const int SMOOTH_SCALABLE = 0xffff; - const QString foundryName; // No such concept. - const bool scalable = true; - const bool antialias = false; - const int size = SMOOTH_SCALABLE; - - IDWriteFontList *matchingFonts; - if (SUCCEEDED(fontFamily->GetMatchingFonts(DWRITE_FONT_WEIGHT_REGULAR, - DWRITE_FONT_STRETCH_NORMAL, - DWRITE_FONT_STYLE_NORMAL, - &matchingFonts))) { - for (uint j = 0; j < matchingFonts->GetFontCount(); ++j) { - IDWriteFont *font; - if (SUCCEEDED(matchingFonts->GetFont(j, &font))) { - IDWriteFont1 *font1 = nullptr; - if (!SUCCEEDED(font->QueryInterface(__uuidof(IDWriteFont1), - reinterpret_cast(&font1)))) { - qCWarning(lcQpaFonts) << "COM object does not support IDWriteFont1"; - continue; - } - - QString defaultLocaleFamilyName; - QString englishLocaleFamilyName; - - IDWriteFontFamily *fontFamily2; - if (SUCCEEDED(font1->GetFontFamily(&fontFamily2))) { - IDWriteLocalizedStrings *names; - if (SUCCEEDED(fontFamily2->GetFamilyNames(&names))) { - defaultLocaleFamilyName = hasDefaultLocale ? localeString(names, defaultLocale) : QString(); - englishLocaleFamilyName = localeString(names, englishLocale); - - names->Release(); - } - - fontFamily2->Release(); - } - - if (defaultLocaleFamilyName.isEmpty() && englishLocaleFamilyName.isEmpty()) - englishLocaleFamilyName = familyName; - - { - IDWriteLocalizedStrings *names; - if (SUCCEEDED(font1->GetFaceNames(&names))) { - QString defaultLocaleStyleName = hasDefaultLocale ? localeString(names, defaultLocale) : QString(); - QString englishLocaleStyleName = localeString(names, englishLocale); - - QFont::Stretch stretch = fromDirectWriteStretch(font1->GetStretch()); - QFont::Style style = fromDirectWriteStyle(font1->GetStyle()); - QFont::Weight weight = fromDirectWriteWeight(font1->GetWeight()); - bool fixed = font1->IsMonospacedFont(); - - qCDebug(lcQpaFonts) << "Family" << familyName << "has english variant" << englishLocaleStyleName << ", in default locale:" << defaultLocaleStyleName << stretch << style << weight << fixed; - - IDWriteFontFace *face = nullptr; - if (SUCCEEDED(font->CreateFontFace(&face))) { - QSupportedWritingSystems writingSystems; - - const void *tableData = nullptr; - UINT32 tableSize; - void *tableContext = nullptr; - BOOL exists; - HRESULT hr = face->TryGetFontTable(qbswap(MAKE_TAG('O','S','/','2')), - &tableData, - &tableSize, - &tableContext, - &exists); - if (SUCCEEDED(hr) && exists) { - writingSystems = QPlatformFontDatabase::writingSystemsFromOS2Table(reinterpret_cast(tableData), tableSize); - } else { // Fall back to checking first character of each Unicode range in font (may include too many writing systems) - quint32 rangeCount; - hr = font1->GetUnicodeRanges(0, nullptr, &rangeCount); - - if (rangeCount > 0) { - QVarLengthArray ranges(rangeCount); - - hr = font1->GetUnicodeRanges(rangeCount, ranges.data(), &rangeCount); - if (SUCCEEDED(hr)) { - for (uint i = 0; i < rangeCount; ++i) { - QChar::Script script = QChar::script(ranges.at(i).first); - - QFontDatabase::WritingSystem writingSystem = qt_writing_system_for_script(script); - - if (writingSystem > QFontDatabase::Any && writingSystem < QFontDatabase::WritingSystemsCount) - writingSystems.setSupported(writingSystem); - } - } else { - const QString errorString = qt_error_string(int(hr)); - qCWarning(lcQpaFonts) << "Failed to get unicode ranges for font" << englishLocaleFamilyName << englishLocaleStyleName << ":" << errorString; - } - } - } - - if (!englishLocaleStyleName.isEmpty() || defaultLocaleStyleName.isEmpty()) { - qCDebug(lcQpaFonts) << "Font" << englishLocaleFamilyName << englishLocaleStyleName << "supports writing systems:" << writingSystems; - - QPlatformFontDatabase::registerFont(englishLocaleFamilyName, englishLocaleStyleName, QString(), weight, style, stretch, antialias, scalable, size, fixed, writingSystems, face); - face->AddRef(); - } - - if (!defaultLocaleFamilyName.isEmpty() && defaultLocaleFamilyName != englishLocaleFamilyName) { - QPlatformFontDatabase::registerFont(defaultLocaleFamilyName, defaultLocaleStyleName, QString(), weight, style, stretch, antialias, scalable, size, fixed, writingSystems, face); - face->AddRef(); - } - - face->Release(); - } - - names->Release(); - } - } - - font1->Release(); - font->Release(); - } - } - - matchingFonts->Release(); - } -} - -QFontEngine *QWindowsDirectWriteFontDatabase::fontEngine(const QFontDef &fontDef, void *handle) -{ - IDWriteFontFace *face = reinterpret_cast(handle); - Q_ASSERT(face != nullptr); - - QWindowsFontEngineDirectWrite *fontEngine = new QWindowsFontEngineDirectWrite(face, fontDef.pixelSize, data()); - fontEngine->initFontInfo(fontDef, defaultVerticalDPI()); - - return fontEngine; -} - -QStringList QWindowsDirectWriteFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const -{ - QStringList result; - result.append(familyForStyleHint(styleHint)); - result.append(extraTryFontsForFamily(family)); - result.append(QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script)); - - qCDebug(lcQpaFonts) << __FUNCTION__ << family << style << styleHint - << script << result; - return result; -} - -QStringList QWindowsDirectWriteFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName, QFontDatabasePrivate::ApplicationFont *applicationFont) -{ - qCDebug(lcQpaFonts) << "Adding application font" << fileName; - - QByteArray loadedData = fontData; - if (loadedData.isEmpty()) { - QFile file(fileName); - if (!file.open(QIODevice::ReadOnly)) { - qCWarning(lcQpaFonts) << "Cannot open" << fileName << "for reading."; - return QStringList(); - } - loadedData = file.readAll(); - } - - IDWriteFontFace *face = createDirectWriteFace(loadedData); - if (face == nullptr) { - qCWarning(lcQpaFonts) << "Failed to create DirectWrite face from font data. Font may be unsupported."; - return QStringList(); - } - - wchar_t defaultLocale[LOCALE_NAME_MAX_LENGTH]; - bool hasDefaultLocale = GetUserDefaultLocaleName(defaultLocale, LOCALE_NAME_MAX_LENGTH) != 0; - wchar_t englishLocale[] = L"en-us"; - - static const int SMOOTH_SCALABLE = 0xffff; - const QString foundryName; // No such concept. - const bool scalable = true; - const bool antialias = false; - const int size = SMOOTH_SCALABLE; - - QSupportedWritingSystems writingSystems; - writingSystems.setSupported(QFontDatabase::Any); - writingSystems.setSupported(QFontDatabase::Latin); - - QStringList ret; - IDWriteFontFace3 *face3 = nullptr; - if (SUCCEEDED(face->QueryInterface(__uuidof(IDWriteFontFace3), - reinterpret_cast(&face3)))) { - QString defaultLocaleFamilyName; - QString englishLocaleFamilyName; - - IDWriteLocalizedStrings *names; - if (SUCCEEDED(face3->GetFamilyNames(&names))) { - defaultLocaleFamilyName = hasDefaultLocale ? localeString(names, defaultLocale) : QString(); - englishLocaleFamilyName = localeString(names, englishLocale); - - names->Release(); - } - - QString defaultLocaleStyleName; - QString englishLocaleStyleName; - if (SUCCEEDED(face3->GetFaceNames(&names))) { - defaultLocaleStyleName = hasDefaultLocale ? localeString(names, defaultLocale) : QString(); - englishLocaleStyleName = localeString(names, englishLocale); - - names->Release(); - } - - QFont::Stretch stretch = fromDirectWriteStretch(face3->GetStretch()); - QFont::Style style = fromDirectWriteStyle(face3->GetStyle()); - QFont::Weight weight = fromDirectWriteWeight(face3->GetWeight()); - bool fixed = face3->IsMonospacedFont(); - - qCDebug(lcQpaFonts) << "\tFont names:" << englishLocaleFamilyName << ", " << defaultLocaleFamilyName - << ", style names:" << englishLocaleStyleName << ", " << defaultLocaleStyleName - << ", stretch:" << stretch - << ", style:" << style - << ", weight:" << weight - << ", fixed:" << fixed; - - if (!englishLocaleFamilyName.isEmpty()) { - if (applicationFont != nullptr) { - QFontDatabasePrivate::ApplicationFont::Properties properties; - properties.style = style; - properties.weight = weight; - properties.familyName = englishLocaleFamilyName; - properties.styleName = englishLocaleStyleName; - applicationFont->properties.append(properties); - } - - ret.append(englishLocaleFamilyName); - QPlatformFontDatabase::registerFont(englishLocaleFamilyName, englishLocaleStyleName, QString(), weight, style, stretch, antialias, scalable, size, fixed, writingSystems, face); - face->AddRef(); - } - - if (!defaultLocaleFamilyName.isEmpty() && defaultLocaleFamilyName != englishLocaleFamilyName) { - if (applicationFont != nullptr) { - QFontDatabasePrivate::ApplicationFont::Properties properties; - properties.style = style; - properties.weight = weight; - properties.familyName = englishLocaleFamilyName; - properties.styleName = englishLocaleStyleName; - applicationFont->properties.append(properties); - } - - ret.append(defaultLocaleFamilyName); - QPlatformFontDatabase::registerFont(defaultLocaleFamilyName, defaultLocaleStyleName, QString(), weight, style, stretch, antialias, scalable, size, fixed, writingSystems, face); - face->AddRef(); - } - - face3->Release(); - } else { - qCWarning(lcQpaFonts) << "Unable to query IDWriteFontFace3 interface from font face."; - } - - face->Release(); - - return ret; -} - -void QWindowsDirectWriteFontDatabase::releaseHandle(void *handle) -{ - IDWriteFontFace *face = reinterpret_cast(handle); - face->Release(); -} - -bool QWindowsDirectWriteFontDatabase::fontsAlwaysScalable() const -{ - return true; -} - -bool QWindowsDirectWriteFontDatabase::isPrivateFontFamily(const QString &family) const -{ - Q_UNUSED(family); - return false; -} - -void QWindowsDirectWriteFontDatabase::populateFontDatabase() -{ - wchar_t defaultLocale[LOCALE_NAME_MAX_LENGTH]; - bool hasDefaultLocale = GetUserDefaultLocaleName(defaultLocale, LOCALE_NAME_MAX_LENGTH) != 0; - wchar_t englishLocale[] = L"en-us"; - - QString defaultFontName = defaultFont().family(); - QString systemDefaultFontName = systemDefaultFont().family(); - - IDWriteFontCollection *fontCollection; - if (SUCCEEDED(data()->directWriteFactory->GetSystemFontCollection(&fontCollection))) { - for (uint i = 0; i < fontCollection->GetFontFamilyCount(); ++i) { - IDWriteFontFamily *fontFamily; - if (SUCCEEDED(fontCollection->GetFontFamily(i, &fontFamily))) { - QString defaultLocaleName; - QString englishLocaleName; - - IDWriteLocalizedStrings *names; - if (SUCCEEDED(fontFamily->GetFamilyNames(&names))) { - if (hasDefaultLocale) - defaultLocaleName = localeString(names, defaultLocale); - - englishLocaleName = localeString(names, englishLocale); - } - - qCDebug(lcQpaFonts) << "Registering font, english name = " << englishLocaleName << ", name in current locale = " << defaultLocaleName; - if (!defaultLocaleName.isEmpty()) { - registerFontFamily(defaultLocaleName); - m_populatedFonts.insert(defaultLocaleName, fontFamily); - fontFamily->AddRef(); - - if (defaultLocaleName == defaultFontName && defaultFontName != systemDefaultFontName) { - qDebug(lcQpaFonts) << "Adding default font" << systemDefaultFontName << "as alternative to" << defaultLocaleName; - - m_populatedFonts.insert(systemDefaultFontName, fontFamily); - fontFamily->AddRef(); - } - } - - if (!englishLocaleName.isEmpty() && englishLocaleName != defaultLocaleName) { - registerFontFamily(englishLocaleName); - m_populatedFonts.insert(englishLocaleName, fontFamily); - fontFamily->AddRef(); - - if (englishLocaleName == defaultFontName && defaultFontName != systemDefaultFontName) { - qDebug(lcQpaFonts) << "Adding default font" << systemDefaultFontName << "as alternative to" << englishLocaleName; - - m_populatedFonts.insert(systemDefaultFontName, fontFamily); - fontFamily->AddRef(); - } - } - - fontFamily->Release(); - } - } - } -} - -QFont QWindowsDirectWriteFontDatabase::defaultFont() const -{ - return QFont(QStringLiteral("Segoe UI")); -} - -#endif // QT_USE_DIRECTWRITE3 - -QT_END_NAMESPACE diff --git a/src/platformsupport/fontdatabases/windows/qwindowsdirectwritefontdatabase_p.h b/src/platformsupport/fontdatabases/windows/qwindowsdirectwritefontdatabase_p.h deleted file mode 100644 index f46c57e6a5..0000000000 --- a/src/platformsupport/fontdatabases/windows/qwindowsdirectwritefontdatabase_p.h +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef QWINDOWSDIRECTWRITEFONTDATABASE_P_H -#define QWINDOWSDIRECTWRITEFONTDATABASE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qwindowsfontdatabasebase_p.h" - -#include -#include - -struct IDWriteFactory; -struct IDWriteFont; -struct IDWriteFontFamily; -struct IDWriteLocalizedStrings; - -QT_BEGIN_NAMESPACE - -#ifdef QT_USE_DIRECTWRITE3 - -class QWindowsDirectWriteFontDatabase : public QWindowsFontDatabaseBase -{ - Q_DISABLE_COPY_MOVE(QWindowsDirectWriteFontDatabase) -public: - QWindowsDirectWriteFontDatabase(); - ~QWindowsDirectWriteFontDatabase() override; - - void populateFontDatabase() override; - void populateFamily(const QString &familyName) override; - QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) override; - QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const override; - QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName, QFontDatabasePrivate::ApplicationFont *font = nullptr) override; - void releaseHandle(void *handle) override; - QFont defaultFont() const override; - - bool fontsAlwaysScalable() const override; - bool isPrivateFontFamily(const QString &family) const override; - -private: - static QString localeString(IDWriteLocalizedStrings *names, wchar_t localeName[]); - - QHash m_populatedFonts; -}; - -#endif // QT_USE_DIRECTWRITE3 - -QT_END_NAMESPACE - -#endif // QWINDOWSDIRECTWRITEFONTDATABASE_P_H diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp deleted file mode 100644 index 2beb35eb03..0000000000 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp +++ /dev/null @@ -1,1231 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#include "qwindowsfontdatabase_p.h" -#include "qwindowsfontdatabase_ft_p.h" // for default font -#include "qwindowsfontengine_p.h" -#include "qwindowsfontenginedirectwrite_p.h" -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#if !defined(QT_NO_DIRECTWRITE) -# if defined(QT_USE_DIRECTWRITE2) -# include -# else -# include -# endif -# include -# include "qwindowsdirectwritefontdatabase_p.h" -#endif - -QT_BEGIN_NAMESPACE - -Q_LOGGING_CATEGORY(lcQpaFonts, "qt.qpa.fonts") - -#ifndef QT_NO_DIRECTWRITE -// ### fixme: Consider direct linking of dwrite.dll once Windows Vista pre SP2 is dropped (QTBUG-49711) - -typedef HRESULT (WINAPI *DWriteCreateFactoryType)(DWRITE_FACTORY_TYPE, const IID &, IUnknown **); - -static inline bool useDirectWrite(QFont::HintingPreference hintingPreference, - const QString &familyName = QString(), - bool isColorFont = false) -{ - const unsigned options = QWindowsFontDatabase::fontOptions(); - if (Q_UNLIKELY(options & QWindowsFontDatabase::DontUseDirectWriteFonts)) - return false; - - // At some scales, GDI will misrender the MingLiU font, so we force use of - // DirectWrite to work around the issue. - if (Q_UNLIKELY(familyName.startsWith(QLatin1String("MingLiU")))) - return true; - - if (isColorFont) - return (options & QWindowsFontDatabase::DontUseColorFonts) == 0; - - return hintingPreference == QFont::PreferNoHinting - || hintingPreference == QFont::PreferVerticalHinting - || (QHighDpiScaling::isActive() && hintingPreference == QFont::PreferDefaultHinting); -} -#endif // !QT_NO_DIRECTWRITE - -/*! - \struct QWindowsFontEngineData - \brief Static constant data shared by the font engines. -*/ - -QWindowsFontEngineData::QWindowsFontEngineData() - : fontSmoothingGamma(QWindowsFontDatabase::fontSmoothingGamma()) -{ - // from qapplication_win.cpp - UINT result = 0; - if (SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0)) - clearTypeEnabled = (result == FE_FONTSMOOTHINGCLEARTYPE); - - const qreal gray_gamma = 2.31; - for (int i=0; i<256; ++i) - pow_gamma[i] = uint(qRound(qPow(i / qreal(255.), gray_gamma) * 2047)); - - HDC displayDC = GetDC(0); - hdc = CreateCompatibleDC(displayDC); - ReleaseDC(0, displayDC); -} - -unsigned QWindowsFontDatabase::m_fontOptions = 0; - -void QWindowsFontDatabase::setFontOptions(unsigned options) -{ - m_fontOptions = options & (QWindowsFontDatabase::DontUseDirectWriteFonts | - QWindowsFontDatabase::DontUseColorFonts); -} - -unsigned QWindowsFontDatabase::fontOptions() -{ - return m_fontOptions; -} - -qreal QWindowsFontDatabase::fontSmoothingGamma() -{ - int winSmooth; - qreal result = 1; - if (SystemParametersInfo(0x200C /* SPI_GETFONTSMOOTHINGCONTRAST */, 0, &winSmooth, 0)) - result = qreal(winSmooth) / qreal(1000.0); - - // Safeguard ourselves against corrupt registry values... - if (result > 5 || result < 1) - result = qreal(1.4); - return result; -} - -/*! - \class QWindowsFontDatabase - \brief Font database for Windows - - \note The Qt 4.8 WIndows font database employed a mechanism of - delayed population of the database again passing a font name - to EnumFontFamiliesEx(), working around the fact that - EnumFontFamiliesEx() does not list all fonts by default. - This should be introduced to QPA as well? - - \internal -*/ - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const QFontDef &def) -{ - QDebugStateSaver saver(d); - d.nospace(); - d.noquote(); - d << "QFontDef(Family=\"" << def.family << '"'; - if (!def.styleName.isEmpty()) - d << ", stylename=" << def.styleName; - d << ", pointsize=" << def.pointSize << ", pixelsize=" << def.pixelSize - << ", styleHint=" << def.styleHint << ", weight=" << def.weight - << ", stretch=" << def.stretch << ", hintingPreference=" - << def.hintingPreference << ')'; - return d; -} - -QDebug operator<<(QDebug d, const LOGFONT &lf) -{ - QDebugStateSaver saver(d); - d.nospace(); - d.noquote(); - d << "LOGFONT(\"" << QString::fromWCharArray(lf.lfFaceName) - << "\", lfWidth=" << lf.lfWidth << ", lfHeight=" << lf.lfHeight << ')'; - return d; -} -#endif // !QT_NO_DEBUG_STREAM - -static inline QFontDatabase::WritingSystem writingSystemFromCharSet(uchar charSet) -{ - switch (charSet) { - case ANSI_CHARSET: - case EASTEUROPE_CHARSET: - case BALTIC_CHARSET: - case TURKISH_CHARSET: - return QFontDatabase::Latin; - case GREEK_CHARSET: - return QFontDatabase::Greek; - case RUSSIAN_CHARSET: - return QFontDatabase::Cyrillic; - case HEBREW_CHARSET: - return QFontDatabase::Hebrew; - case ARABIC_CHARSET: - return QFontDatabase::Arabic; - case THAI_CHARSET: - return QFontDatabase::Thai; - case GB2312_CHARSET: - return QFontDatabase::SimplifiedChinese; - case CHINESEBIG5_CHARSET: - return QFontDatabase::TraditionalChinese; - case SHIFTJIS_CHARSET: - return QFontDatabase::Japanese; - case HANGUL_CHARSET: - case JOHAB_CHARSET: - return QFontDatabase::Korean; - case VIETNAMESE_CHARSET: - return QFontDatabase::Vietnamese; - case SYMBOL_CHARSET: - return QFontDatabase::Symbol; - default: - break; - } - return QFontDatabase::Any; -} - -#ifdef MAKE_TAG -#undef MAKE_TAG -#endif -// GetFontData expects the tags in little endian ;( -#define MAKE_TAG(ch1, ch2, ch3, ch4) (\ - (((quint32)(ch4)) << 24) | \ - (((quint32)(ch3)) << 16) | \ - (((quint32)(ch2)) << 8) | \ - ((quint32)(ch1)) \ - ) - -bool qt_localizedName(const QString &name) -{ - const QChar *c = name.unicode(); - for (int i = 0; i < name.length(); ++i) { - if (c[i].unicode() >= 0x100) - return true; - } - return false; -} - -namespace { - -static QString readName(bool unicode, const uchar *string, int length) -{ - QString out; - if (unicode) { - // utf16 - - length /= 2; - out.resize(length); - QChar *uc = out.data(); - for (int i = 0; i < length; ++i) - uc[i] = qt_getUShort(string + 2*i); - } else { - // Apple Roman - - out.resize(length); - QChar *uc = out.data(); - for (int i = 0; i < length; ++i) - uc[i] = QLatin1Char(char(string[i])); - } - return out; -} - -enum FieldTypeValue { - FamilyId = 1, - StyleId = 2, - PreferredFamilyId = 16, - PreferredStyleId = 17, -}; - -enum PlatformFieldValue { - PlatformId_Unicode = 0, - PlatformId_Apple = 1, - PlatformId_Microsoft = 3 -}; - -QFontNames qt_getCanonicalFontNames(const uchar *table, quint32 bytes) -{ - QFontNames out; - const int NameRecordSize = 12; - const int MS_LangIdEnglish = 0x009; - - // get the name table - quint16 count; - quint16 string_offset; - const unsigned char *names; - - if (bytes < 8) - return out; - - if (qt_getUShort(table) != 0) - return out; - - count = qt_getUShort(table + 2); - string_offset = qt_getUShort(table + 4); - names = table + 6; - - if (string_offset >= bytes || 6 + count*NameRecordSize > string_offset) - return out; - - enum PlatformIdType { - NotFound = 0, - Unicode = 1, - Apple = 2, - Microsoft = 3 - }; - - PlatformIdType idStatus[4] = { NotFound, NotFound, NotFound, NotFound }; - int ids[4] = { -1, -1, -1, -1 }; - - for (int i = 0; i < count; ++i) { - // search for the correct name entries - - quint16 platform_id = qt_getUShort(names + i*NameRecordSize); - quint16 encoding_id = qt_getUShort(names + 2 + i*NameRecordSize); - quint16 language_id = qt_getUShort(names + 4 + i*NameRecordSize); - quint16 name_id = qt_getUShort(names + 6 + i*NameRecordSize); - - PlatformIdType *idType = nullptr; - int *id = nullptr; - - switch (name_id) { - case FamilyId: - idType = &idStatus[0]; - id = &ids[0]; - break; - case StyleId: - idType = &idStatus[1]; - id = &ids[1]; - break; - case PreferredFamilyId: - idType = &idStatus[2]; - id = &ids[2]; - break; - case PreferredStyleId: - idType = &idStatus[3]; - id = &ids[3]; - break; - default: - continue; - } - - quint16 length = qt_getUShort(names + 8 + i*NameRecordSize); - quint16 offset = qt_getUShort(names + 10 + i*NameRecordSize); - if (DWORD(string_offset + offset + length) > bytes) - continue; - - if ((platform_id == PlatformId_Microsoft - && (encoding_id == 0 || encoding_id == 1)) - && ((language_id & 0x3ff) == MS_LangIdEnglish - || *idType < Microsoft)) { - *id = i; - *idType = Microsoft; - } - // not sure if encoding id 4 for Unicode is utf16 or ucs4... - else if (platform_id == PlatformId_Unicode && encoding_id < 4 && *idType < Unicode) { - *id = i; - *idType = Unicode; - } - else if (platform_id == PlatformId_Apple && encoding_id == 0 && language_id == 0 && *idType < Apple) { - *id = i; - *idType = Apple; - } - } - - QString strings[4]; - for (int i = 0; i < 4; ++i) { - if (idStatus[i] == NotFound) - continue; - int id = ids[i]; - quint16 length = qt_getUShort(names + 8 + id * NameRecordSize); - quint16 offset = qt_getUShort(names + 10 + id * NameRecordSize); - const unsigned char *string = table + string_offset + offset; - strings[i] = readName(idStatus[i] != Apple, string, length); - } - - out.name = strings[0]; - out.style = strings[1]; - out.preferredName = strings[2]; - out.preferredStyle = strings[3]; - return out; -} - -} // namespace - -QString qt_getEnglishName(const QString &familyName, bool includeStyle) -{ - QString i18n_name; - QString faceName = familyName; - faceName.truncate(LF_FACESIZE - 1); - - HDC hdc = GetDC( 0 ); - LOGFONT lf; - memset(&lf, 0, sizeof(LOGFONT)); - faceName.toWCharArray(lf.lfFaceName); - lf.lfFaceName[faceName.size()] = 0; - lf.lfCharSet = DEFAULT_CHARSET; - HFONT hfont = CreateFontIndirect(&lf); - - if (!hfont) { - ReleaseDC(0, hdc); - return QString(); - } - - HGDIOBJ oldobj = SelectObject( hdc, hfont ); - - const DWORD name_tag = MAKE_TAG( 'n', 'a', 'm', 'e' ); - - // get the name table - unsigned char *table = 0; - - DWORD bytes = GetFontData( hdc, name_tag, 0, 0, 0 ); - if ( bytes == GDI_ERROR ) { - // ### Unused variable - // int err = GetLastError(); - goto error; - } - - table = new unsigned char[bytes]; - GetFontData(hdc, name_tag, 0, table, bytes); - if ( bytes == GDI_ERROR ) - goto error; - - { - const QFontNames names = qt_getCanonicalFontNames(table, bytes); - i18n_name = names.name; - if (includeStyle) - i18n_name += QLatin1Char(' ') + names.style; - } -error: - delete [] table; - SelectObject( hdc, oldobj ); - DeleteObject( hfont ); - ReleaseDC( 0, hdc ); - - //qDebug("got i18n name of '%s' for font '%s'", i18n_name.latin1(), familyName.toLocal8Bit().data()); - return i18n_name; -} - -// Note this duplicates parts of qt_getEnglishName, we should try to unify the two functions. -QFontNames qt_getCanonicalFontNames(const LOGFONT &lf) -{ - QFontNames fontNames; - HDC hdc = GetDC(0); - HFONT hfont = CreateFontIndirect(&lf); - - if (!hfont) { - ReleaseDC(0, hdc); - return fontNames; - } - - HGDIOBJ oldobj = SelectObject(hdc, hfont); - - // get the name table - QByteArray table; - const DWORD name_tag = MAKE_TAG('n', 'a', 'm', 'e'); - DWORD bytes = GetFontData(hdc, name_tag, 0, 0, 0); - if (bytes != GDI_ERROR) { - table.resize(bytes); - - if (GetFontData(hdc, name_tag, 0, table.data(), bytes) != GDI_ERROR) - fontNames = qt_getCanonicalFontNames(reinterpret_cast(table.constData()), bytes); - } - - SelectObject(hdc, oldobj); - DeleteObject(hfont); - ReleaseDC(0, hdc); - - return fontNames; -} - -static QChar *createFontFile(const QString &faceName) -{ - QChar *faceNamePtr = nullptr; - if (!faceName.isEmpty()) { - const int nameLength = qMin(faceName.length(), LF_FACESIZE - 1); - faceNamePtr = new QChar[nameLength + 1]; - memcpy(static_cast(faceNamePtr), faceName.utf16(), sizeof(wchar_t) * nameLength); - faceNamePtr[nameLength] = 0; - } - return faceNamePtr; -} - -namespace { - struct StoreFontPayload { - StoreFontPayload(const QString &family, - QWindowsFontDatabase *fontDatabase) - : populatedFontFamily(family) - , windowsFontDatabase(fontDatabase) - {} - - QString populatedFontFamily; - QSet foundFontAndStyles; - QWindowsFontDatabase *windowsFontDatabase; - }; -} - -static bool addFontToDatabase(QString familyName, - QString styleName, - const LOGFONT &logFont, - const TEXTMETRIC *textmetric, - const FONTSIGNATURE *signature, - int type, - StoreFontPayload *sfp) -{ - // the "@family" fonts are just the same as "family". Ignore them. - if (familyName.isEmpty() || familyName.at(0) == QLatin1Char('@') || familyName.startsWith(QLatin1String("WST_"))) - return false; - - uchar charSet = logFont.lfCharSet; - - static const int SMOOTH_SCALABLE = 0xffff; - const QString foundryName; // No such concept. - const bool fixed = !(textmetric->tmPitchAndFamily & TMPF_FIXED_PITCH); - const bool ttf = (textmetric->tmPitchAndFamily & TMPF_TRUETYPE); - const bool scalable = textmetric->tmPitchAndFamily & (TMPF_VECTOR|TMPF_TRUETYPE); - const int size = scalable ? SMOOTH_SCALABLE : textmetric->tmHeight; - const QFont::Style style = textmetric->tmItalic ? QFont::StyleItalic : QFont::StyleNormal; - const bool antialias = false; - const QFont::Weight weight = QPlatformFontDatabase::weightFromInteger(textmetric->tmWeight); - const QFont::Stretch stretch = QFont::Unstretched; - -#ifndef QT_NO_DEBUG_OUTPUT - if (lcQpaFonts().isDebugEnabled()) { - QString message; - QTextStream str(&message); - str << __FUNCTION__ << ' ' << familyName << ' ' << charSet << " TTF=" << ttf; - if (type & DEVICE_FONTTYPE) - str << " DEVICE"; - if (type & RASTER_FONTTYPE) - str << " RASTER"; - if (type & TRUETYPE_FONTTYPE) - str << " TRUETYPE"; - str << " scalable=" << scalable << " Size=" << size - << " Style=" << style << " Weight=" << weight - << " stretch=" << stretch; - qCDebug(lcQpaFonts) << message; - } -#endif - QString englishName; - QString faceName; - - QString subFamilyName; - QString subFamilyStyle; - // Look-up names registered in the font - QFontNames canonicalNames = qt_getCanonicalFontNames(logFont); - if (qt_localizedName(familyName) && !canonicalNames.name.isEmpty()) - englishName = canonicalNames.name; - if (!canonicalNames.preferredName.isEmpty()) { - subFamilyName = familyName; - subFamilyStyle = styleName; - faceName = familyName; // Remember the original name for later lookups - familyName = canonicalNames.preferredName; - styleName = canonicalNames.preferredStyle; - } - - QSupportedWritingSystems writingSystems; - if (type & TRUETYPE_FONTTYPE) { - Q_ASSERT(signature); - quint32 unicodeRange[4] = { - signature->fsUsb[0], signature->fsUsb[1], - signature->fsUsb[2], signature->fsUsb[3] - }; - quint32 codePageRange[2] = { - signature->fsCsb[0], signature->fsCsb[1] - }; - writingSystems = QPlatformFontDatabase::writingSystemsFromTrueTypeBits(unicodeRange, codePageRange); - // ### Hack to work around problem with Thai text on Windows 7. Segoe UI contains - // the symbol for Baht, and Windows thus reports that it supports the Thai script. - // Since it's the default UI font on this platform, most widgets will be unable to - // display Thai text by default. As a temporary work around, we special case Segoe UI - // and remove the Thai script from its list of supported writing systems. - if (writingSystems.supported(QFontDatabase::Thai) && - familyName == QLatin1String("Segoe UI")) - writingSystems.setSupported(QFontDatabase::Thai, false); - } else { - const QFontDatabase::WritingSystem ws = writingSystemFromCharSet(charSet); - if (ws != QFontDatabase::Any) - writingSystems.setSupported(ws); - } - - // We came here from populating a different font family, so we have - // to ensure the entire typographic family is populated before we - // mark it as such inside registerFont() - if (!subFamilyName.isEmpty() - && familyName != subFamilyName - && sfp->populatedFontFamily != familyName - && !QPlatformFontDatabase::isFamilyPopulated(familyName)) { - sfp->windowsFontDatabase->populateFamily(familyName); - } - - QPlatformFontDatabase::registerFont(familyName, styleName, foundryName, weight, - style, stretch, antialias, scalable, size, fixed, writingSystems, createFontFile(faceName)); - - // add fonts windows can generate for us: - if (weight <= QFont::DemiBold && styleName.isEmpty()) - QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, QFont::Bold, - style, stretch, antialias, scalable, size, fixed, writingSystems, createFontFile(faceName)); - if (style != QFont::StyleItalic && styleName.isEmpty()) - QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, weight, - QFont::StyleItalic, stretch, antialias, scalable, size, fixed, writingSystems, createFontFile(faceName)); - if (weight <= QFont::DemiBold && style != QFont::StyleItalic && styleName.isEmpty()) - QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, QFont::Bold, - QFont::StyleItalic, stretch, antialias, scalable, size, fixed, writingSystems, createFontFile(faceName)); - - if (!subFamilyName.isEmpty() && familyName != subFamilyName) { - QPlatformFontDatabase::registerFont(subFamilyName, subFamilyStyle, foundryName, weight, - style, stretch, antialias, scalable, size, fixed, writingSystems, createFontFile(faceName)); - } - - if (!englishName.isEmpty() && englishName != familyName) - QPlatformFontDatabase::registerAliasToFontFamily(familyName, englishName); - - return true; -} - -static int QT_WIN_CALLBACK storeFont(const LOGFONT *logFont, const TEXTMETRIC *textmetric, - DWORD type, LPARAM lparam) -{ - const ENUMLOGFONTEX *f = reinterpret_cast(logFont); - const QString familyName = QString::fromWCharArray(f->elfLogFont.lfFaceName); - const QString styleName = QString::fromWCharArray(f->elfStyle); - - // NEWTEXTMETRICEX (passed for TT fonts) is a NEWTEXTMETRIC, which according - // to the documentation is identical to a TEXTMETRIC except for the last four - // members, which we don't use anyway - const FONTSIGNATURE *signature = nullptr; - StoreFontPayload *sfp = reinterpret_cast(lparam); - Q_ASSERT(sfp != nullptr); - if (type & TRUETYPE_FONTTYPE) { - signature = &reinterpret_cast(textmetric)->ntmFontSig; - // We get a callback for each script-type supported, but we register them all - // at once using the signature, so we only need one call to addFontToDatabase(). - FontAndStyle fontAndStyle = {familyName, styleName}; - if (sfp->foundFontAndStyles.contains(fontAndStyle)) - return 1; - sfp->foundFontAndStyles.insert(fontAndStyle); - } - addFontToDatabase(familyName, styleName, *logFont, textmetric, signature, type, sfp); - - // keep on enumerating - return 1; -} - -void QWindowsFontDatabase::populateFamily(const QString &familyName) -{ - qCDebug(lcQpaFonts) << familyName; - if (familyName.size() >= LF_FACESIZE) { - qCWarning(lcQpaFonts) << "Unable to enumerate family '" << familyName << '\''; - return; - } - HDC dummy = GetDC(0); - LOGFONT lf; - lf.lfCharSet = DEFAULT_CHARSET; - familyName.toWCharArray(lf.lfFaceName); - lf.lfFaceName[familyName.size()] = 0; - lf.lfPitchAndFamily = 0; - StoreFontPayload sfp(familyName, this); - EnumFontFamiliesEx(dummy, &lf, storeFont, reinterpret_cast(&sfp), 0); - ReleaseDC(0, dummy); -} - -static int QT_WIN_CALLBACK populateFontFamilies(const LOGFONT *logFont, const TEXTMETRIC *textmetric, - DWORD, LPARAM) -{ - // the "@family" fonts are just the same as "family". Ignore them. - const ENUMLOGFONTEX *f = reinterpret_cast(logFont); - const wchar_t *faceNameW = f->elfLogFont.lfFaceName; - if (faceNameW[0] && faceNameW[0] != L'@' && wcsncmp(faceNameW, L"WST_", 4)) { - const QString faceName = QString::fromWCharArray(faceNameW); - QPlatformFontDatabase::registerFontFamily(faceName); - // Register current font's english name as alias - const bool ttf = (textmetric->tmPitchAndFamily & TMPF_TRUETYPE); - if (ttf && qt_localizedName(faceName)) { - const QString englishName = qt_getEnglishName(faceName); - if (!englishName.isEmpty()) - QPlatformFontDatabase::registerAliasToFontFamily(faceName, englishName); - } - } - return 1; // continue -} - -void QWindowsFontDatabase::addDefaultEUDCFont() -{ - const QString path = QWinRegistryKey(HKEY_CURRENT_USER, LR"(EUDC\1252)") - .stringValue(L"SystemDefaultEUDCFont"); - if (!path.isEmpty()) { - QFile file(path); - if (!file.open(QIODevice::ReadOnly)) { - qCWarning(lcQpaFonts) << "Unable to open default EUDC font:" << path; - return; - } - - m_eudcFonts = addApplicationFont(file.readAll(), path); - } -} - -void QWindowsFontDatabase::populateFontDatabase() -{ - removeApplicationFonts(); - HDC dummy = GetDC(0); - LOGFONT lf; - lf.lfCharSet = DEFAULT_CHARSET; - lf.lfFaceName[0] = 0; - lf.lfPitchAndFamily = 0; - EnumFontFamiliesEx(dummy, &lf, populateFontFamilies, 0, 0); - ReleaseDC(0, dummy); - // Work around EnumFontFamiliesEx() not listing the system font. - QString systemDefaultFamily = QWindowsFontDatabase::systemDefaultFont().family(); - if (QPlatformFontDatabase::resolveFontFamilyAlias(systemDefaultFamily) == systemDefaultFamily) - QPlatformFontDatabase::registerFontFamily(systemDefaultFamily); - addDefaultEUDCFont(); -} - -QWindowsFontDatabase::QWindowsFontDatabase() -{ - // Properties accessed by QWin32PrintEngine (Qt Print Support) - static const int hfontMetaTypeId = qRegisterMetaType(); - static const int logFontMetaTypeId = qRegisterMetaType(); - Q_UNUSED(hfontMetaTypeId) - Q_UNUSED(logFontMetaTypeId) - - if (lcQpaFonts().isDebugEnabled()) { - QSharedPointer d = data(); - qCDebug(lcQpaFonts) << __FUNCTION__ << "Clear type: " - << d->clearTypeEnabled << "gamma: " << d->fontSmoothingGamma; - } -} - -QWindowsFontDatabase::~QWindowsFontDatabase() -{ - removeApplicationFonts(); -} - -QFontEngine * QWindowsFontDatabase::fontEngine(const QFontDef &fontDef, void *handle) -{ - const QString faceName(static_cast(handle)); - QFontEngine *fe = QWindowsFontDatabase::createEngine(fontDef, faceName, - defaultVerticalDPI(), - data()); - qCDebug(lcQpaFonts) << __FUNCTION__ << "FONTDEF" << fontDef << fe << handle; - return fe; -} - -QFontEngine *QWindowsFontDatabase::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) -{ - EmbeddedFont font(fontData); - QFontEngine *fontEngine = 0; - -#if !defined(QT_NO_DIRECTWRITE) - if (!useDirectWrite(hintingPreference)) -#endif - { - GUID guid; - CoCreateGuid(&guid); - -QT_WARNING_PUSH -QT_WARNING_DISABLE_GCC("-Wstrict-aliasing") - QString uniqueFamilyName = QLatin1Char('f') - + QString::number(guid.Data1, 36) + QLatin1Char('-') - + QString::number(guid.Data2, 36) + QLatin1Char('-') - + QString::number(guid.Data3, 36) + QLatin1Char('-') - + QString::number(*reinterpret_cast(guid.Data4), 36); -QT_WARNING_POP - - QString actualFontName = font.changeFamilyName(uniqueFamilyName); - if (actualFontName.isEmpty()) { - qWarning("%s: Can't change family name of font", __FUNCTION__); - return 0; - } - - DWORD count = 0; - QByteArray newFontData = font.data(); - HANDLE fontHandle = - AddFontMemResourceEx(const_cast(newFontData.constData()), - DWORD(newFontData.size()), 0, &count); - if (count == 0 && fontHandle != 0) { - RemoveFontMemResourceEx(fontHandle); - fontHandle = 0; - } - - if (fontHandle == 0) { - qWarning("%s: AddFontMemResourceEx failed", __FUNCTION__); - } else { - QFontDef request; - request.family = uniqueFamilyName; - request.pixelSize = pixelSize; - request.styleStrategy = QFont::PreferMatch; - request.hintingPreference = hintingPreference; - request.stretch = QFont::Unstretched; - - fontEngine = QWindowsFontDatabase::createEngine(request, QString(), - defaultVerticalDPI(), - data()); - - if (fontEngine) { - if (request.family != fontEngine->fontDef.family) { - qWarning("%s: Failed to load font. Got fallback instead: %s", - __FUNCTION__, qPrintable(fontEngine->fontDef.family)); - if (fontEngine->ref.loadRelaxed() == 0) - delete fontEngine; - fontEngine = 0; - } else { - Q_ASSERT(fontEngine->ref.loadRelaxed() == 0); - - // Override the generated font name - switch (fontEngine->type()) { - case QFontEngine::Win: - static_cast(fontEngine)->setUniqueFamilyName(uniqueFamilyName); - fontEngine->fontDef.family = actualFontName; - break; - -#if !defined(QT_NO_DIRECTWRITE) - case QFontEngine::DirectWrite: - static_cast(fontEngine)->setUniqueFamilyName(uniqueFamilyName); - fontEngine->fontDef.family = actualFontName; - break; -#endif // !QT_NO_DIRECTWRITE - - default: - Q_ASSERT_X(false, Q_FUNC_INFO, "Unhandled font engine."); - } - - UniqueFontData uniqueData; - uniqueData.handle = fontHandle; - uniqueData.refCount.ref(); - m_uniqueFontData[uniqueFamilyName] = uniqueData; - } - } else { - RemoveFontMemResourceEx(fontHandle); - } - } - - // Get style and weight info - if (fontEngine != nullptr) - font.updateFromOS2Table(fontEngine); - } -#if !defined(QT_NO_DIRECTWRITE) - else { - fontEngine = QWindowsFontDatabaseBase::fontEngine(fontData, pixelSize, hintingPreference); - } -#endif - - qCDebug(lcQpaFonts) << __FUNCTION__ << "FONTDATA" << fontData << pixelSize << hintingPreference << fontEngine; - return fontEngine; -} - -static QList getTrueTypeFontOffsets(const uchar *fontData) -{ - QList offsets; - const quint32 headerTag = *reinterpret_cast(fontData); - if (headerTag != MAKE_TAG('t', 't', 'c', 'f')) { - if (headerTag != MAKE_TAG(0, 1, 0, 0) - && headerTag != MAKE_TAG('O', 'T', 'T', 'O') - && headerTag != MAKE_TAG('t', 'r', 'u', 'e') - && headerTag != MAKE_TAG('t', 'y', 'p', '1')) - return offsets; - offsets << 0; - return offsets; - } - const quint32 numFonts = qFromBigEndian(fontData + 8); - for (uint i = 0; i < numFonts; ++i) { - offsets << qFromBigEndian(fontData + 12 + i * 4); - } - return offsets; -} - -static void getFontTable(const uchar *fileBegin, const uchar *data, quint32 tag, const uchar **table, quint32 *length) -{ - const quint16 numTables = qFromBigEndian(data + 4); - for (uint i = 0; i < numTables; ++i) { - const quint32 offset = 12 + 16 * i; - if (*reinterpret_cast(data + offset) == tag) { - *table = fileBegin + qFromBigEndian(data + offset + 8); - *length = qFromBigEndian(data + offset + 12); - return; - } - } - *table = 0; - *length = 0; - return; -} - -static void getFamiliesAndSignatures(const QByteArray &fontData, - QList *families, - QVector *signatures, - QVector *values) -{ - const uchar *data = reinterpret_cast(fontData.constData()); - - QList offsets = getTrueTypeFontOffsets(data); - if (offsets.isEmpty()) - return; - - for (int i = 0; i < offsets.count(); ++i) { - const uchar *font = data + offsets.at(i); - const uchar *table; - quint32 length; - getFontTable(data, font, MAKE_TAG('n', 'a', 'm', 'e'), &table, &length); - if (!table) - continue; - QFontNames names = qt_getCanonicalFontNames(table, length); - if (names.name.isEmpty()) - continue; - - families->append(std::move(names)); - - if (values || signatures) - getFontTable(data, font, MAKE_TAG('O', 'S', '/', '2'), &table, &length); - - if (values) { - QFontValues fontValues; - if (table && length >= 64) { - // Read in some details about the font, offset calculated based on the specification - fontValues.weight = qFromBigEndian(table + 4); - - quint16 fsSelection = qFromBigEndian(table + 62); - fontValues.isItalic = (fsSelection & 1) != 0; - fontValues.isUnderlined = (fsSelection & (1 << 1)) != 0; - fontValues.isOverstruck = (fsSelection & (1 << 4)) != 0; - } - values->append(std::move(fontValues)); - } - - if (signatures) { - FONTSIGNATURE signature; - if (table && length >= 86) { - // Offsets taken from OS/2 table in the TrueType spec - signature.fsUsb[0] = qFromBigEndian(table + 42); - signature.fsUsb[1] = qFromBigEndian(table + 46); - signature.fsUsb[2] = qFromBigEndian(table + 50); - signature.fsUsb[3] = qFromBigEndian(table + 54); - - signature.fsCsb[0] = qFromBigEndian(table + 78); - signature.fsCsb[1] = qFromBigEndian(table + 82); - } else { - memset(&signature, 0, sizeof(signature)); - } - signatures->append(signature); - } - } -} - -QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName, QFontDatabasePrivate::ApplicationFont *applicationFont) -{ - WinApplicationFont font; - font.fileName = fileName; - QVector signatures; - QVector fontValues; - QList families; - QStringList familyNames; - - if (!fontData.isEmpty()) { - getFamiliesAndSignatures(fontData, &families, &signatures, &fontValues); - if (families.isEmpty()) - return familyNames; - - DWORD dummy = 0; - font.handle = - AddFontMemResourceEx(const_cast(fontData.constData()), - DWORD(fontData.size()), 0, &dummy); - if (font.handle == 0) - return QStringList(); - - // Memory fonts won't show up in enumeration, so do add them the hard way. - for (int j = 0; j < families.count(); ++j) { - const auto &family = families.at(j); - const QString &familyName = family.name; - const QString &styleName = family.style; - familyNames << familyName; - HDC hdc = GetDC(0); - LOGFONT lf; - memset(&lf, 0, sizeof(LOGFONT)); - memcpy(lf.lfFaceName, familyName.utf16(), sizeof(wchar_t) * qMin(LF_FACESIZE - 1, familyName.size())); - lf.lfCharSet = DEFAULT_CHARSET; - const QFontValues &values = fontValues.at(j); - lf.lfWeight = values.weight; - if (values.isItalic) - lf.lfItalic = TRUE; - if (values.isOverstruck) - lf.lfStrikeOut = TRUE; - if (values.isUnderlined) - lf.lfUnderline = TRUE; - HFONT hfont = CreateFontIndirect(&lf); - HGDIOBJ oldobj = SelectObject(hdc, hfont); - - if (applicationFont != nullptr) { - QFontDatabasePrivate::ApplicationFont::Properties properties; - properties.style = values.isItalic ? QFont::StyleItalic : QFont::StyleNormal; - properties.weight = QPlatformFontDatabase::weightFromInteger(values.weight); - properties.familyName = familyName; - properties.styleName = styleName; - - applicationFont->properties.append(properties); - } - - TEXTMETRIC textMetrics; - GetTextMetrics(hdc, &textMetrics); - - StoreFontPayload sfp(familyName, this); - addFontToDatabase(familyName, styleName, lf, &textMetrics, &signatures.at(j), - TRUETYPE_FONTTYPE, &sfp); - - SelectObject(hdc, oldobj); - DeleteObject(hfont); - ReleaseDC(0, hdc); - } - } else { - QFile f(fileName); - if (!f.open(QIODevice::ReadOnly)) - return QStringList(); - QByteArray data = f.readAll(); - f.close(); - - - getFamiliesAndSignatures(data, &families, nullptr, applicationFont != nullptr ? &fontValues : nullptr); - - if (families.isEmpty()) - return QStringList(); - - if (AddFontResourceExW((wchar_t*)fileName.utf16(), FR_PRIVATE, 0) == 0) - return QStringList(); - - font.handle = 0; - - // Fonts based on files are added via populate, as they will show up in font enumeration. - for (int j = 0; j < families.count(); ++j) { - const QString familyName = families.at(j).name; - familyNames << familyName; - - if (applicationFont != nullptr) { - const QString &styleName = families.at(j).style; - const QFontValues &values = fontValues.at(j); - - QFontDatabasePrivate::ApplicationFont::Properties properties; - properties.style = values.isItalic ? QFont::StyleItalic : QFont::StyleNormal; - properties.weight = QPlatformFontDatabase::weightFromInteger(values.weight); - properties.familyName = familyName; - properties.styleName = styleName; - - applicationFont->properties.append(properties); - } - - populateFamily(familyName); - } - } - - m_applicationFonts << font; - - return familyNames; -} - -void QWindowsFontDatabase::removeApplicationFonts() -{ - for (const WinApplicationFont &font : qAsConst(m_applicationFonts)) { - if (font.handle) { - RemoveFontMemResourceEx(font.handle); - } else { - RemoveFontResourceExW(reinterpret_cast(font.fileName.utf16()), - FR_PRIVATE, nullptr); - } - } - m_applicationFonts.clear(); - m_eudcFonts.clear(); -} - -void QWindowsFontDatabase::releaseHandle(void *handle) -{ - const QChar *faceName = reinterpret_cast(handle); - delete[] faceName; -} - -QString QWindowsFontDatabase::fontDir() const -{ - const QString result = QPlatformFontDatabase::fontDir(); - qCDebug(lcQpaFonts) << __FUNCTION__ << result; - return result; -} - -bool QWindowsFontDatabase::fontsAlwaysScalable() const -{ - return false; -} - -void QWindowsFontDatabase::derefUniqueFont(const QString &uniqueFont) -{ - if (m_uniqueFontData.contains(uniqueFont)) { - if (!m_uniqueFontData[uniqueFont].refCount.deref()) { - RemoveFontMemResourceEx(m_uniqueFontData[uniqueFont].handle); - m_uniqueFontData.remove(uniqueFont); - } - } -} - -void QWindowsFontDatabase::refUniqueFont(const QString &uniqueFont) -{ - if (m_uniqueFontData.contains(uniqueFont)) - m_uniqueFontData[uniqueFont].refCount.ref(); -} - -QStringList QWindowsFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const -{ - QStringList result; - result.append(familyForStyleHint(styleHint)); - result.append(m_eudcFonts); - result.append(extraTryFontsForFamily(family)); - result.append(QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script)); - - qCDebug(lcQpaFonts) << __FUNCTION__ << family << style << styleHint - << script << result; - return result; -} - - -QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request, const QString &faceName, - int dpi, - const QSharedPointer &data) -{ - QFontEngine *fe = 0; - - LOGFONT lf = fontDefToLOGFONT(request, faceName); - const bool preferClearTypeAA = lf.lfQuality == CLEARTYPE_QUALITY; - - if (request.stretch != 100) { - HFONT hfont = CreateFontIndirect(&lf); - if (!hfont) { - qErrnoWarning("%s: CreateFontIndirect failed", __FUNCTION__); - hfont = QWindowsFontDatabase::systemFont(); - } - - HGDIOBJ oldObj = SelectObject(data->hdc, hfont); - TEXTMETRIC tm; - if (!GetTextMetrics(data->hdc, &tm)) - qErrnoWarning("%s: GetTextMetrics failed", __FUNCTION__); - else - lf.lfWidth = tm.tmAveCharWidth * request.stretch / 100; - SelectObject(data->hdc, oldObj); - - DeleteObject(hfont); - } - -#if !defined(QT_NO_DIRECTWRITE) - if (data->directWriteFactory != nullptr) { - const QString fam = QString::fromWCharArray(lf.lfFaceName); - const QString nameSubstitute = QWindowsFontEngineDirectWrite::fontNameSubstitute(fam); - if (nameSubstitute != fam) { - const int nameSubstituteLength = qMin(nameSubstitute.length(), LF_FACESIZE - 1); - memcpy(lf.lfFaceName, nameSubstitute.utf16(), nameSubstituteLength * sizeof(wchar_t)); - lf.lfFaceName[nameSubstituteLength] = 0; - } - - HFONT hfont = CreateFontIndirect(&lf); - if (!hfont) { - qErrnoWarning("%s: CreateFontIndirect failed", __FUNCTION__); - } else { - HGDIOBJ oldFont = SelectObject(data->hdc, hfont); - - const QFont::HintingPreference hintingPreference = - static_cast(request.hintingPreference); - bool useDw = useDirectWrite(hintingPreference, fam); - - IDWriteFontFace *directWriteFontFace = NULL; - HRESULT hr = data->directWriteGdiInterop->CreateFontFaceFromHdc(data->hdc, &directWriteFontFace); - if (SUCCEEDED(hr)) { - bool isColorFont = false; -#if defined(QT_USE_DIRECTWRITE2) - IDWriteFontFace2 *directWriteFontFace2 = nullptr; - if (SUCCEEDED(directWriteFontFace->QueryInterface(__uuidof(IDWriteFontFace2), - reinterpret_cast(&directWriteFontFace2)))) { - if (directWriteFontFace2->IsColorFont()) - isColorFont = directWriteFontFace2->GetPaletteEntryCount() > 0; - - directWriteFontFace2->Release(); - } -#endif - useDw = useDw || useDirectWrite(hintingPreference, fam, isColorFont); - qCDebug(lcQpaFonts) << __FUNCTION__ << request.family << request.pointSize - << "pt" << "hintingPreference=" << hintingPreference << "color=" << isColorFont - << dpi << "dpi" << "useDirectWrite=" << useDw; - if (useDw) { - QWindowsFontEngineDirectWrite *fedw = new QWindowsFontEngineDirectWrite(directWriteFontFace, - request.pixelSize, - data); - - wchar_t n[64]; - GetTextFace(data->hdc, 64, n); - - QFontDef fontDef = request; - fontDef.family = QString::fromWCharArray(n); - - if (isColorFont) - fedw->glyphFormat = QFontEngine::Format_ARGB; - fedw->initFontInfo(fontDef, dpi); - fe = fedw; - } - directWriteFontFace->Release(); - } else if (useDw) { - const QString errorString = qt_error_string(int(hr)); - qWarning().noquote().nospace() << "DirectWrite: CreateFontFaceFromHDC() failed (" - << errorString << ") for " << request << ' ' << lf << " dpi=" << dpi; - } - - SelectObject(data->hdc, oldFont); - DeleteObject(hfont); - } - } -#endif // QT_NO_DIRECTWRITE - - if (!fe) { - QWindowsFontEngine *few = new QWindowsFontEngine(request.family, lf, data); - if (preferClearTypeAA) - few->glyphFormat = QFontEngine::Format_A32; - few->initFontInfo(request, dpi); - fe = few; - } - - return fe; -} - -bool QWindowsFontDatabase::isPrivateFontFamily(const QString &family) const -{ - return m_eudcFonts.contains(family) || QPlatformFontDatabase::isPrivateFontFamily(family); -} - -QT_END_NAMESPACE diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp deleted file mode 100644 index cde20eebc2..0000000000 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp +++ /dev/null @@ -1,444 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#include "qwindowsfontdatabase_ft_p.h" -#include "qwindowsfontdatabase_p.h" - -#include - -#include -#include FT_TRUETYPE_TABLES_H - -#include -#include -#include -#if QT_CONFIG(regularexpression) -#include -#endif -#include -#include - -#include - -QT_BEGIN_NAMESPACE - -static inline QFontDatabase::WritingSystem writingSystemFromCharSet(uchar charSet) -{ - switch (charSet) { - case ANSI_CHARSET: - case EASTEUROPE_CHARSET: - case BALTIC_CHARSET: - case TURKISH_CHARSET: - return QFontDatabase::Latin; - case GREEK_CHARSET: - return QFontDatabase::Greek; - case RUSSIAN_CHARSET: - return QFontDatabase::Cyrillic; - case HEBREW_CHARSET: - return QFontDatabase::Hebrew; - case ARABIC_CHARSET: - return QFontDatabase::Arabic; - case THAI_CHARSET: - return QFontDatabase::Thai; - case GB2312_CHARSET: - return QFontDatabase::SimplifiedChinese; - case CHINESEBIG5_CHARSET: - return QFontDatabase::TraditionalChinese; - case SHIFTJIS_CHARSET: - return QFontDatabase::Japanese; - case HANGUL_CHARSET: - case JOHAB_CHARSET: - return QFontDatabase::Korean; - case VIETNAMESE_CHARSET: - return QFontDatabase::Vietnamese; - case SYMBOL_CHARSET: - return QFontDatabase::Symbol; - default: - break; - } - return QFontDatabase::Any; -} - -static FontFile * createFontFile(const QString &fileName, int index) -{ - FontFile *fontFile = new FontFile; - fontFile->fileName = fileName; - fontFile->indexValue = index; - return fontFile; -} - -namespace { -struct FontKey -{ - QString fileName; - QStringList fontNames; -}; -} // namespace - -typedef QVector FontKeys; - -static FontKeys &fontKeys() -{ - static FontKeys result; - if (result.isEmpty()) { - const QStringList keys = { QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"), - QStringLiteral("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts") }; - for (const auto key : keys) { - const QSettings fontRegistry(key, QSettings::NativeFormat); - const QStringList allKeys = fontRegistry.allKeys(); - const QString trueType = QStringLiteral("(TrueType)"); -#if QT_CONFIG(regularexpression) - const QRegularExpression sizeListMatch(QStringLiteral("\\s(\\d+,)+\\d+")); - Q_ASSERT(sizeListMatch.isValid()); -#endif - const int size = allKeys.size(); - result.reserve(result.size() + size); - for (int i = 0; i < size; ++i) { - FontKey fontKey; - const QString ®istryFontKey = allKeys.at(i); - fontKey.fileName = fontRegistry.value(registryFontKey).toString(); - QString realKey = registryFontKey; - realKey.remove(trueType); -#if QT_CONFIG(regularexpression) - realKey.remove(sizeListMatch); -#endif - const auto fontNames = QStringRef(&realKey).trimmed().split(QLatin1Char('&')); - fontKey.fontNames.reserve(fontNames.size()); - for (const QStringRef &fontName : fontNames) - fontKey.fontNames.append(fontName.trimmed().toString()); - result.append(fontKey); - } - } - } - return result; -} - -static const FontKey *findFontKey(const QString &name, int *indexIn = nullptr) -{ - const FontKeys &keys = fontKeys(); - for (auto it = keys.constBegin(), cend = keys.constEnd(); it != cend; ++it) { - const int index = it->fontNames.indexOf(name); - if (index >= 0) { - if (indexIn) - *indexIn = index; - return &(*it); - } - } - if (indexIn) - *indexIn = -1; - return nullptr; -} - -static bool addFontToDatabase(QString familyName, - QString styleName, - const QString &fullName, - const LOGFONT &logFont, - const TEXTMETRIC *textmetric, - const FONTSIGNATURE *signature, - int type) -{ - // the "@family" fonts are just the same as "family". Ignore them. - if (familyName.isEmpty() || familyName.at(0) == QLatin1Char('@') || familyName.startsWith(QLatin1String("WST_"))) - return false; - - uchar charSet = logFont.lfCharSet; - - static const int SMOOTH_SCALABLE = 0xffff; - const QString foundryName; // No such concept. - const bool fixed = !(textmetric->tmPitchAndFamily & TMPF_FIXED_PITCH); - const bool ttf = (textmetric->tmPitchAndFamily & TMPF_TRUETYPE); - const bool scalable = textmetric->tmPitchAndFamily & (TMPF_VECTOR|TMPF_TRUETYPE); - const int size = scalable ? SMOOTH_SCALABLE : textmetric->tmHeight; - const QFont::Style style = textmetric->tmItalic ? QFont::StyleItalic : QFont::StyleNormal; - const bool antialias = false; - const QFont::Weight weight = QPlatformFontDatabase::weightFromInteger(textmetric->tmWeight); - const QFont::Stretch stretch = QFont::Unstretched; - -#ifndef QT_NO_DEBUG_STREAM - if (lcQpaFonts().isDebugEnabled()) { - QString message; - QTextStream str(&message); - str << __FUNCTION__ << ' ' << familyName << "::" << fullName << ' ' << charSet << " TTF=" << ttf; - if (type & DEVICE_FONTTYPE) - str << " DEVICE"; - if (type & RASTER_FONTTYPE) - str << " RASTER"; - if (type & TRUETYPE_FONTTYPE) - str << " TRUETYPE"; - str << " scalable=" << scalable << " Size=" << size - << " Style=" << style << " Weight=" << weight - << " stretch=" << stretch; - qCDebug(lcQpaFonts) << message; - } -#endif - - QString englishName; - QString faceName = familyName; - - QString subFamilyName; - QString subFamilyStyle; - // Look-up names registered in the font - QFontNames canonicalNames = qt_getCanonicalFontNames(logFont); - if (qt_localizedName(familyName) && !canonicalNames.name.isEmpty()) - englishName = canonicalNames.name; - if (!canonicalNames.preferredName.isEmpty()) { - subFamilyName = familyName; - subFamilyStyle = styleName; - familyName = canonicalNames.preferredName; - styleName = canonicalNames.preferredStyle; - } - - QSupportedWritingSystems writingSystems; - if (type & TRUETYPE_FONTTYPE) { - Q_ASSERT(signature); - quint32 unicodeRange[4] = { - signature->fsUsb[0], signature->fsUsb[1], - signature->fsUsb[2], signature->fsUsb[3] - }; - quint32 codePageRange[2] = { - signature->fsCsb[0], signature->fsCsb[1] - }; - writingSystems = QPlatformFontDatabase::writingSystemsFromTrueTypeBits(unicodeRange, codePageRange); - // ### Hack to work around problem with Thai text on Windows 7. Segoe UI contains - // the symbol for Baht, and Windows thus reports that it supports the Thai script. - // Since it's the default UI font on this platform, most widgets will be unable to - // display Thai text by default. As a temporary work around, we special case Segoe UI - // and remove the Thai script from its list of supported writing systems. - if (writingSystems.supported(QFontDatabase::Thai) && - faceName == QLatin1String("Segoe UI")) - writingSystems.setSupported(QFontDatabase::Thai, false); - } else { - const QFontDatabase::WritingSystem ws = writingSystemFromCharSet(charSet); - if (ws != QFontDatabase::Any) - writingSystems.setSupported(ws); - } - - int index = 0; - const FontKey *key = findFontKey(fullName, &index); - if (!key) { - // On non-English locales, the styles of the font may be localized in enumeration, but - // not in the registry. - QLocale systemLocale = QLocale::system(); - if (systemLocale.language() != QLocale::C - && systemLocale.language() != QLocale::English - && styleName != QLatin1String("Italic") - && styleName != QLatin1String("Bold")) { - key = findFontKey(qt_getEnglishName(fullName, true), &index); - } - if (!key) - key = findFontKey(faceName, &index); - if (!key && !englishName.isEmpty()) - key = findFontKey(englishName, &index); - if (!key) - return false; - } - QString value = key->fileName; - if (value.isEmpty()) - return false; - - if (!QDir::isAbsolutePath(value)) - value.prepend(QFile::decodeName(qgetenv("windir") + "\\Fonts\\")); - - QPlatformFontDatabase::registerFont(familyName, styleName, foundryName, weight, style, stretch, - antialias, scalable, size, fixed, writingSystems, createFontFile(value, index)); - - // add fonts windows can generate for us: - if (weight <= QFont::DemiBold && styleName.isEmpty()) - QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, QFont::Bold, style, stretch, - antialias, scalable, size, fixed, writingSystems, createFontFile(value, index)); - - if (style != QFont::StyleItalic && styleName.isEmpty()) - QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, weight, QFont::StyleItalic, stretch, - antialias, scalable, size, fixed, writingSystems, createFontFile(value, index)); - - if (weight <= QFont::DemiBold && style != QFont::StyleItalic && styleName.isEmpty()) - QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, QFont::Bold, QFont::StyleItalic, stretch, - antialias, scalable, size, fixed, writingSystems, createFontFile(value, index)); - - if (!subFamilyName.isEmpty() && familyName != subFamilyName) { - QPlatformFontDatabase::registerFont(subFamilyName, subFamilyStyle, foundryName, weight, - style, stretch, antialias, scalable, size, fixed, writingSystems, createFontFile(value, index)); - } - - if (!englishName.isEmpty() && englishName != familyName) - QPlatformFontDatabase::registerAliasToFontFamily(familyName, englishName); - - return true; -} - -static int QT_WIN_CALLBACK storeFont(const LOGFONT *logFont, const TEXTMETRIC *textmetric, - DWORD type, LPARAM lparam) -{ - const ENUMLOGFONTEX *f = reinterpret_cast(logFont); - const QString faceName = QString::fromWCharArray(f->elfLogFont.lfFaceName); - const QString styleName = QString::fromWCharArray(f->elfStyle); - const QString fullName = QString::fromWCharArray(f->elfFullName); - - // NEWTEXTMETRICEX (passed for TT fonts) is a NEWTEXTMETRIC, which according - // to the documentation is identical to a TEXTMETRIC except for the last four - // members, which we don't use anyway - const FONTSIGNATURE *signature = nullptr; - if (type & TRUETYPE_FONTTYPE) { - signature = &reinterpret_cast(textmetric)->ntmFontSig; - // We get a callback for each script-type supported, but we register them all - // at once using the signature, so we only need one call to addFontToDatabase(). - QSet *foundFontAndStyles = reinterpret_cast *>(lparam); - FontAndStyle fontAndStyle = {faceName, styleName}; - if (foundFontAndStyles->contains(fontAndStyle)) - return 1; - foundFontAndStyles->insert(fontAndStyle); - } - addFontToDatabase(faceName, styleName, fullName, *logFont, textmetric, signature, type); - - // keep on enumerating - return 1; -} - -/*! - \brief Populate font database using EnumFontFamiliesEx(). - - Normally, leaving the name empty should enumerate - all fonts, however, system fonts like "MS Shell Dlg 2" - are only found when specifying the name explicitly. -*/ - -void QWindowsFontDatabaseFT::populateFamily(const QString &familyName) -{ - qCDebug(lcQpaFonts) << familyName; - if (familyName.size() >= LF_FACESIZE) { - qCWarning(lcQpaFonts) << "Unable to enumerate family '" << familyName << '\''; - return; - } - HDC dummy = GetDC(0); - LOGFONT lf; - memset(&lf, 0, sizeof(LOGFONT)); - familyName.toWCharArray(lf.lfFaceName); - lf.lfFaceName[familyName.size()] = 0; - lf.lfCharSet = DEFAULT_CHARSET; - lf.lfPitchAndFamily = 0; - QSet foundFontAndStyles; - EnumFontFamiliesEx(dummy, &lf, storeFont, reinterpret_cast(&foundFontAndStyles), 0); - ReleaseDC(0, dummy); -} - -// Delayed population of font families - -static int QT_WIN_CALLBACK populateFontFamilies(const LOGFONT *logFont, const TEXTMETRIC *textmetric, - DWORD, LPARAM) -{ - const ENUMLOGFONTEX *f = reinterpret_cast(logFont); - // the "@family" fonts are just the same as "family". Ignore them. - const wchar_t *faceNameW = f->elfLogFont.lfFaceName; - if (faceNameW[0] && faceNameW[0] != L'@' && wcsncmp(faceNameW, L"WST_", 4)) { - // Register only font families for which a font file exists for delayed population - const bool ttf = textmetric->tmPitchAndFamily & TMPF_TRUETYPE; - const QString faceName = QString::fromWCharArray(faceNameW); - const FontKey *key = findFontKey(faceName); - if (!key) { - key = findFontKey(QString::fromWCharArray(f->elfFullName)); - if (!key && ttf && qt_localizedName(faceName)) - key = findFontKey(qt_getEnglishName(faceName)); - } - if (key) { - QPlatformFontDatabase::registerFontFamily(faceName); - // Register current font's english name as alias - if (ttf && qt_localizedName(faceName)) { - const QString englishName = qt_getEnglishName(faceName); - if (!englishName.isEmpty()) - QPlatformFontDatabase::registerAliasToFontFamily(faceName, englishName); - } - } - } - return 1; // continue -} - -void QWindowsFontDatabaseFT::populateFontDatabase() -{ - HDC dummy = GetDC(0); - LOGFONT lf; - lf.lfCharSet = DEFAULT_CHARSET; - lf.lfFaceName[0] = 0; - lf.lfPitchAndFamily = 0; - EnumFontFamiliesEx(dummy, &lf, populateFontFamilies, 0, 0); - ReleaseDC(0, dummy); - // Work around EnumFontFamiliesEx() not listing the system font - QString systemDefaultFamily = QWindowsFontDatabase::systemDefaultFont().family(); - if (QPlatformFontDatabase::resolveFontFamilyAlias(systemDefaultFamily) == systemDefaultFamily) - QPlatformFontDatabase::registerFontFamily(systemDefaultFamily); -} - -QFontEngine * QWindowsFontDatabaseFT::fontEngine(const QFontDef &fontDef, void *handle) -{ - QFontEngine *fe = QFreeTypeFontDatabase::fontEngine(fontDef, handle); - qCDebug(lcQpaFonts) << __FUNCTION__ << "FONTDEF" << fontDef.family << fe << handle; - return fe; -} - -QFontEngine *QWindowsFontDatabaseFT::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) -{ - QFontEngine *fe = QFreeTypeFontDatabase::fontEngine(fontData, pixelSize, hintingPreference); - qCDebug(lcQpaFonts) << __FUNCTION__ << "FONTDATA" << fontData << pixelSize << hintingPreference << fe; - return fe; -} - -QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const -{ - QStringList result; - result.append(QWindowsFontDatabaseBase::familyForStyleHint(styleHint)); - result.append(QWindowsFontDatabaseBase::extraTryFontsForFamily(family)); - result.append(QFreeTypeFontDatabase::fallbacksForFamily(family, style, styleHint, script)); - - qCDebug(lcQpaFonts) << __FUNCTION__ << family << style << styleHint - << script << result; - - return result; -} -QString QWindowsFontDatabaseFT::fontDir() const -{ - const QString result = QLatin1String(qgetenv("windir")) + QLatin1String("/Fonts");//QPlatformFontDatabase::fontDir(); - qCDebug(lcQpaFonts) << __FUNCTION__ << result; - return result; -} - -QFont QWindowsFontDatabaseFT::defaultFont() const -{ - return QWindowsFontDatabase::systemDefaultFont(); -} - -QT_END_NAMESPACE diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft_p.h deleted file mode 100644 index 16f61010d4..0000000000 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft_p.h +++ /dev/null @@ -1,79 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef QWINDOWSFONTDATABASEFT_H -#define QWINDOWSFONTDATABASEFT_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class QWindowsFontDatabaseFT : public QFreeTypeFontDatabase -{ -public: - void populateFontDatabase() override; - void populateFamily(const QString &familyName) override; - QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) override; - QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, - QFont::HintingPreference hintingPreference) override; - - QStringList fallbacksForFamily(const QString &family, QFont::Style style, - QFont::StyleHint styleHint, - QChar::Script script) const override; - - QString fontDir() const override; - QFont defaultFont() const override; -}; - -QT_END_NAMESPACE - -#endif // QWINDOWSFONTDATABASEFT_H diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h deleted file mode 100644 index 0652685fc5..0000000000 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h +++ /dev/null @@ -1,174 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef QWINDOWSFONTDATABASE_H -#define QWINDOWSFONTDATABASE_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qwindowsfontdatabasebase_p.h" - -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class QWindowsFontDatabase : public QWindowsFontDatabaseBase -{ - Q_DISABLE_COPY_MOVE(QWindowsFontDatabase) -public: - enum FontOptions { - // Relevant bits from QWindowsIntegration::Options - DontUseDirectWriteFonts = 0x40, - DontUseColorFonts = 0x80 - }; - - QWindowsFontDatabase(); - ~QWindowsFontDatabase() override; - - void ensureFamilyPopulated(const QString &familyName); - - void populateFontDatabase() override; - void populateFamily(const QString &familyName) override; - QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) override; - QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) override; - QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const override; - QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName, QFontDatabasePrivate::ApplicationFont *applicationFont = nullptr) override; - void releaseHandle(void *handle) override; - QString fontDir() const override; - - QFont defaultFont() const override { return systemDefaultFont(); } - bool fontsAlwaysScalable() const override; - void derefUniqueFont(const QString &uniqueFont); - void refUniqueFont(const QString &uniqueFont); - bool isPrivateFontFamily(const QString &family) const override; - - static QFontEngine *createEngine(const QFontDef &request, const QString &faceName, - int dpi, - const QSharedPointer &data); - - static qreal fontSmoothingGamma(); - - static void setFontOptions(unsigned options); - static unsigned fontOptions(); - -private: - void removeApplicationFonts(); - void addDefaultEUDCFont(); - - struct WinApplicationFont { - HANDLE handle; - QString fileName; - }; - - QList m_applicationFonts; - - struct UniqueFontData { - HANDLE handle; - QAtomicInt refCount; - }; - - QMap m_uniqueFontData; - - static unsigned m_fontOptions; - QStringList m_eudcFonts; -}; - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug, const QFontDef &def); -#endif - -inline quint16 qt_getUShort(const unsigned char *p) -{ - quint16 val; - val = *p++ << 8; - val |= *p; - - return val; -} - -struct QFontNames -{ - QString name; // e.g. "DejaVu Sans Condensed" - QString style; // e.g. "Italic" - QString preferredName; // e.g. "DejaVu Sans" - QString preferredStyle; // e.g. "Condensed Italic" -}; - -struct QFontValues -{ - quint16 weight = 0; - bool isItalic = false; - bool isOverstruck = false; - bool isUnderlined = false; -}; - -bool qt_localizedName(const QString &name); -QString qt_getEnglishName(const QString &familyName, bool includeStyle = false); -QFontNames qt_getCanonicalFontNames(const LOGFONT &lf); - -struct FontAndStyle { - QString font; - QString style; - - friend inline bool operator==(const FontAndStyle &lhs, const FontAndStyle &rhs) noexcept - { return lhs.font == rhs.font && lhs.style == rhs.style; } - friend inline bool operator!=(const FontAndStyle &lhs, const FontAndStyle &rhs) noexcept - { return !operator==(lhs, rhs); } -}; -inline size_t qHash(const FontAndStyle &key, size_t seed) noexcept -{ - return qHashMulti(seed, key.font, key.style); -} - -QT_END_NAMESPACE - -#endif // QWINDOWSFONTDATABASE_H diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabasebase.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabasebase.cpp deleted file mode 100644 index 568d1463e7..0000000000 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabasebase.cpp +++ /dev/null @@ -1,985 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qwindowsfontdatabasebase_p.h" -#include "qwindowsfontdatabase_p.h" - -#include -#include -#include - -#if !defined(QT_NO_DIRECTWRITE) -# if defined(QT_USE_DIRECTWRITE3) -# include -# elif defined(QT_USE_DIRECTWRITE2) -# include -# else -# include -# endif -# include -# include "qwindowsfontenginedirectwrite_p.h" -#endif - -QT_BEGIN_NAMESPACE - -// Helper classes for creating font engines directly from font data -namespace { - -# pragma pack(1) - - // Common structure for all formats of the "name" table - struct NameTable - { - quint16 format; - quint16 count; - quint16 stringOffset; - }; - - struct NameRecord - { - quint16 platformID; - quint16 encodingID; - quint16 languageID; - quint16 nameID; - quint16 length; - quint16 offset; - }; - - struct OffsetSubTable - { - quint32 scalerType; - quint16 numTables; - quint16 searchRange; - quint16 entrySelector; - quint16 rangeShift; - }; - - struct TableDirectory : public QWindowsFontDatabaseBase::FontTable - { - quint32 identifier; - quint32 checkSum; - quint32 offset; - quint32 length; - }; - - struct OS2Table - { - quint16 version; - qint16 avgCharWidth; - quint16 weightClass; - quint16 widthClass; - quint16 type; - qint16 subscriptXSize; - qint16 subscriptYSize; - qint16 subscriptXOffset; - qint16 subscriptYOffset; - qint16 superscriptXSize; - qint16 superscriptYSize; - qint16 superscriptXOffset; - qint16 superscriptYOffset; - qint16 strikeOutSize; - qint16 strikeOutPosition; - qint16 familyClass; - quint8 panose[10]; - quint32 unicodeRanges[4]; - quint8 vendorID[4]; - quint16 selection; - quint16 firstCharIndex; - quint16 lastCharIndex; - qint16 typoAscender; - qint16 typoDescender; - qint16 typoLineGap; - quint16 winAscent; - quint16 winDescent; - quint32 codepageRanges[2]; - qint16 height; - qint16 capHeight; - quint16 defaultChar; - quint16 breakChar; - quint16 maxContext; - }; - -# pragma pack() - -} // Anonymous namespace - -QWindowsFontDatabaseBase::FontTable *QWindowsFontDatabaseBase::EmbeddedFont::tableDirectoryEntry(const QByteArray &tagName) -{ - Q_ASSERT(tagName.size() == 4); - quint32 tagId = *(reinterpret_cast(tagName.constData())); - const size_t fontDataSize = m_fontData.size(); - if (Q_UNLIKELY(fontDataSize < sizeof(OffsetSubTable))) - return nullptr; - - OffsetSubTable *offsetSubTable = reinterpret_cast(m_fontData.data()); - TableDirectory *tableDirectory = reinterpret_cast(offsetSubTable + 1); - - const size_t tableCount = qFromBigEndian(offsetSubTable->numTables); - if (Q_UNLIKELY(fontDataSize < sizeof(OffsetSubTable) + sizeof(TableDirectory) * tableCount)) - return nullptr; - - TableDirectory *tableDirectoryEnd = tableDirectory + tableCount; - for (TableDirectory *entry = tableDirectory; entry < tableDirectoryEnd; ++entry) { - if (entry->identifier == tagId) - return entry; - } - - return nullptr; -} - -QString QWindowsFontDatabaseBase::EmbeddedFont::familyName(QWindowsFontDatabaseBase::FontTable *directoryEntry) -{ - QString name; - - TableDirectory *nameTableDirectoryEntry = static_cast(directoryEntry); - if (nameTableDirectoryEntry == nullptr) - nameTableDirectoryEntry = static_cast(tableDirectoryEntry("name")); - - if (nameTableDirectoryEntry != nullptr) { - quint32 offset = qFromBigEndian(nameTableDirectoryEntry->offset); - if (Q_UNLIKELY(quint32(m_fontData.size()) < offset + sizeof(NameTable))) - return QString(); - - NameTable *nameTable = reinterpret_cast(m_fontData.data() + offset); - NameRecord *nameRecord = reinterpret_cast(nameTable + 1); - - quint16 nameTableCount = qFromBigEndian(nameTable->count); - if (Q_UNLIKELY(quint32(m_fontData.size()) < offset + sizeof(NameRecord) * nameTableCount)) - return QString(); - - for (int i = 0; i < nameTableCount; ++i, ++nameRecord) { - if (qFromBigEndian(nameRecord->nameID) == 1 - && qFromBigEndian(nameRecord->platformID) == 3 // Windows - && qFromBigEndian(nameRecord->languageID) == 0x0409) { // US English - quint16 stringOffset = qFromBigEndian(nameTable->stringOffset); - quint16 nameOffset = qFromBigEndian(nameRecord->offset); - quint16 nameLength = qFromBigEndian(nameRecord->length); - - if (Q_UNLIKELY(quint32(m_fontData.size()) < offset + stringOffset + nameOffset + nameLength)) - return QString(); - - const void *ptr = reinterpret_cast(nameTable) - + stringOffset - + nameOffset; - - const quint16 *s = reinterpret_cast(ptr); - const quint16 *e = s + nameLength / sizeof(quint16); - while (s != e) - name += QChar( qFromBigEndian(*s++)); - break; - } - } - } - - return name; -} - -void QWindowsFontDatabaseBase::EmbeddedFont::updateFromOS2Table(QFontEngine *fontEngine) -{ - TableDirectory *os2TableEntry = static_cast(tableDirectoryEntry("OS/2")); - if (os2TableEntry != nullptr) { - const OS2Table *os2Table = - reinterpret_cast(m_fontData.constData() - + qFromBigEndian(os2TableEntry->offset)); - - bool italic = qFromBigEndian(os2Table->selection) & (1 << 0); - bool oblique = qFromBigEndian(os2Table->selection) & (1 << 9); - - if (italic) - fontEngine->fontDef.style = QFont::StyleItalic; - else if (oblique) - fontEngine->fontDef.style = QFont::StyleOblique; - else - fontEngine->fontDef.style = QFont::StyleNormal; - - fontEngine->fontDef.weight = QPlatformFontDatabase::weightFromInteger(qFromBigEndian(os2Table->weightClass)); - } -} - -QString QWindowsFontDatabaseBase::EmbeddedFont::changeFamilyName(const QString &newFamilyName) -{ - TableDirectory *nameTableDirectoryEntry = static_cast(tableDirectoryEntry("name")); - if (nameTableDirectoryEntry == nullptr) - 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() * int(sizeof(quint16)); - - const QString regularString = QString::fromLatin1("Regular"); - int regularStringSize = regularString.size() * int(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(newNameTable.data()); - nameTable->count = qbswap(requiredRecordCount); - nameTable->stringOffset = qbswap(sizeOfHeader); - - NameRecord *nameRecord = reinterpret_cast(nameTable + 1); - for (int i = 0; i < requiredRecordCount; ++i, nameRecord++) { - nameRecord->nameID = qbswap(nameIds[i]); - nameRecord->encodingID = qbswap(1); - nameRecord->languageID = qbswap(0x0409); - nameRecord->platformID = qbswap(3); - nameRecord->length = qbswap(newFamilyNameSize); - - // Special case for sub-family - if (nameIds[i] == 4) { - nameRecord->offset = qbswap(newFamilyNameSize); - nameRecord->length = qbswap(regularStringSize); - } - } - - // nameRecord now points to string data - quint16 *stringStorage = reinterpret_cast(nameRecord); - const quint16 *sourceString = newFamilyName.utf16(); - for (int i = 0; i < newFamilyName.size(); ++i) - stringStorage[i] = qbswap(sourceString[i]); - stringStorage += newFamilyName.size(); - - sourceString = regularString.utf16(); - for (int i = 0; i < regularString.size(); ++i) - stringStorage[i] = qbswap(sourceString[i]); - } - - quint32 *p = reinterpret_cast(newNameTable.data()); - quint32 *tableEnd = reinterpret_cast(newNameTable.data() + fullSize); - - quint32 checkSum = 0; - while (p < tableEnd) - checkSum += qFromBigEndian(*(p++)); - - nameTableDirectoryEntry->checkSum = qbswap(checkSum); - nameTableDirectoryEntry->offset = qbswap(m_fontData.size()); - nameTableDirectoryEntry->length = qbswap(fullSize); - - m_fontData.append(newNameTable); - - return oldFamilyName; -} - -#if !defined(QT_NO_DIRECTWRITE) - -namespace { - class DirectWriteFontFileStream: public IDWriteFontFileStream - { - Q_DISABLE_COPY(DirectWriteFontFileStream) - public: - DirectWriteFontFileStream(const QByteArray &fontData) - : m_fontData(fontData) - , m_referenceCount(0) - { - } - virtual ~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 (fileOffset + fragmentSize <= quint64(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) {} - virtual ~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 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("%s: Wrong key size", __FUNCTION__); - return E_FAIL; - } - - const void *key = *reinterpret_cast(fontFileReferenceKey); - *fontFileStream = NULL; - auto it = m_fontDatas.constFind(key); - if (it == m_fontDatas.constEnd()) - return E_FAIL; - - QByteArray fontData = it.value(); - DirectWriteFontFileStream *stream = new DirectWriteFontFileStream(fontData); - stream->AddRef(); - *fontFileStream = stream; - - return S_OK; - } - - class CustomFontFileLoader - { - public: - CustomFontFileLoader(IDWriteFactory *factory) - { - m_directWriteFactory = factory; - - if (m_directWriteFactory) { - m_directWriteFactory->AddRef(); - - m_directWriteFontFileLoader = new DirectWriteFontFileLoader(); - m_directWriteFactory->RegisterFontFileLoader(m_directWriteFontFileLoader); - } - } - - ~CustomFontFileLoader() - { - if (m_directWriteFactory != nullptr && m_directWriteFontFileLoader != nullptr) - m_directWriteFactory->UnregisterFontFileLoader(m_directWriteFontFileLoader); - - if (m_directWriteFactory != nullptr) - m_directWriteFactory->Release(); - } - - void addKey(const void *key, const QByteArray &fontData) - { - if (m_directWriteFontFileLoader != nullptr) - m_directWriteFontFileLoader->addKey(key, fontData); - } - - void removeKey(const void *key) - { - if (m_directWriteFontFileLoader != nullptr) - m_directWriteFontFileLoader->removeKey(key); - } - - IDWriteFontFileLoader *loader() const - { - return m_directWriteFontFileLoader; - } - - private: - IDWriteFactory *m_directWriteFactory = nullptr; - DirectWriteFontFileLoader *m_directWriteFontFileLoader = nullptr; - }; -} // Anonymous namespace - -#endif // !defined(QT_NO_DIRECTWRITE) - - -QWindowsFontEngineData::~QWindowsFontEngineData() -{ - if (hdc) - DeleteDC(hdc); - -#if !defined(QT_NO_DIRECTWRITE) - if (directWriteGdiInterop) - directWriteGdiInterop->Release(); - if (directWriteFactory) - directWriteFactory->Release(); -#endif -} - -QWindowsFontDatabaseBase::QWindowsFontDatabaseBase() -{ -} - -QWindowsFontDatabaseBase::~QWindowsFontDatabaseBase() -{ -} - -typedef QSharedPointer QWindowsFontEngineDataPtr; -typedef QThreadStorage FontEngineThreadLocalData; -Q_GLOBAL_STATIC(FontEngineThreadLocalData, fontEngineThreadLocalData) - -QSharedPointer QWindowsFontDatabaseBase::data() -{ - FontEngineThreadLocalData *data = fontEngineThreadLocalData(); - if (!data->hasLocalData()) - data->setLocalData(QSharedPointer::create()); - - if (!init(data->localData())) - qCWarning(lcQpaFonts) << "Cannot initialize common font database data"; - - return data->localData(); -} - -bool QWindowsFontDatabaseBase::init(QSharedPointer d) -{ -#if !defined(QT_NO_DIRECTWRITE) - if (!d->directWriteFactory) { - createDirectWriteFactory(&d->directWriteFactory); - if (!d->directWriteFactory) - return false; - } - if (!d->directWriteGdiInterop) { - const HRESULT hr = d->directWriteFactory->GetGdiInterop(&d->directWriteGdiInterop); - if (FAILED(hr)) { - qErrnoWarning("%s: GetGdiInterop failed", __FUNCTION__); - return false; - } - } -#endif - return true; -} - -#if !defined(QT_NO_DIRECTWRITE) -// ### Qt 6: Link directly to dwrite instead -typedef HRESULT (WINAPI *DWriteCreateFactoryType)(DWRITE_FACTORY_TYPE, const IID &, IUnknown **); -static inline DWriteCreateFactoryType resolveDWriteCreateFactory() -{ - QSystemLibrary library(QStringLiteral("dwrite")); - QFunctionPointer result = library.resolve("DWriteCreateFactory"); - if (Q_UNLIKELY(!result)) { - qWarning("Unable to load dwrite.dll"); - return nullptr; - } - return reinterpret_cast(result); -} - -void QWindowsFontDatabaseBase::createDirectWriteFactory(IDWriteFactory **factory) -{ - *factory = nullptr; - - static const DWriteCreateFactoryType dWriteCreateFactory = resolveDWriteCreateFactory(); - if (!dWriteCreateFactory) - return; - - IUnknown *result = nullptr; -# if defined(QT_USE_DIRECTWRITE3) - dWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory3), &result); -# endif - -# if defined(QT_USE_DIRECTWRITE2) - if (result == nullptr) - dWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory2), &result); -# endif - - if (result == nullptr) { - if (FAILED(dWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), &result))) { - qErrnoWarning("DWriteCreateFactory failed"); - return; - } - } - - *factory = static_cast(result); -} -#endif // !defined(QT_NO_DIRECTWRITE) - -static int s_defaultVerticalDPI = 96; // Native Pixels - -int QWindowsFontDatabaseBase::defaultVerticalDPI() -{ - return s_defaultVerticalDPI; -} - -void QWindowsFontDatabaseBase::setDefaultVerticalDPI(int d) -{ - s_defaultVerticalDPI = d; -} - -LOGFONT QWindowsFontDatabaseBase::fontDefToLOGFONT(const QFontDef &request, const QString &faceName) -{ - LOGFONT lf; - memset(&lf, 0, sizeof(LOGFONT)); - - lf.lfHeight = -qRound(request.pixelSize); - lf.lfWidth = 0; - lf.lfEscapement = 0; - lf.lfOrientation = 0; - if (request.weight == 50) - lf.lfWeight = FW_DONTCARE; - else - lf.lfWeight = (request.weight*900)/99; - lf.lfItalic = request.style != QFont::StyleNormal; - lf.lfCharSet = DEFAULT_CHARSET; - - int strat = OUT_DEFAULT_PRECIS; - if (request.styleStrategy & QFont::PreferBitmap) { - strat = OUT_RASTER_PRECIS; - } else if (request.styleStrategy & QFont::PreferDevice) { - strat = OUT_DEVICE_PRECIS; - } else if (request.styleStrategy & QFont::PreferOutline) { - strat = OUT_OUTLINE_PRECIS; - } else if (request.styleStrategy & QFont::ForceOutline) { - strat = OUT_TT_ONLY_PRECIS; - } - - lf.lfOutPrecision = strat; - - int qual = DEFAULT_QUALITY; - - if (request.styleStrategy & QFont::PreferMatch) - qual = DRAFT_QUALITY; - else if (request.styleStrategy & QFont::PreferQuality) - qual = PROOF_QUALITY; - - if (request.styleStrategy & QFont::PreferAntialias) { - qual = (request.styleStrategy & QFont::NoSubpixelAntialias) == 0 - ? CLEARTYPE_QUALITY : ANTIALIASED_QUALITY; - } else if (request.styleStrategy & QFont::NoAntialias) { - qual = NONANTIALIASED_QUALITY; - } else if ((request.styleStrategy & QFont::NoSubpixelAntialias) && data()->clearTypeEnabled) { - qual = ANTIALIASED_QUALITY; - } - - lf.lfQuality = qual; - - lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; - - int hint = FF_DONTCARE; - switch (request.styleHint) { - case QFont::Helvetica: - hint = FF_SWISS; - break; - case QFont::Times: - hint = FF_ROMAN; - break; - case QFont::Courier: - hint = FF_MODERN; - break; - case QFont::OldEnglish: - hint = FF_DECORATIVE; - break; - case QFont::System: - hint = FF_MODERN; - break; - default: - break; - } - - lf.lfPitchAndFamily = DEFAULT_PITCH | hint; - - QString fam = faceName; - if (fam.isEmpty()) - fam = request.families.size() > 0 ? request.families.at(0) : request.family; - if (Q_UNLIKELY(fam.size() >= LF_FACESIZE)) { - qCritical("%s: Family name '%s' is too long.", __FUNCTION__, qPrintable(fam)); - fam.truncate(LF_FACESIZE - 1); - } - - if (fam.isEmpty()) - fam = QStringLiteral("MS Sans Serif"); - - if (fam == QLatin1String("MS Sans Serif") - && (request.style == QFont::StyleItalic || (-lf.lfHeight > 18 && -lf.lfHeight != 24))) { - fam = QStringLiteral("Arial"); // MS Sans Serif has bearing problems in italic, and does not scale - } - if (fam == QLatin1String("Courier") && !(request.styleStrategy & QFont::PreferBitmap)) - fam = QStringLiteral("Courier New"); - - memcpy(lf.lfFaceName, fam.utf16(), fam.size() * sizeof(wchar_t)); - - return lf; -} - -QFont QWindowsFontDatabaseBase::LOGFONT_to_QFont(const LOGFONT& logFont, int verticalDPI_In) -{ - if (verticalDPI_In <= 0) - verticalDPI_In = defaultVerticalDPI(); - QFont qFont(QString::fromWCharArray(logFont.lfFaceName)); - qFont.setItalic(logFont.lfItalic); - if (logFont.lfWeight != FW_DONTCARE) - qFont.setWeight(QPlatformFontDatabase::weightFromInteger(logFont.lfWeight)); - const qreal logFontHeight = qAbs(logFont.lfHeight); - qFont.setPointSizeF(logFontHeight * 72.0 / qreal(verticalDPI_In)); - qFont.setUnderline(logFont.lfUnderline); - qFont.setOverline(false); - qFont.setStrikeOut(logFont.lfStrikeOut); - return qFont; -} - -// ### fixme Qt 6 (QTBUG-58610): See comment at QWindowsFontDatabase::systemDefaultFont() -HFONT QWindowsFontDatabaseBase::systemFont() -{ - static const auto stock_sysfont = - reinterpret_cast(GetStockObject(DEFAULT_GUI_FONT)); - return stock_sysfont; -} - -QFont QWindowsFontDatabaseBase::systemDefaultFont() -{ -#if QT_VERSION >= 0x060000 - // 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); - const QFont systemFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfMessageFont); -#else - LOGFONT lf; - GetObject(systemFont(), sizeof(lf), &lf); - QFont systemFont = LOGFONT_to_QFont(lf); - // "MS Shell Dlg 2" is the correct system font >= Win2k - if (systemFont.family() == QLatin1String("MS Shell Dlg")) - systemFont.setFamily(QStringLiteral("MS Shell Dlg 2")); - // Qt 5 by (Qt 4) legacy uses GetStockObject(DEFAULT_GUI_FONT) to - // obtain the default GUI font (typically "MS Shell Dlg 2, 8pt"). This has been - // long deprecated; the message font of the NONCLIENTMETRICS structure obtained by - // SystemParametersInfo(SPI_GETNONCLIENTMETRICS) should be used instead (see - // QWindowsTheme::refreshFonts(), typically "Segoe UI, 9pt"), which is larger. -#endif // Qt 5 - qCDebug(lcQpaFonts) << __FUNCTION__ << systemFont; - return systemFont; -} - -#if !defined(QT_NO_DIRECTWRITE) -IDWriteFontFace *QWindowsFontDatabaseBase::createDirectWriteFace(const QByteArray &fontData) const -{ - QSharedPointer fontEngineData = data(); - if (fontEngineData->directWriteFactory == nullptr) { - qCWarning(lcQpaFonts) << "DirectWrite factory not created in QWindowsFontDatabaseBase::createDirectWriteFace()"; - return nullptr; - } - - CustomFontFileLoader fontFileLoader(fontEngineData->directWriteFactory); - fontFileLoader.addKey(this, fontData); - - IDWriteFontFile *fontFile = nullptr; - const void *key = this; - - HRESULT hres = fontEngineData->directWriteFactory->CreateCustomFontFileReference(&key, - sizeof(void *), - fontFileLoader.loader(), - &fontFile); - if (FAILED(hres)) { - qErrnoWarning(hres, "%s: CreateCustomFontFileReference failed", __FUNCTION__); - return nullptr; - } - - BOOL isSupportedFontType; - DWRITE_FONT_FILE_TYPE fontFileType; - DWRITE_FONT_FACE_TYPE fontFaceType; - UINT32 numberOfFaces; - fontFile->Analyze(&isSupportedFontType, &fontFileType, &fontFaceType, &numberOfFaces); - if (!isSupportedFontType) { - fontFile->Release(); - return nullptr; - } - - // ### 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; - } - - fontFile->Release(); - return directWriteFontFace; -} -#endif // !defined(QT_NO_DIRECTWRITE) - -QFontEngine *QWindowsFontDatabaseBase::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) -{ - QFontEngine *fontEngine = nullptr; - -#if !defined(QT_NO_DIRECTWRITE) - QSharedPointer fontEngineData = data(); - if (fontEngineData->directWriteFactory == nullptr) - return nullptr; - - IDWriteFontFace *directWriteFontFace = createDirectWriteFace(fontData); - fontEngine = new QWindowsFontEngineDirectWrite(directWriteFontFace, - pixelSize, - fontEngineData); - - // Get font family from font data - EmbeddedFont font(fontData); - font.updateFromOS2Table(fontEngine); - fontEngine->fontDef.family = font.familyName(); - fontEngine->fontDef.hintingPreference = hintingPreference; - - directWriteFontFace->Release(); -#else // !defined(QT_NO_DIRECTWRITE) - Q_UNUSED(fontData); - Q_UNUSED(pixelSize); - Q_UNUSED(hintingPreference); -#endif - - return fontEngine; -} - -QString QWindowsFontDatabaseBase::familyForStyleHint(QFont::StyleHint styleHint) -{ - switch (styleHint) { - case QFont::Times: - return QStringLiteral("Times New Roman"); - case QFont::Courier: - return QStringLiteral("Courier New"); - case QFont::Monospace: - return QStringLiteral("Courier New"); - case QFont::Cursive: - return QStringLiteral("Comic Sans MS"); - case QFont::Fantasy: - return QStringLiteral("Impact"); - case QFont::Decorative: - return QStringLiteral("Old English"); - case QFont::Helvetica: - return QStringLiteral("Arial"); - case QFont::System: - default: - break; - } - return QStringLiteral("MS Shell Dlg 2"); -} - -// Creation functions - -static const char *other_tryFonts[] = { - "Arial", - "MS UI Gothic", - "Gulim", - "SimSun", - "PMingLiU", - "Arial Unicode MS", - 0 -}; - -static const char *jp_tryFonts [] = { - "MS UI Gothic", - "Arial", - "Gulim", - "SimSun", - "PMingLiU", - "Arial Unicode MS", - 0 -}; - -static const char *ch_CN_tryFonts [] = { - "SimSun", - "Arial", - "PMingLiU", - "Gulim", - "MS UI Gothic", - "Arial Unicode MS", - 0 -}; - -static const char *ch_TW_tryFonts [] = { - "PMingLiU", - "Arial", - "SimSun", - "Gulim", - "MS UI Gothic", - "Arial Unicode MS", - 0 -}; - -static const char *kr_tryFonts[] = { - "Gulim", - "Arial", - "PMingLiU", - "SimSun", - "MS UI Gothic", - "Arial Unicode MS", - 0 -}; - -static const char **tryFonts = nullptr; - -QStringList QWindowsFontDatabaseBase::extraTryFontsForFamily(const QString &family) -{ - QStringList result; - QFontDatabase db; - if (!db.writingSystems(family).contains(QFontDatabase::Symbol)) { - if (!tryFonts) { - LANGID lid = GetUserDefaultLangID(); - switch (lid&0xff) { - case LANG_CHINESE: // Chinese - if ( lid == 0x0804 || lid == 0x1004) // China mainland and Singapore - tryFonts = ch_CN_tryFonts; - else - tryFonts = ch_TW_tryFonts; // Taiwan, Hong Kong and Macau - break; - case LANG_JAPANESE: - tryFonts = jp_tryFonts; - break; - case LANG_KOREAN: - tryFonts = kr_tryFonts; - break; - default: - tryFonts = other_tryFonts; - break; - } - } - QFontDatabase db; - const QStringList families = db.families(); - const char **tf = tryFonts; - while (tf && *tf) { - // QTBUG-31689, family might be an English alias for a localized font name. - const QString family = QString::fromLatin1(*tf); - if (families.contains(family) || db.hasFamily(family)) - result << family; - ++tf; - } - } - result.append(QStringLiteral("Segoe UI Emoji")); - result.append(QStringLiteral("Segoe UI Symbol")); - return result; -} - -QT_END_NAMESPACE diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabasebase_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabasebase_p.h deleted file mode 100644 index 55763f7c76..0000000000 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabasebase_p.h +++ /dev/null @@ -1,138 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef QWINDOWSFONTDATABASEBASE_P_H -#define QWINDOWSFONTDATABASEBASE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include -#include -#include - -#if !defined(QT_NO_DIRECTWRITE) - struct IDWriteFactory; - struct IDWriteGdiInterop; - struct IDWriteFontFace; -#endif - -QT_BEGIN_NAMESPACE - -Q_DECLARE_LOGGING_CATEGORY(lcQpaFonts); - -class QWindowsFontEngineData -{ - Q_DISABLE_COPY_MOVE(QWindowsFontEngineData) -public: - QWindowsFontEngineData(); - ~QWindowsFontEngineData(); - - uint pow_gamma[256]; - - bool clearTypeEnabled = false; - qreal fontSmoothingGamma; - HDC hdc = 0; -#if !defined(QT_NO_DIRECTWRITE) - IDWriteFactory *directWriteFactory = nullptr; - IDWriteGdiInterop *directWriteGdiInterop = nullptr; -#endif -}; - -class QWindowsFontDatabaseBase : public QPlatformFontDatabase -{ -public: - QWindowsFontDatabaseBase(); - ~QWindowsFontDatabaseBase() override; - - QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) override; - - static int defaultVerticalDPI(); - static void setDefaultVerticalDPI(int d); - - static QSharedPointer data(); -#if !defined(QT_NO_DIRECTWRITE) - static void createDirectWriteFactory(IDWriteFactory **factory); -#endif - static QFont systemDefaultFont(); - static HFONT systemFont(); - static LOGFONT fontDefToLOGFONT(const QFontDef &fontDef, const QString &faceName); - static QFont LOGFONT_to_QFont(const LOGFONT& lf, int verticalDPI = 0); - - static QString familyForStyleHint(QFont::StyleHint styleHint); - static QStringList extraTryFontsForFamily(const QString &family); - - class FontTable{}; - class EmbeddedFont - { - public: - EmbeddedFont(const QByteArray &fontData) : m_fontData(fontData) {} - - QString changeFamilyName(const QString &newFamilyName); - QByteArray data() const { return m_fontData; } - void updateFromOS2Table(QFontEngine *fontEngine); - FontTable *tableDirectoryEntry(const QByteArray &tagName); - QString familyName(FontTable *nameTableDirectory = nullptr); - - private: - QByteArray m_fontData; - }; - -protected: - -#if !defined(QT_NO_DIRECTWRITE) - IDWriteFontFace *createDirectWriteFace(const QByteArray &fontData) const; -#endif - -private: - static bool init(QSharedPointer data); -}; - -QT_END_NAMESPACE - -#endif // QWINDOWSFONTDATABASEBASE_P_H diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp deleted file mode 100644 index 6248041a3d..0000000000 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp +++ /dev/null @@ -1,1204 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module 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$ -** -****************************************************************************/ - -#include "qwindowsfontengine_p.h" -#include "qwindowsnativeimage_p.h" -#include "qwindowsfontdatabase_p.h" -#include -#include "qwindowsfontenginedirectwrite_p.h" - -#include -#include // glyph_metrics_t -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#if !defined(QT_NO_DIRECTWRITE) -# include -# include -#endif - -QT_BEGIN_NAMESPACE - -//### mingw needed define -#ifndef TT_PRIM_CSPLINE -#define TT_PRIM_CSPLINE 3 -#endif - -// GetFontData expects the tags in little endian ;( -#define MAKE_LITTLE_ENDIAN_TAG(ch1, ch2, ch3, ch4) (\ - (((quint32)(ch4)) << 24) | \ - (((quint32)(ch3)) << 16) | \ - (((quint32)(ch2)) << 8) | \ - ((quint32)(ch1)) \ - ) - -// common DC for all fonts - -typedef BOOL (WINAPI *PtrGetCharWidthI)(HDC, UINT, UINT, LPWORD, LPINT); -static PtrGetCharWidthI ptrGetCharWidthI = 0; -static bool resolvedGetCharWidthI = false; - -static void resolveGetCharWidthI() -{ - if (resolvedGetCharWidthI) - return; - resolvedGetCharWidthI = true; - ptrGetCharWidthI = (PtrGetCharWidthI)QSystemLibrary::resolve(QStringLiteral("gdi32"), "GetCharWidthI"); -} - -// general font engine - -QFixed QWindowsFontEngine::lineThickness() const -{ - if(lineWidth > 0) - return lineWidth; - - return QFontEngine::lineThickness(); -} - -static OUTLINETEXTMETRIC *getOutlineTextMetric(HDC hdc) -{ - const auto size = GetOutlineTextMetrics(hdc, 0, nullptr); - auto otm = reinterpret_cast(malloc(size)); - GetOutlineTextMetrics(hdc, size, otm); - return otm; -} - -bool QWindowsFontEngine::hasCFFTable() const -{ - HDC hdc = m_fontEngineData->hdc; - SelectObject(hdc, hfont); - return GetFontData(hdc, MAKE_LITTLE_ENDIAN_TAG('C', 'F', 'F', ' '), 0, 0, 0) != GDI_ERROR; -} - -bool QWindowsFontEngine::hasCMapTable() const -{ - HDC hdc = m_fontEngineData->hdc; - SelectObject(hdc, hfont); - return GetFontData(hdc, MAKE_LITTLE_ENDIAN_TAG('c', 'm', 'a', 'p'), 0, 0, 0) != GDI_ERROR; -} - -static inline QString stringFromOutLineTextMetric(const OUTLINETEXTMETRIC *otm, PSTR offset) -{ - const uchar *p = reinterpret_cast(otm) + quintptr(offset); - return QString::fromWCharArray(reinterpret_cast(p)); -} - -void QWindowsFontEngine::getCMap() -{ - ttf = (bool)(tm.tmPitchAndFamily & TMPF_TRUETYPE) || hasCMapTable(); - - cffTable = hasCFFTable(); - - HDC hdc = m_fontEngineData->hdc; - SelectObject(hdc, hfont); - bool symb = false; - if (ttf) { - cmapTable = getSfntTable(MAKE_TAG('c', 'm', 'a', 'p')); - cmap = QFontEngine::getCMap(reinterpret_cast(cmapTable.constData()), - cmapTable.size(), &symb, &cmapSize); - } - if (!cmap) { - ttf = false; - symb = false; - } - symbol = symb; - designToDevice = 1; - _faceId.index = 0; - if(cmap) { - OUTLINETEXTMETRIC *otm = getOutlineTextMetric(hdc); - unitsPerEm = int(otm->otmEMSquare); - const QFixed unitsPerEmF(unitsPerEm); - designToDevice = unitsPerEmF / QFixed::fromReal(fontDef.pixelSize); - x_height = int(otm->otmsXHeight); - loadKerningPairs(designToDevice); - _faceId.filename = QFile::encodeName(stringFromOutLineTextMetric(otm, otm->otmpFullName)); - lineWidth = otm->otmsUnderscoreSize; - fsType = otm->otmfsType; - free(otm); - - } else { - unitsPerEm = tm.tmHeight; - } -} - -int QWindowsFontEngine::getGlyphIndexes(const QChar *str, int numChars, QGlyphLayout *glyphs) const -{ - int glyph_pos = 0; - { - if (symbol) { - QStringIterator it(str, str + numChars); - while (it.hasNext()) { - const uint uc = it.next(); - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc); - if(!glyphs->glyphs[glyph_pos] && uc < 0x100) - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000); - ++glyph_pos; - } - } else if (ttf) { - QStringIterator it(str, str + numChars); - while (it.hasNext()) { - const uint uc = it.next(); - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc); - ++glyph_pos; - } - } else { - QStringIterator it(str, str + numChars); - while (it.hasNext()) { - const uint uc = it.next(); - if (uc >= tm.tmFirstChar && uc <= tm.tmLastChar) - glyphs->glyphs[glyph_pos] = uc; - else - glyphs->glyphs[glyph_pos] = 0; - ++glyph_pos; - } - } - } - glyphs->numGlyphs = glyph_pos; - return glyph_pos; -} - -/*! - \class QWindowsFontEngine - \brief Standard Windows font engine. - \internal - - Will probably be superseded by a common Free Type font engine in Qt 5.X. -*/ - -QWindowsFontEngine::QWindowsFontEngine(const QString &name, - LOGFONT lf, - const QSharedPointer &fontEngineData) - : QFontEngine(Win), - m_fontEngineData(fontEngineData), - _name(name), - m_logfont(lf), - ttf(0), - hasOutline(0) -{ - qCDebug(lcQpaFonts) << __FUNCTION__ << name << lf.lfHeight; - hfont = CreateFontIndirect(&m_logfont); - if (!hfont) { - qErrnoWarning("%s: CreateFontIndirect failed for family '%s'", __FUNCTION__, qPrintable(name)); - hfont = QWindowsFontDatabase::systemFont(); - } - - HDC hdc = m_fontEngineData->hdc; - SelectObject(hdc, hfont); - const BOOL res = GetTextMetrics(hdc, &tm); - if (!res) { - qErrnoWarning("%s: GetTextMetrics failed", __FUNCTION__); - ZeroMemory(&tm, sizeof(TEXTMETRIC)); - } - - fontDef.pixelSize = -lf.lfHeight; - fontDef.fixedPitch = !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH); - - cache_cost = tm.tmHeight * tm.tmAveCharWidth * 2000; - getCMap(); - - if (!resolvedGetCharWidthI) - resolveGetCharWidthI(); - - // ### Properties accessed by QWin32PrintEngine (QtPrintSupport) - QVariantMap userData; - userData.insert(QStringLiteral("logFont"), QVariant::fromValue(m_logfont)); - userData.insert(QStringLiteral("hFont"), QVariant::fromValue(hfont)); - userData.insert(QStringLiteral("trueType"), QVariant(bool(ttf))); - setUserData(userData); - - hasUnreliableOutline = (tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR)) == 0; -} - -QWindowsFontEngine::~QWindowsFontEngine() -{ - if (designAdvances) - free(designAdvances); - - if (widthCache) - free(widthCache); - - // make sure we aren't by accident still selected - SelectObject(m_fontEngineData->hdc, QWindowsFontDatabase::systemFont()); - - if (!DeleteObject(hfont)) - qErrnoWarning("%s: QFontEngineWin: failed to delete font...", __FUNCTION__); - qCDebug(lcQpaFonts) << __FUNCTION__ << _name; - - if (!uniqueFamilyName.isEmpty()) { - if (QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration()) { - QPlatformFontDatabase *pfdb = pi->fontDatabase(); - static_cast(pfdb)->derefUniqueFont(uniqueFamilyName); - } - } -} - -glyph_t QWindowsFontEngine::glyphIndex(uint ucs4) const -{ - glyph_t glyph = 0; - - if (symbol) { - glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4); - if (glyph == 0 && ucs4 < 0x100) - glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4 + 0xf000); - } else if (ttf) { - glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4); - } else if (ucs4 >= tm.tmFirstChar && ucs4 <= tm.tmLastChar) { - glyph = ucs4; - } - - return glyph; -} - -HGDIOBJ QWindowsFontEngine::selectDesignFont() const -{ - LOGFONT f = m_logfont; - f.lfHeight = -unitsPerEm; - f.lfWidth = 0; - HFONT designFont = CreateFontIndirect(&f); - return SelectObject(m_fontEngineData->hdc, designFont); -} - -bool QWindowsFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QFontEngine::ShaperFlags flags) const -{ - Q_ASSERT(glyphs->numGlyphs >= *nglyphs); - if (*nglyphs < len) { - *nglyphs = len; - return false; - } - - glyphs->numGlyphs = *nglyphs; - *nglyphs = getGlyphIndexes(str, len, glyphs); - - if (!(flags & GlyphIndicesOnly)) - recalcAdvances(glyphs, flags); - - return true; -} - -inline void calculateTTFGlyphWidth(HDC hdc, UINT glyph, int &width) -{ - if (ptrGetCharWidthI) - ptrGetCharWidthI(hdc, glyph, 1, 0, &width); -} - -void QWindowsFontEngine::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags flags) const -{ - HGDIOBJ oldFont = 0; - HDC hdc = m_fontEngineData->hdc; - if (ttf && (flags & DesignMetrics)) { - for(int i = 0; i < glyphs->numGlyphs; i++) { - unsigned int glyph = glyphs->glyphs[i]; - if(int(glyph) >= designAdvancesSize) { - const int newSize = int(glyph + 256) >> 8 << 8; - designAdvances = reinterpret_cast(realloc(designAdvances, size_t(newSize) * sizeof(QFixed))); - Q_CHECK_PTR(designAdvances); - for(int i = designAdvancesSize; i < newSize; ++i) - designAdvances[i] = -1000000; - designAdvancesSize = newSize; - } - if (designAdvances[glyph] < -999999) { - if (!oldFont) - oldFont = selectDesignFont(); - - int width = 0; - calculateTTFGlyphWidth(hdc, glyph, width); - designAdvances[glyph] = QFixed(width) / designToDevice; - } - glyphs->advances[i] = designAdvances[glyph]; - } - if(oldFont) - DeleteObject(SelectObject(hdc, oldFont)); - } else { - for(int i = 0; i < glyphs->numGlyphs; i++) { - unsigned int glyph = glyphs->glyphs[i]; - - if (glyph >= widthCacheSize) { - const uint newSize = (glyph + 256) >> 8 << 8; - widthCache = reinterpret_cast(realloc(widthCache, newSize * sizeof(QFixed))); - Q_CHECK_PTR(widthCache); - memset(widthCache + widthCacheSize, 0, newSize - widthCacheSize); - widthCacheSize = newSize; - } - glyphs->advances[i] = widthCache[glyph]; - // font-width cache failed - if (glyphs->advances[i].value() == 0) { - int width = 0; - if (!oldFont) - oldFont = SelectObject(hdc, hfont); - - if (!ttf) { - QChar ch[2] = { ushort(glyph), 0 }; - int chrLen = 1; - if (QChar::requiresSurrogates(glyph)) { - ch[0] = QChar::highSurrogate(glyph); - ch[1] = QChar::lowSurrogate(glyph); - ++chrLen; - } - SIZE size = {0, 0}; - GetTextExtentPoint32(hdc, reinterpret_cast(ch), chrLen, &size); - width = size.cx; - } else { - calculateTTFGlyphWidth(hdc, glyph, width); - } - glyphs->advances[i] = width; - // if glyph's within cache range, store it for later - if (width > 0 && width < 0x100) - widthCache[glyph] = uchar(width); - } - } - - if (oldFont) - SelectObject(hdc, oldFont); - } -} - -glyph_metrics_t QWindowsFontEngine::boundingBox(const QGlyphLayout &glyphs) -{ - if (glyphs.numGlyphs == 0) - return glyph_metrics_t(); - - QFixed w = 0; - for (int i = 0; i < glyphs.numGlyphs; ++i) - w += glyphs.effectiveAdvance(i); - - return glyph_metrics_t(0, -tm.tmAscent, w - lastRightBearing(glyphs), tm.tmHeight, w, 0); -} - -bool QWindowsFontEngine::getOutlineMetrics(glyph_t glyph, const QTransform &t, glyph_metrics_t *metrics) const -{ - Q_ASSERT(metrics != 0); - - HDC hdc = m_fontEngineData->hdc; - - GLYPHMETRICS gm; - DWORD res = 0; - MAT2 mat; - mat.eM11.value = mat.eM22.value = 1; - mat.eM11.fract = mat.eM22.fract = 0; - mat.eM21.value = mat.eM12.value = 0; - mat.eM21.fract = mat.eM12.fract = 0; - - if (t.type() > QTransform::TxTranslate) { - // We need to set the transform using the HDC's world - // matrix rather than using the MAT2 above, because the - // results provided when transforming via MAT2 does not - // match the glyphs that are drawn using a WorldTransform - XFORM xform; - xform.eM11 = FLOAT(t.m11()); - xform.eM12 = FLOAT(t.m12()); - xform.eM21 = FLOAT(t.m21()); - xform.eM22 = FLOAT(t.m22()); - xform.eDx = 0; - xform.eDy = 0; - SetGraphicsMode(hdc, GM_ADVANCED); - SetWorldTransform(hdc, &xform); - } - - uint format = GGO_METRICS; - if (ttf) - format |= GGO_GLYPH_INDEX; - res = GetGlyphOutline(hdc, glyph, format, &gm, 0, 0, &mat); - - if (t.type() > QTransform::TxTranslate) { - XFORM xform; - xform.eM11 = xform.eM22 = 1; - xform.eM12 = xform.eM21 = xform.eDx = xform.eDy = 0; - SetWorldTransform(hdc, &xform); - SetGraphicsMode(hdc, GM_COMPATIBLE); - } - - if (res != GDI_ERROR) { - *metrics = glyph_metrics_t(gm.gmptGlyphOrigin.x, -gm.gmptGlyphOrigin.y, - int(gm.gmBlackBoxX), int(gm.gmBlackBoxY), - gm.gmCellIncX, gm.gmCellIncY); - return true; - } else { - return false; - } -} - -glyph_metrics_t QWindowsFontEngine::boundingBox(glyph_t glyph, const QTransform &t) -{ - HDC hdc = m_fontEngineData->hdc; - SelectObject(hdc, hfont); - - glyph_metrics_t glyphMetrics; - bool success = getOutlineMetrics(glyph, t, &glyphMetrics); - - if (!ttf && !success) { - // Bitmap fonts - wchar_t ch = wchar_t(glyph); - ABCFLOAT abc; - GetCharABCWidthsFloat(hdc, ch, ch, &abc); - int width = qRound(abc.abcfB); - - return glyph_metrics_t(QFixed::fromReal(abc.abcfA), -tm.tmAscent, width, tm.tmHeight, width, 0).transformed(t); - } - - return glyphMetrics; -} - -namespace { -# pragma pack(1) - - struct OS2Table - { - quint16 version; - qint16 avgCharWidth; - quint16 weightClass; - quint16 widthClass; - quint16 type; - qint16 subscriptXSize; - qint16 subscriptYSize; - qint16 subscriptXOffset; - qint16 subscriptYOffset; - qint16 superscriptXSize; - qint16 superscriptYSize; - qint16 superscriptXOffset; - qint16 superscriptYOffset; - qint16 strikeOutSize; - qint16 strikeOutPosition; - qint16 familyClass; - quint8 panose[10]; - quint32 unicodeRanges[4]; - quint8 vendorID[4]; - quint16 selection; - quint16 firstCharIndex; - quint16 lastCharIndex; - qint16 typoAscender; - qint16 typoDescender; - qint16 typoLineGap; - quint16 winAscent; - quint16 winDescent; - quint32 codepageRanges[2]; - qint16 height; - qint16 capHeight; - quint16 defaultChar; - quint16 breakChar; - quint16 maxContext; - }; - -# pragma pack() -} - -QFixed QWindowsFontEngine::capHeight() const -{ - const QByteArray tableData = getSfntTable(MAKE_TAG('O', 'S', '/', '2')); - if (size_t(tableData.size()) >= sizeof(OS2Table)) { - const OS2Table *table = reinterpret_cast(tableData.constData()); - if (qFromBigEndian(table->version) >= 2) { - qint16 capHeight = qFromBigEndian(table->capHeight); - if (capHeight > 0) - return QFixed(capHeight) / designToDevice; - } - } - return calculatedCapHeight(); -} - -QFixed QWindowsFontEngine::xHeight() const -{ - if(x_height >= 0) - return x_height; - return QFontEngine::xHeight(); -} - -QFixed QWindowsFontEngine::averageCharWidth() const -{ - return tm.tmAveCharWidth; -} - -qreal QWindowsFontEngine::maxCharWidth() const -{ - return tm.tmMaxCharWidth; -} - -enum { max_font_count = 256 }; -static const ushort char_table[] = { - 40, - 67, - 70, - 75, - 86, - 88, - 89, - 91, - 102, - 114, - 124, - 127, - 205, - 645, - 884, - 922, - 1070, - 12386, - 0 -}; - -static const int char_table_entries = sizeof(char_table)/sizeof(ushort); - -#ifndef Q_CC_MINGW -void QWindowsFontEngine::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing) -{ - HDC hdc = m_fontEngineData->hdc; - SelectObject(hdc, hfont); - - if (ttf) { - ABC abcWidths; - GetCharABCWidthsI(hdc, glyph, 1, 0, &abcWidths); - if (leftBearing) - *leftBearing = abcWidths.abcA; - if (rightBearing) - *rightBearing = abcWidths.abcC; - } else { - QFontEngine::getGlyphBearings(glyph, leftBearing, rightBearing); - } -} -#endif // Q_CC_MINGW - -void QWindowsFontEngine::initializeHeightMetrics() const -{ - m_ascent = tm.tmAscent; - m_descent = tm.tmDescent; - m_leading = tm.tmExternalLeading; - - QFontEngine::initializeHeightMetrics(); -} - -bool QWindowsFontEngine::hasUnreliableGlyphOutline() const -{ - return hasUnreliableOutline || QFontEngine::hasUnreliableGlyphOutline(); -} - -qreal QWindowsFontEngine::minLeftBearing() const -{ - if (lbearing == SHRT_MIN) - minRightBearing(); // calculates both - - return lbearing; -} - -qreal QWindowsFontEngine::minRightBearing() const -{ - if (rbearing == SHRT_MIN) { - int ml = 0; - int mr = 0; - HDC hdc = m_fontEngineData->hdc; - SelectObject(hdc, hfont); - if (ttf) { - ABC *abc = 0; - int n = tm.tmLastChar - tm.tmFirstChar; - if (n <= max_font_count) { - abc = new ABC[n+1]; - GetCharABCWidths(hdc, tm.tmFirstChar, tm.tmLastChar, abc); - } else { - abc = new ABC[char_table_entries+1]; - for(int i = 0; i < char_table_entries; i++) - GetCharABCWidths(hdc, char_table[i], char_table[i], abc + i); - n = char_table_entries; - } - ml = abc[0].abcA; - mr = abc[0].abcC; - for (int i = 1; i < n; i++) { - if (abc[i].abcA + abc[i].abcB + abc[i].abcC != 0) { - ml = qMin(ml,abc[i].abcA); - mr = qMin(mr,abc[i].abcC); - } - } - delete [] abc; - } else { - ABCFLOAT *abc = 0; - int n = tm.tmLastChar - tm.tmFirstChar+1; - if (n <= max_font_count) { - abc = new ABCFLOAT[n]; - GetCharABCWidthsFloat(hdc, tm.tmFirstChar, tm.tmLastChar, abc); - } else { - abc = new ABCFLOAT[char_table_entries]; - for(int i = 0; i < char_table_entries; i++) - GetCharABCWidthsFloat(hdc, char_table[i], char_table[i], abc+i); - n = char_table_entries; - } - float fml = abc[0].abcfA; - float fmr = abc[0].abcfC; - for (int i=1; i(dataBuffer + headerOffset); - - QPointF lastPoint(qt_to_qpointf(ttph->pfxStart, scale, stretch)); - path->moveTo(lastPoint + oset); - offset += sizeof(TTPOLYGONHEADER); - while (offset < headerOffset + ttph->cb) { - const TTPOLYCURVE *curve = reinterpret_cast(dataBuffer + offset); - switch (curve->wType) { - case TT_PRIM_LINE: { - for (int i=0; icpfx; ++i) { - QPointF p = qt_to_qpointf(curve->apfx[i], scale, stretch) + oset; - path->lineTo(p); - } - break; - } - case TT_PRIM_QSPLINE: { - const QPainterPath::Element &elm = path->elementAt(path->elementCount()-1); - QPointF prev(elm.x, elm.y); - QPointF endPoint; - for (int i=0; icpfx - 1; ++i) { - QPointF p1 = qt_to_qpointf(curve->apfx[i], scale, stretch) + oset; - QPointF p2 = qt_to_qpointf(curve->apfx[i+1], scale, stretch) + oset; - if (i < curve->cpfx - 2) { - endPoint = QPointF((p1.x() + p2.x()) / 2, (p1.y() + p2.y()) / 2); - } else { - endPoint = p2; - } - - path->quadTo(p1, endPoint); - prev = endPoint; - } - - break; - } - case TT_PRIM_CSPLINE: { - for (int i=0; icpfx; ) { - QPointF p2 = qt_to_qpointf(curve->apfx[i++], scale, stretch) + oset; - QPointF p3 = qt_to_qpointf(curve->apfx[i++], scale, stretch) + oset; - QPointF p4 = qt_to_qpointf(curve->apfx[i++], scale, stretch) + oset; - path->cubicTo(p2, p3, p4); - } - break; - } - default: - qWarning("QFontEngineWin::addOutlineToPath, unhandled switch case"); - } - offset += sizeof(TTPOLYCURVE) + (curve->cpfx-1) * sizeof(POINTFX); - } - path->closeSubpath(); - headerOffset += ttph->cb; - } - delete [] dataBuffer; - - return true; -} - -void QWindowsFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, - QPainterPath *path, QTextItem::RenderFlags) -{ - LOGFONT lf = m_logfont; - // The sign must be negative here to make sure we match against character height instead of - // hinted cell height. This ensures that we get linear matching, and we need this for - // paths since we later on apply a scaling transform to the glyph outline to get the - // font at the correct pixel size. - lf.lfHeight = -unitsPerEm; - lf.lfWidth = 0; - HFONT hf = CreateFontIndirect(&lf); - HDC hdc = m_fontEngineData->hdc; - HGDIOBJ oldfont = SelectObject(hdc, hf); - - qreal scale = qreal(fontDef.pixelSize) / unitsPerEm; - qreal stretch = fontDef.stretch ? qreal(fontDef.stretch) / 100 : 1.0; - for(int i = 0; i < nglyphs; ++i) { - if (!addGlyphToPath(glyphs[i], positions[i], hdc, path, ttf, /*metric*/0, - scale, stretch)) { - // Some windows fonts, like "Modern", are vector stroke - // fonts, which are reported as TMPF_VECTOR but do not - // support GetGlyphOutline, and thus we set this bit so - // that addOutLineToPath can check it and return safely... - hasOutline = false; - break; - } - } - DeleteObject(SelectObject(hdc, oldfont)); -} - -void QWindowsFontEngine::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, - QPainterPath *path, QTextItem::RenderFlags flags) -{ - if(tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR)) { - hasOutline = true; - QFontEngine::addOutlineToPath(x, y, glyphs, path, flags); - if (hasOutline) { - // has_outline is set to false if addGlyphToPath gets - // false from GetGlyphOutline, meaning its not an outline - // font. - return; - } - } - QFontEngine::addBitmapFontToPath(x, y, glyphs, path, flags); -} - -QFontEngine::FaceId QWindowsFontEngine::faceId() const -{ - return _faceId; -} - -QT_BEGIN_INCLUDE_NAMESPACE -#include -QT_END_INCLUDE_NAMESPACE - -int QWindowsFontEngine::synthesized() const -{ - if(synthesized_flags == -1) { - synthesized_flags = 0; - if(ttf) { - const DWORD HEAD = MAKE_LITTLE_ENDIAN_TAG('h', 'e', 'a', 'd'); - HDC hdc = m_fontEngineData->hdc; - SelectObject(hdc, hfont); - uchar data[4]; - GetFontData(hdc, HEAD, 44, &data, 4); - USHORT macStyle = qt_getUShort(data); - if (tm.tmItalic && !(macStyle & 2)) - synthesized_flags = SynthesizedItalic; - if (fontDef.stretch != 100 && ttf) - synthesized_flags |= SynthesizedStretch; - if (tm.tmWeight >= 500 && tm.tmWeight < 750 && !(macStyle & 1)) - synthesized_flags |= SynthesizedBold; - //qDebug() << "font is" << _name << - // "it=" << (macStyle & 2) << fontDef.style << "flags=" << synthesized_flags; - } - } - return synthesized_flags; -} - -QFixed QWindowsFontEngine::emSquareSize() const -{ - return unitsPerEm; -} - -QFontEngine::Properties QWindowsFontEngine::properties() const -{ - LOGFONT lf = m_logfont; - lf.lfHeight = unitsPerEm; - HFONT hf = CreateFontIndirect(&lf); - HDC hdc = m_fontEngineData->hdc; - HGDIOBJ oldfont = SelectObject(hdc, hf); - OUTLINETEXTMETRIC *otm = getOutlineTextMetric(hdc); - Properties p; - p.emSquare = unitsPerEm; - p.italicAngle = otm->otmItalicAngle; - const QByteArray name = stringFromOutLineTextMetric(otm, otm->otmpFamilyName).toLatin1() - + stringFromOutLineTextMetric(otm, otm->otmpStyleName).toLatin1(); - p.postscriptName = QFontEngine::convertToPostscriptFontFamilyName(name); - p.boundingBox = QRectF(otm->otmrcFontBox.left, -otm->otmrcFontBox.top, - otm->otmrcFontBox.right - otm->otmrcFontBox.left, - otm->otmrcFontBox.top - otm->otmrcFontBox.bottom); - p.ascent = otm->otmAscent; - p.descent = -otm->otmDescent; - p.leading = int(otm->otmLineGap); - p.capHeight = 0; - p.lineWidth = otm->otmsUnderscoreSize; - free(otm); - DeleteObject(SelectObject(hdc, oldfont)); - return p; -} - -void QWindowsFontEngine::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) -{ - LOGFONT lf = m_logfont; - lf.lfHeight = -unitsPerEm; - int flags = synthesized(); - if(flags & SynthesizedItalic) - lf.lfItalic = false; - lf.lfWidth = 0; - HFONT hf = CreateFontIndirect(&lf); - HDC hdc = m_fontEngineData->hdc; - HGDIOBJ oldfont = SelectObject(hdc, hf); - QFixedPoint p; - p.x = 0; - p.y = 0; - addGlyphToPath(glyph, p, hdc, path, ttf, metrics); - DeleteObject(SelectObject(hdc, oldfont)); -} - -bool QWindowsFontEngine::getSfntTableData(uint tag, uchar *buffer, uint *length) const -{ - if (!ttf && !cffTable) - return false; - HDC hdc = m_fontEngineData->hdc; - SelectObject(hdc, hfont); - DWORD t = qbswap(tag); - *length = GetFontData(hdc, t, 0, buffer, *length); - Q_ASSERT(*length == GDI_ERROR || int(*length) > 0); - return *length != GDI_ERROR; -} - -#if !defined(CLEARTYPE_QUALITY) -# define CLEARTYPE_QUALITY 5 -#endif - -QWindowsNativeImage *QWindowsFontEngine::drawGDIGlyph(HFONT font, glyph_t glyph, int margin, - const QTransform &t, - QImage::Format mask_format) -{ - Q_UNUSED(mask_format) - glyph_metrics_t gm = boundingBox(glyph); - -// printf(" -> for glyph %4x\n", glyph); - - int gx = gm.x.toInt(); - int gy = gm.y.toInt(); - int iw = gm.width.toInt(); - int ih = gm.height.toInt(); - - if (iw <= 0 || ih <= 0) - return 0; - - bool has_transformation = t.type() > QTransform::TxTranslate; - - unsigned int options = ttf ? ETO_GLYPH_INDEX : 0; - XFORM xform; - - if (has_transformation) { - xform.eM11 = FLOAT(t.m11()); - xform.eM12 = FLOAT(t.m12()); - xform.eM21 = FLOAT(t.m21()); - xform.eM22 = FLOAT(t.m22()); - xform.eDx = margin; - xform.eDy = margin; - - const HDC hdc = m_fontEngineData->hdc; - - SetGraphicsMode(hdc, GM_ADVANCED); - SetWorldTransform(hdc, &xform); - HGDIOBJ old_font = SelectObject(hdc, font); - - const UINT ggo_options = GGO_METRICS | (ttf ? GGO_GLYPH_INDEX : 0); - GLYPHMETRICS tgm; - MAT2 mat; - memset(&mat, 0, sizeof(mat)); - mat.eM11.value = mat.eM22.value = 1; - - const DWORD result = GetGlyphOutline(hdc, glyph, ggo_options, &tgm, 0, 0, &mat); - - XFORM identity = {1, 0, 0, 1, 0, 0}; - SetWorldTransform(hdc, &identity); - SetGraphicsMode(hdc, GM_COMPATIBLE); - SelectObject(hdc, old_font); - - if (result == GDI_ERROR) { - const int errorCode = int(GetLastError()); - qErrnoWarning(errorCode, "QWinFontEngine: unable to query transformed glyph metrics (GetGlyphOutline() failed, error %d)...", errorCode); - return 0; - } - - iw = int(tgm.gmBlackBoxX); - ih = int(tgm.gmBlackBoxY); - - xform.eDx -= tgm.gmptGlyphOrigin.x; - xform.eDy += tgm.gmptGlyphOrigin.y; - } - - // The padding here needs to be kept in sync with the values in alphaMapBoundingBox. - QWindowsNativeImage *ni = new QWindowsNativeImage(iw + 2 * margin, - ih + 2 * margin, - QWindowsNativeImage::systemFormat()); - - /*If cleartype is enabled we use the standard system format even on Windows CE - and not the special textbuffer format we have to use if cleartype is disabled*/ - - ni->image().fill(0xffffffff); - - HDC hdc = ni->hdc(); - - SelectObject(hdc, GetStockObject(NULL_BRUSH)); - SelectObject(hdc, GetStockObject(BLACK_PEN)); - SetTextColor(hdc, RGB(0,0,0)); - SetBkMode(hdc, TRANSPARENT); - SetTextAlign(hdc, TA_BASELINE); - - HGDIOBJ old_font = SelectObject(hdc, font); - - if (has_transformation) { - SetGraphicsMode(hdc, GM_ADVANCED); - SetWorldTransform(hdc, &xform); - ExtTextOut(hdc, 0, 0, options, 0, reinterpret_cast(&glyph), 1, 0); - } else { - ExtTextOut(hdc, -gx + margin, -gy + margin, options, 0, reinterpret_cast(&glyph), 1, 0); - } - - SelectObject(hdc, old_font); - return ni; -} - -glyph_metrics_t QWindowsFontEngine::alphaMapBoundingBox(glyph_t glyph, QFixed, const QTransform &matrix, GlyphFormat format) -{ - int margin = 0; - if (format == QFontEngine::Format_A32 || format == QFontEngine::Format_ARGB) - margin = glyphMargin(QFontEngine::Format_A32); - glyph_metrics_t gm = boundingBox(glyph, matrix); - gm.width += margin * 2; - gm.height += margin * 2; - return gm; -} - -QImage QWindowsFontEngine::alphaMapForGlyph(glyph_t glyph, const QTransform &xform) -{ - HFONT font = hfont; - - bool clearTypeTemporarilyDisabled = (m_fontEngineData->clearTypeEnabled && m_logfont.lfQuality != NONANTIALIASED_QUALITY); - if (clearTypeTemporarilyDisabled) { - LOGFONT lf = m_logfont; - lf.lfQuality = ANTIALIASED_QUALITY; - font = CreateFontIndirect(&lf); - } - QImage::Format mask_format = QWindowsNativeImage::systemFormat(); - mask_format = QImage::Format_RGB32; - - const QWindowsNativeImage *mask = drawGDIGlyph(font, glyph, 0, xform, mask_format); - if (mask == 0) { - if (m_fontEngineData->clearTypeEnabled) - DeleteObject(font); - return QImage(); - } - - QImage alphaMap(mask->width(), mask->height(), QImage::Format_Alpha8); - - - // Copy data... Cannot use QPainter here as GDI has messed up the - // Alpha channel of the ni.image pixels... - for (int y=0; yheight(); ++y) { - uchar *dest = alphaMap.scanLine(y); - if (mask->image().format() == QImage::Format_RGB16) { - const qint16 *src = reinterpret_cast(mask->image().constScanLine(y)); - for (int x=0; xwidth(); ++x) - dest[x] = 255 - qGray(src[x]); - } else { - const uint *src = reinterpret_cast(mask->image().constScanLine(y)); - for (int x=0; xwidth(); ++x) { - if (QWindowsNativeImage::systemFormat() == QImage::Format_RGB16) - dest[x] = 255 - qGray(src[x]); - else - dest[x] = 255 - (m_fontEngineData->pow_gamma[qGray(src[x])] * 255. / 2047.); - } - } - } - - // Cleanup... - delete mask; - if (clearTypeTemporarilyDisabled) { - DeleteObject(font); - } - - return alphaMap; -} - -#define SPI_GETFONTSMOOTHINGCONTRAST 0x200C -#define SPI_SETFONTSMOOTHINGCONTRAST 0x200D - -QImage QWindowsFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed, const QTransform &t) -{ - HFONT font = hfont; - - UINT contrast; - SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &contrast, 0); - SystemParametersInfo(SPI_SETFONTSMOOTHINGCONTRAST, 0, reinterpret_cast(quintptr(1000)), 0); - - int margin = glyphMargin(QFontEngine::Format_A32); - QWindowsNativeImage *mask = drawGDIGlyph(font, glyph, margin, t, QImage::Format_RGB32); - SystemParametersInfo(SPI_SETFONTSMOOTHINGCONTRAST, 0, reinterpret_cast(quintptr(contrast)), 0); - - if (mask == 0) - return QImage(); - - // Gracefully handle the odd case when the display is 16-bit - const QImage source = mask->image().depth() == 32 - ? mask->image() - : mask->image().convertToFormat(QImage::Format_RGB32); - - QImage rgbMask(mask->width(), mask->height(), QImage::Format_RGB32); - for (int y=0; yheight(); ++y) { - auto dest = reinterpret_cast(rgbMask.scanLine(y)); - const uint *src = reinterpret_cast(source.constScanLine(y)); - for (int x=0; xwidth(); ++x) { - dest[x] = 0xffffffff - (0x00ffffff & src[x]); - } - } - - delete mask; - - return rgbMask; -} - -QFontEngine *QWindowsFontEngine::cloneWithSize(qreal pixelSize) const -{ - QFontDef request = fontDef; - QString actualFontName = request.family; - if (!uniqueFamilyName.isEmpty()) - request.family = uniqueFamilyName; - request.pixelSize = pixelSize; - const QString faceName = QString::fromWCharArray(m_logfont.lfFaceName); - - QFontEngine *fontEngine = - QWindowsFontDatabase::createEngine(request, faceName, - QWindowsFontDatabase::defaultVerticalDPI(), - m_fontEngineData); - if (fontEngine) { - fontEngine->fontDef.family = actualFontName; - if (!uniqueFamilyName.isEmpty()) { - static_cast(fontEngine)->setUniqueFamilyName(uniqueFamilyName); - if (QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration()) { - QPlatformFontDatabase *pfdb = pi->fontDatabase(); - static_cast(pfdb)->refUniqueFont(uniqueFamilyName); - } - } - } - return fontEngine; -} - -Qt::HANDLE QWindowsFontEngine::handle() const -{ - return hfont; -} - -void QWindowsFontEngine::initFontInfo(const QFontDef &request, - int dpi) -{ - fontDef = request; // most settings are equal - HDC dc = m_fontEngineData->hdc; - SelectObject(dc, hfont); - wchar_t n[64]; - GetTextFace(dc, 64, n); - fontDef.family = QString::fromWCharArray(n); - fontDef.fixedPitch = !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH); - if (fontDef.pointSize < 0) { - fontDef.pointSize = fontDef.pixelSize * 72. / dpi; - } else if (fontDef.pixelSize == -1) { - fontDef.pixelSize = qRound(fontDef.pointSize * dpi / 72.); - } -} - -bool QWindowsFontEngine::supportsTransformation(const QTransform &transform) const -{ - // Support all transformations for ttf files, and translations for raster fonts - return ttf || transform.type() <= QTransform::TxTranslate; -} - -QT_END_NAMESPACE diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h deleted file mode 100644 index 8a676affcd..0000000000 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h +++ /dev/null @@ -1,175 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module 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$ -** -****************************************************************************/ - -#ifndef QWINDOWSFONTENGINE_H -#define QWINDOWSFONTENGINE_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -#include -#include -#include - -#include - -QT_BEGIN_NAMESPACE - -class QWindowsNativeImage; -class QWindowsFontEngineData; - -class QWindowsFontEngine : public QFontEngine -{ - Q_DISABLE_COPY_MOVE(QWindowsFontEngine) -public: - QWindowsFontEngine(const QString &name, LOGFONT lf, - const QSharedPointer &fontEngineData); - - ~QWindowsFontEngine() override; - void initFontInfo(const QFontDef &request, - int dpi); - - QFixed lineThickness() const override; - Properties properties() const override; - void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) override; - FaceId faceId() const override; - bool getSfntTableData(uint tag, uchar *buffer, uint *length) const override; - int synthesized() const override; - QFixed emSquareSize() const override; - - glyph_t glyphIndex(uint ucs4) const override; - bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const override; - void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags) const override; - - void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) override; - void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, - QPainterPath *path, QTextItem::RenderFlags flags) override; - - HGDIOBJ selectDesignFont() const; - - glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) override; - glyph_metrics_t boundingBox(glyph_t g) override { return boundingBox(g, QTransform()); } - glyph_metrics_t boundingBox(glyph_t g, const QTransform &t) override; - - - QFixed xHeight() const override; - QFixed capHeight() const override; - QFixed averageCharWidth() const override; - qreal maxCharWidth() const override; - qreal minLeftBearing() const override; - qreal minRightBearing() const override; - - QImage alphaMapForGlyph(glyph_t t) override { return alphaMapForGlyph(t, QTransform()); } - QImage alphaMapForGlyph(glyph_t, const QTransform &xform) override; - QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, const QTransform &xform) override; - glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed, const QTransform &matrix, GlyphFormat) override; - - QFontEngine *cloneWithSize(qreal pixelSize) const override; - Qt::HANDLE handle() const override; - bool supportsTransformation(const QTransform &transform) const override; - -#ifndef Q_CC_MINGW - void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0) override; -#endif - - bool hasUnreliableGlyphOutline() const override; - - int getGlyphIndexes(const QChar *ch, int numChars, QGlyphLayout *glyphs) const; - void getCMap(); - - bool getOutlineMetrics(glyph_t glyph, const QTransform &t, glyph_metrics_t *metrics) const; - - const QSharedPointer &fontEngineData() const { return m_fontEngineData; } - - void setUniqueFamilyName(const QString &newName) { uniqueFamilyName = newName; } - -protected: - void initializeHeightMetrics() const override; - -private: - QWindowsNativeImage *drawGDIGlyph(HFONT font, glyph_t, int margin, const QTransform &xform, - QImage::Format mask_format); - bool hasCFFTable() const; - bool hasCMapTable() const; - - const QSharedPointer m_fontEngineData; - - const QString _name; - QString uniqueFamilyName; - HFONT hfont = 0; - const LOGFONT m_logfont; - uint ttf : 1; - uint hasOutline : 1; - uint hasUnreliableOutline : 1; - uint cffTable : 1; - TEXTMETRIC tm; - const unsigned char *cmap = nullptr; - int cmapSize = 0; - QByteArray cmapTable; - mutable qreal lbearing = SHRT_MIN; - mutable qreal rbearing = SHRT_MIN; - QFixed designToDevice; - int unitsPerEm = 0; - QFixed x_height = -1; - FaceId _faceId; - - mutable int synthesized_flags = -1; - mutable QFixed lineWidth = -1; - mutable unsigned char *widthCache = nullptr; - mutable uint widthCacheSize = 0; - mutable QFixed *designAdvances = nullptr; - mutable int designAdvancesSize = 0; -}; - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(HFONT) -Q_DECLARE_METATYPE(LOGFONT) - -#endif // QWINDOWSFONTENGINE_H diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp deleted file mode 100644 index d96e65a532..0000000000 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp +++ /dev/null @@ -1,1030 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module 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$ -** -****************************************************************************/ - -#ifndef QT_NO_DIRECTWRITE - -#include "qwindowsfontenginedirectwrite_p.h" -#include "qwindowsfontdatabase_p.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(QT_USE_DIRECTWRITE2) -# include -#else -# include -#endif - -#include - -QT_BEGIN_NAMESPACE - -// Clang does not consider __declspec(nothrow) as nothrow -QT_WARNING_DISABLE_CLANG("-Wmicrosoft-exception-spec") - -// Convert from design units to logical pixels -#define DESIGN_TO_LOGICAL(DESIGN_UNIT_VALUE) \ - QFixed::fromReal((qreal(DESIGN_UNIT_VALUE) / qreal(m_unitsPerEm)) * fontDef.pixelSize) - -namespace { - - class GeometrySink: public IDWriteGeometrySink - { - Q_DISABLE_COPY_MOVE(GeometrySink) - public: - GeometrySink(QPainterPath *path) - : m_refCount(0), m_path(path) - { - Q_ASSERT(m_path != 0); - } - virtual ~GeometrySink() = default; - - IFACEMETHOD_(void, AddBeziers)(const D2D1_BEZIER_SEGMENT *beziers, UINT bezierCount); - IFACEMETHOD_(void, AddLines)(const D2D1_POINT_2F *points, UINT pointCount); - IFACEMETHOD_(void, BeginFigure)(D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN figureBegin); - IFACEMETHOD(Close)(); - IFACEMETHOD_(void, EndFigure)(D2D1_FIGURE_END figureEnd); - IFACEMETHOD_(void, SetFillMode)(D2D1_FILL_MODE fillMode); - IFACEMETHOD_(void, SetSegmentFlags)(D2D1_PATH_SEGMENT vertexFlags); - - IFACEMETHOD_(unsigned long, AddRef)(); - IFACEMETHOD_(unsigned long, Release)(); - IFACEMETHOD(QueryInterface)(IID const &riid, void **ppvObject); - - private: - inline static QPointF fromD2D1_POINT_2F(const D2D1_POINT_2F &inp) - { - return QPointF(inp.x, inp.y); - } - - unsigned long m_refCount; - QPointF m_startPoint; - QPainterPath *m_path; - }; - - void GeometrySink::AddBeziers(const D2D1_BEZIER_SEGMENT *beziers, - UINT bezierCount) - { - for (uint i=0; icubicTo(c1, c2, p2); - } - } - - void GeometrySink::AddLines(const D2D1_POINT_2F *points, UINT pointsCount) - { - for (uint i=0; ilineTo(fromD2D1_POINT_2F(points[i])); - } - - void GeometrySink::BeginFigure(D2D1_POINT_2F startPoint, - D2D1_FIGURE_BEGIN /*figureBegin*/) - { - m_startPoint = fromD2D1_POINT_2F(startPoint); - m_path->moveTo(m_startPoint); - } - - IFACEMETHODIMP GeometrySink::Close() - { - return E_NOTIMPL; - } - - void GeometrySink::EndFigure(D2D1_FIGURE_END figureEnd) - { - if (figureEnd == D2D1_FIGURE_END_CLOSED) - m_path->closeSubpath(); - } - - void GeometrySink::SetFillMode(D2D1_FILL_MODE fillMode) - { - m_path->setFillRule(fillMode == D2D1_FILL_MODE_ALTERNATE - ? Qt::OddEvenFill - : Qt::WindingFill); - } - - void GeometrySink::SetSegmentFlags(D2D1_PATH_SEGMENT /*vertexFlags*/) - { - /* Not implemented */ - } - - IFACEMETHODIMP_(unsigned long) GeometrySink::AddRef() - { - return InterlockedIncrement(&m_refCount); - } - - IFACEMETHODIMP_(unsigned long) GeometrySink::Release() - { - unsigned long newCount = InterlockedDecrement(&m_refCount); - if (newCount == 0) - { - delete this; - return 0; - } - - return newCount; - } - - IFACEMETHODIMP GeometrySink::QueryInterface(IID const &riid, void **ppvObject) - { - if (__uuidof(IDWriteGeometrySink) == riid) { - *ppvObject = this; - } else if (__uuidof(IUnknown) == riid) { - *ppvObject = this; - } else { - *ppvObject = NULL; - return E_FAIL; - } - - AddRef(); - return S_OK; - } - -} - -static DWRITE_MEASURING_MODE renderModeToMeasureMode(DWRITE_RENDERING_MODE renderMode) -{ - switch (renderMode) { - case DWRITE_RENDERING_MODE_GDI_CLASSIC: - return DWRITE_MEASURING_MODE_GDI_CLASSIC; - case DWRITE_RENDERING_MODE_GDI_NATURAL: - return DWRITE_MEASURING_MODE_GDI_NATURAL; - default: - return DWRITE_MEASURING_MODE_NATURAL; - } -} - -static DWRITE_RENDERING_MODE hintingPreferenceToRenderingMode(QFont::HintingPreference hintingPreference) -{ - if (QHighDpiScaling::isActive() && hintingPreference == QFont::PreferDefaultHinting) - hintingPreference = QFont::PreferVerticalHinting; - - switch (hintingPreference) { - case QFont::PreferNoHinting: - return DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC; - case QFont::PreferVerticalHinting: - return DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL; - default: - return DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC; - } -} - -/*! - \class QWindowsFontEngineDirectWrite - \brief Windows font engine using Direct Write. - \internal - - Font engine for subpixel positioned text on Windows Vista - (with platform update) and later. If selected during - configuration, the engine will be selected only when the hinting - preference of a font is set to None or Vertical hinting, or - when fontengine=directwrite is selected as platform option. -*/ - -QWindowsFontEngineDirectWrite::QWindowsFontEngineDirectWrite(IDWriteFontFace *directWriteFontFace, - qreal pixelSize, - const QSharedPointer &d) - : QFontEngine(DirectWrite) - , m_fontEngineData(d) - , m_directWriteFontFace(directWriteFontFace) - , m_directWriteBitmapRenderTarget(0) - , m_lineThickness(-1) - , m_unitsPerEm(-1) - , m_capHeight(-1) - , m_xHeight(-1) -{ - qCDebug(lcQpaFonts) << __FUNCTION__ << pixelSize; - - Q_ASSERT(m_directWriteFontFace); - - m_fontEngineData->directWriteFactory->AddRef(); - m_directWriteFontFace->AddRef(); - - fontDef.pixelSize = pixelSize; - collectMetrics(); - cache_cost = (m_ascent.toInt() + m_descent.toInt()) * m_xHeight.toInt() * 2000; -} - -QWindowsFontEngineDirectWrite::~QWindowsFontEngineDirectWrite() -{ - qCDebug(lcQpaFonts) << __FUNCTION__; - - m_fontEngineData->directWriteFactory->Release(); - m_directWriteFontFace->Release(); - - if (m_directWriteBitmapRenderTarget != 0) - m_directWriteBitmapRenderTarget->Release(); - - if (!m_uniqueFamilyName.isEmpty()) { - QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase(); - static_cast(pfdb)->derefUniqueFont(m_uniqueFamilyName); - } -} - -#ifndef Q_CC_MINGW -typedef IDWriteLocalFontFileLoader QIdWriteLocalFontFileLoader; - -static UUID uuidIdWriteLocalFontFileLoader() -{ - return __uuidof(IDWriteLocalFontFileLoader); -} -#else // !Q_CC_MINGW -DECLARE_INTERFACE_(QIdWriteLocalFontFileLoader, IDWriteFontFileLoader) -{ - STDMETHOD(GetFilePathLengthFromKey)(THIS_ void const *, UINT32, UINT32*) PURE; - STDMETHOD(GetFilePathFromKey)(THIS_ void const *, UINT32, WCHAR *, UINT32) PURE; - STDMETHOD(GetLastWriteTimeFromKey)(THIS_ void const *, UINT32, FILETIME *) PURE; -}; - -static UUID uuidIdWriteLocalFontFileLoader() -{ - static const UUID result = { 0xb2d9f3ec, 0xc9fe, 0x4a11, {0xa2, 0xec, 0xd8, 0x62, 0x8, 0xf7, 0xc0, 0xa2}}; - return result; -} -#endif // Q_CC_MINGW - -QString QWindowsFontEngineDirectWrite::filenameFromFontFile(IDWriteFontFile *fontFile) -{ - IDWriteFontFileLoader *loader = nullptr; - - HRESULT hr = fontFile->GetLoader(&loader); - if (FAILED(hr)) { - qErrnoWarning("%s: GetLoader failed", __FUNCTION__); - return QString(); - } - - QIdWriteLocalFontFileLoader *localLoader = nullptr; - hr = loader->QueryInterface(uuidIdWriteLocalFontFileLoader(), - reinterpret_cast(&localLoader)); - - const void *fontFileReferenceKey = nullptr; - UINT32 fontFileReferenceKeySize = 0; - if (SUCCEEDED(hr)) { - hr = fontFile->GetReferenceKey(&fontFileReferenceKey, - &fontFileReferenceKeySize); - if (FAILED(hr)) - qErrnoWarning(hr, "%s: GetReferenceKey failed", __FUNCTION__); - } - - UINT32 filePathLength = 0; - if (SUCCEEDED(hr)) { - hr = localLoader->GetFilePathLengthFromKey(fontFileReferenceKey, - fontFileReferenceKeySize, - &filePathLength); - if (FAILED(hr)) - qErrnoWarning(hr, "GetFilePathLength failed", __FUNCTION__); - } - - QString ret; - if (SUCCEEDED(hr) && filePathLength > 0) { - QVarLengthArray filePath(filePathLength + 1); - - hr = localLoader->GetFilePathFromKey(fontFileReferenceKey, - fontFileReferenceKeySize, - filePath.data(), - filePathLength + 1); - if (FAILED(hr)) - qErrnoWarning(hr, "%s: GetFilePathFromKey failed", __FUNCTION__); - else - ret = QString::fromWCharArray(filePath.data()); - } - - if (localLoader != nullptr) - localLoader->Release(); - - if (loader != nullptr) - loader->Release(); - return ret; -} - -void QWindowsFontEngineDirectWrite::initializeHeightMetrics() const -{ - DWRITE_FONT_METRICS metrics; - m_directWriteFontFace->GetMetrics(&metrics); - - m_ascent = DESIGN_TO_LOGICAL(metrics.ascent); - m_descent = DESIGN_TO_LOGICAL(metrics.descent); - m_leading = DESIGN_TO_LOGICAL(metrics.lineGap); - - QFontEngine::initializeHeightMetrics(); -} - -void QWindowsFontEngineDirectWrite::collectMetrics() -{ - DWRITE_FONT_METRICS metrics; - - m_directWriteFontFace->GetMetrics(&metrics); - m_unitsPerEm = metrics.designUnitsPerEm; - - m_lineThickness = DESIGN_TO_LOGICAL(metrics.underlineThickness); - m_capHeight = DESIGN_TO_LOGICAL(metrics.capHeight); - m_xHeight = DESIGN_TO_LOGICAL(metrics.xHeight); - m_underlinePosition = DESIGN_TO_LOGICAL(metrics.underlinePosition); - - IDWriteFontFile *fontFile = nullptr; - UINT32 numberOfFiles = 1; - if (SUCCEEDED(m_directWriteFontFace->GetFiles(&numberOfFiles, &fontFile))) { - m_faceId.filename = QFile::encodeName(filenameFromFontFile(fontFile)); - fontFile->Release(); - } - - QByteArray table = getSfntTable(MAKE_TAG('h', 'h', 'e', 'a')); - const int advanceWidthMaxLocation = 10; - if (table.size() >= advanceWidthMaxLocation + int(sizeof(quint16))) { - quint16 advanceWidthMax = qFromBigEndian(table.constData() + advanceWidthMaxLocation); - m_maxAdvanceWidth = DESIGN_TO_LOGICAL(advanceWidthMax); - } -} - -QFixed QWindowsFontEngineDirectWrite::underlinePosition() const -{ - if (m_underlinePosition > 0) - return m_underlinePosition; - else - return QFontEngine::underlinePosition(); -} - -QFixed QWindowsFontEngineDirectWrite::lineThickness() const -{ - if (m_lineThickness > 0) - return m_lineThickness; - else - return QFontEngine::lineThickness(); -} - -bool QWindowsFontEngineDirectWrite::getSfntTableData(uint tag, uchar *buffer, uint *length) const -{ - bool ret = false; - - const void *tableData = 0; - UINT32 tableSize; - void *tableContext = 0; - BOOL exists; - HRESULT hr = m_directWriteFontFace->TryGetFontTable(qbswap(tag), - &tableData, &tableSize, - &tableContext, &exists); - if (SUCCEEDED(hr)) { - if (exists) { - ret = true; - if (buffer && *length >= tableSize) - memcpy(buffer, tableData, tableSize); - *length = tableSize; - Q_ASSERT(int(*length) > 0); - } - m_directWriteFontFace->ReleaseFontTable(tableContext); - } else { - qErrnoWarning("%s: TryGetFontTable failed", __FUNCTION__); - } - - return ret; -} - -QFixed QWindowsFontEngineDirectWrite::emSquareSize() const -{ - if (m_unitsPerEm > 0) - return m_unitsPerEm; - else - return QFontEngine::emSquareSize(); -} - -glyph_t QWindowsFontEngineDirectWrite::glyphIndex(uint ucs4) const -{ - UINT16 glyphIndex; - - HRESULT hr = m_directWriteFontFace->GetGlyphIndicesW(&ucs4, 1, &glyphIndex); - if (FAILED(hr)) { - qErrnoWarning("%s: glyphIndex failed", __FUNCTION__); - glyphIndex = 0; - } - - return glyphIndex; -} - -bool QWindowsFontEngineDirectWrite::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, - int *nglyphs, QFontEngine::ShaperFlags flags) const -{ - Q_ASSERT(glyphs->numGlyphs >= *nglyphs); - if (*nglyphs < len) { - *nglyphs = len; - return false; - } - - QVarLengthArray codePoints(len); - int actualLength = 0; - QStringIterator it(str, str + len); - while (it.hasNext()) - codePoints[actualLength++] = it.next(); - - QVarLengthArray glyphIndices(actualLength); - HRESULT hr = m_directWriteFontFace->GetGlyphIndicesW(codePoints.data(), actualLength, - glyphIndices.data()); - if (FAILED(hr)) { - qErrnoWarning("%s: GetGlyphIndicesW failed", __FUNCTION__); - return false; - } - - for (int i = 0; i < actualLength; ++i) - glyphs->glyphs[i] = glyphIndices.at(i); - - *nglyphs = actualLength; - glyphs->numGlyphs = actualLength; - - if (!(flags & GlyphIndicesOnly)) - recalcAdvances(glyphs, {}); - - return true; -} - -QFontEngine::FaceId QWindowsFontEngineDirectWrite::faceId() const -{ - return m_faceId; -} - -void QWindowsFontEngineDirectWrite::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags) const -{ - QVarLengthArray glyphIndices(glyphs->numGlyphs); - - // ### Caching? - for(int i=0; inumGlyphs; i++) - glyphIndices[i] = UINT16(glyphs->glyphs[i]); - - QVarLengthArray glyphMetrics(glyphIndices.size()); - - HRESULT hr; - DWRITE_RENDERING_MODE renderMode = hintingPreferenceToRenderingMode(QFont::HintingPreference(fontDef.hintingPreference)); - if (renderMode == DWRITE_RENDERING_MODE_GDI_CLASSIC || renderMode == DWRITE_RENDERING_MODE_GDI_NATURAL) { - hr = m_directWriteFontFace->GetGdiCompatibleGlyphMetrics(float(fontDef.pixelSize), - 1.0f, - NULL, - TRUE, - glyphIndices.data(), - glyphIndices.size(), - glyphMetrics.data()); - } else { - hr = m_directWriteFontFace->GetDesignGlyphMetrics(glyphIndices.data(), - glyphIndices.size(), - glyphMetrics.data()); - } - if (SUCCEEDED(hr)) { - qreal stretch = fontDef.stretch != QFont::AnyStretch ? fontDef.stretch / 100.0 : 1.0; - for (int i = 0; i < glyphs->numGlyphs; ++i) - glyphs->advances[i] = DESIGN_TO_LOGICAL(glyphMetrics[i].advanceWidth * stretch); - } else { - qErrnoWarning("%s: GetDesignGlyphMetrics failed", __FUNCTION__); - } -} - -void QWindowsFontEngineDirectWrite::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, - QPainterPath *path, QTextItem::RenderFlags flags) -{ - QVarLengthArray glyphIndices(nglyphs); - QVarLengthArray glyphOffsets(nglyphs); - QVarLengthArray glyphAdvances(nglyphs); - - for (int i=0; iGetGlyphRunOutline( - fontDef.pixelSize, - glyphIndices.data(), - glyphAdvances.data(), - glyphOffsets.data(), - nglyphs, - false, - flags & QTextItem::RightToLeft, - &geometrySink - ); - - if (FAILED(hr)) - qErrnoWarning("%s: GetGlyphRunOutline failed", __FUNCTION__); -} - -glyph_metrics_t QWindowsFontEngineDirectWrite::boundingBox(const QGlyphLayout &glyphs) -{ - if (glyphs.numGlyphs == 0) - return glyph_metrics_t(); - QFixed w = 0; - for (int i = 0; i < glyphs.numGlyphs; ++i) - w += glyphs.effectiveAdvance(i); - - return glyph_metrics_t(0, -ascent(), w - lastRightBearing(glyphs), ascent() + descent(), w, 0); -} - -glyph_metrics_t QWindowsFontEngineDirectWrite::boundingBox(glyph_t g) -{ - UINT16 glyphIndex = g; - - DWRITE_GLYPH_METRICS glyphMetrics; - HRESULT hr = m_directWriteFontFace->GetDesignGlyphMetrics(&glyphIndex, 1, &glyphMetrics); - if (SUCCEEDED(hr)) { - QFixed advanceWidth = DESIGN_TO_LOGICAL(glyphMetrics.advanceWidth); - QFixed leftSideBearing = DESIGN_TO_LOGICAL(glyphMetrics.leftSideBearing); - QFixed rightSideBearing = DESIGN_TO_LOGICAL(glyphMetrics.rightSideBearing); - QFixed advanceHeight = DESIGN_TO_LOGICAL(glyphMetrics.advanceHeight); - QFixed verticalOriginY = DESIGN_TO_LOGICAL(glyphMetrics.verticalOriginY); - QFixed topSideBearing = DESIGN_TO_LOGICAL(glyphMetrics.topSideBearing); - QFixed bottomSideBearing = DESIGN_TO_LOGICAL(glyphMetrics.bottomSideBearing); - QFixed width = advanceWidth - leftSideBearing - rightSideBearing; - QFixed height = advanceHeight - topSideBearing - bottomSideBearing; - return glyph_metrics_t(leftSideBearing, - -verticalOriginY + topSideBearing, - width, - height, - advanceWidth, - 0); - } else { - qErrnoWarning("%s: GetDesignGlyphMetrics failed", __FUNCTION__); - } - - return glyph_metrics_t(); -} - -QFixed QWindowsFontEngineDirectWrite::capHeight() const -{ - if (m_capHeight <= 0) - return calculatedCapHeight(); - - return m_capHeight; -} - -QFixed QWindowsFontEngineDirectWrite::xHeight() const -{ - return m_xHeight; -} - -qreal QWindowsFontEngineDirectWrite::maxCharWidth() const -{ - return m_maxAdvanceWidth.toReal(); -} - -QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) -{ - QImage im = imageForGlyph(glyph, subPixelPosition, glyphMargin(Format_A8), t); - - QImage alphaMap(im.width(), im.height(), QImage::Format_Alpha8); - - for (int y=0; y(im.constScanLine(y)); - uchar *dst = alphaMap.scanLine(y); - for (int x=0; xpow_gamma[qGray(0xffffffff - *src)] * 255. / 2047.); - ++dst; - ++src; - } - } - - return alphaMap; -} - -QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition) -{ - return alphaMapForGlyph(glyph, subPixelPosition, QTransform()); -} - -bool QWindowsFontEngineDirectWrite::supportsSubPixelPositions() const -{ - return true; -} - -QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t, - QFixed subPixelPosition, - int margin, - const QTransform &originalTransform, - const QColor &color) -{ - UINT16 glyphIndex = t; - FLOAT glyphAdvance = 0; - - DWRITE_GLYPH_OFFSET glyphOffset; - glyphOffset.advanceOffset = 0; - glyphOffset.ascenderOffset = 0; - - DWRITE_GLYPH_RUN glyphRun; - glyphRun.fontFace = m_directWriteFontFace; - glyphRun.fontEmSize = fontDef.pixelSize; - glyphRun.glyphCount = 1; - glyphRun.glyphIndices = &glyphIndex; - glyphRun.glyphAdvances = &glyphAdvance; - glyphRun.isSideways = false; - glyphRun.bidiLevel = 0; - glyphRun.glyphOffsets = &glyphOffset; - - QTransform xform = originalTransform; - if (fontDef.stretch != 100 && fontDef.stretch != QFont::AnyStretch) - xform.scale(fontDef.stretch / 100.0, 1.0); - - DWRITE_MATRIX transform; - transform.dx = subPixelPosition.toReal(); - transform.dy = 0; - transform.m11 = xform.m11(); - transform.m12 = xform.m12(); - transform.m21 = xform.m21(); - transform.m22 = xform.m22(); - - DWRITE_RENDERING_MODE renderMode = - hintingPreferenceToRenderingMode(QFont::HintingPreference(fontDef.hintingPreference)); - DWRITE_MEASURING_MODE measureMode = - renderModeToMeasureMode(renderMode); - - IDWriteGlyphRunAnalysis *glyphAnalysis = NULL; - HRESULT hr = m_fontEngineData->directWriteFactory->CreateGlyphRunAnalysis( - &glyphRun, - 1.0f, - &transform, - renderMode, - measureMode, - 0.0, 0.0, - &glyphAnalysis - ); - - if (SUCCEEDED(hr)) { - RECT rect; - glyphAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect); - - if (rect.top == rect.bottom || rect.left == rect.right) - return QImage(); - - QRect boundingRect = QRect(QPoint(rect.left - margin, - rect.top - margin), - QPoint(rect.right + margin, - rect.bottom + margin)); - - - const int width = boundingRect.width() - 1; // -1 due to Qt's off-by-one definition of a QRect - const int height = boundingRect.height() - 1; - - QImage image; -#if defined(QT_USE_DIRECTWRITE2) - HRESULT hr = DWRITE_E_NOCOLOR; - IDWriteColorGlyphRunEnumerator *enumerator = 0; - IDWriteFactory2 *factory2 = nullptr; - if (glyphFormat == QFontEngine::Format_ARGB - && SUCCEEDED(m_fontEngineData->directWriteFactory->QueryInterface(__uuidof(IDWriteFactory2), - reinterpret_cast(&factory2)))) { - hr = factory2->TranslateColorGlyphRun(0.0f, - 0.0f, - &glyphRun, - NULL, - measureMode, - NULL, - 0, - &enumerator); - image = QImage(width, height, QImage::Format_ARGB32_Premultiplied); - image.fill(0); - } else -#endif - { - image = QImage(width, height, QImage::Format_RGB32); - image.fill(0xffffffff); - } - -#if defined(QT_USE_DIRECTWRITE2) - BOOL ok = true; - - if (SUCCEEDED(hr)) { - while (SUCCEEDED(hr) && ok) { - const DWRITE_COLOR_GLYPH_RUN *colorGlyphRun = 0; - hr = enumerator->GetCurrentRun(&colorGlyphRun); - if (FAILED(hr)) { // No colored runs, only outline - qErrnoWarning(hr, "%s: IDWriteColorGlyphRunEnumerator::GetCurrentRun failed", __FUNCTION__); - break; - } - - IDWriteGlyphRunAnalysis *colorGlyphsAnalysis = NULL; - hr = m_fontEngineData->directWriteFactory->CreateGlyphRunAnalysis( - &colorGlyphRun->glyphRun, - 1.0f, - &transform, - renderMode, - measureMode, - 0.0, 0.0, - &colorGlyphsAnalysis - ); - if (FAILED(hr)) { - qErrnoWarning(hr, "%s: CreateGlyphRunAnalysis failed for color run", __FUNCTION__); - break; - } - - float r, g, b, a; - if (colorGlyphRun->paletteIndex == 0xFFFF) { - r = float(color.redF()); - g = float(color.greenF()); - b = float(color.blueF()); - a = float(color.alphaF()); - } else { - r = qBound(0.0f, colorGlyphRun->runColor.r, 1.0f); - g = qBound(0.0f, colorGlyphRun->runColor.g, 1.0f); - b = qBound(0.0f, colorGlyphRun->runColor.b, 1.0f); - a = qBound(0.0f, colorGlyphRun->runColor.a, 1.0f); - } - - if (!qFuzzyIsNull(a)) { - renderGlyphRun(&image, - r, - g, - b, - a, - colorGlyphsAnalysis, - boundingRect); - } - colorGlyphsAnalysis->Release(); - - hr = enumerator->MoveNext(&ok); - if (FAILED(hr)) { - qErrnoWarning(hr, "%s: IDWriteColorGlyphRunEnumerator::MoveNext failed", __FUNCTION__); - break; - } - } - } else -#endif - { - float r, g, b, a; - if (glyphFormat == QFontEngine::Format_ARGB) { - r = float(color.redF()); - g = float(color.greenF()); - b = float(color.blueF()); - a = float(color.alphaF()); - } else { - r = g = b = a = 0.0; - } - - renderGlyphRun(&image, - r, - g, - b, - a, - glyphAnalysis, - boundingRect); - } - - glyphAnalysis->Release(); - return image; - } else { - qErrnoWarning(hr, "%s: CreateGlyphRunAnalysis failed", __FUNCTION__); - return QImage(); - } -} - - -void QWindowsFontEngineDirectWrite::renderGlyphRun(QImage *destination, - float r, - float g, - float b, - float a, - IDWriteGlyphRunAnalysis *glyphAnalysis, - const QRect &boundingRect) -{ - const int width = destination->width(); - const int height = destination->height(); - - r *= 255.0; - g *= 255.0; - b *= 255.0; - - const int size = width * height * 3; - if (size > 0) { - RECT rect; - rect.left = boundingRect.left(); - rect.top = boundingRect.top(); - rect.right = boundingRect.right(); - rect.bottom = boundingRect.bottom(); - - QVarLengthArray alphaValueArray(size); - BYTE *alphaValues = alphaValueArray.data(); - memset(alphaValues, 0, size); - - HRESULT hr = glyphAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1, - &rect, - alphaValues, - size); - if (SUCCEEDED(hr)) { - if (destination->hasAlphaChannel()) { - for (int y = 0; y < height; ++y) { - uint *dest = reinterpret_cast(destination->scanLine(y)); - BYTE *src = alphaValues + width * 3 * y; - - for (int x = 0; x < width; ++x) { - float redAlpha = a * *src++ / 255.0; - float greenAlpha = a * *src++ / 255.0; - float blueAlpha = a * *src++ / 255.0; - float averageAlpha = (redAlpha + greenAlpha + blueAlpha) / 3.0; - - QRgb currentRgb = dest[x]; - dest[x] = qRgba(qRound(qRed(currentRgb) * (1.0 - averageAlpha) + averageAlpha * r), - qRound(qGreen(currentRgb) * (1.0 - averageAlpha) + averageAlpha * g), - qRound(qBlue(currentRgb) * (1.0 - averageAlpha) + averageAlpha * b), - qRound(qAlpha(currentRgb) * (1.0 - averageAlpha) + averageAlpha * 255)); - } - } - - } else { - for (int y = 0; y < height; ++y) { - uint *dest = reinterpret_cast(destination->scanLine(y)); - BYTE *src = alphaValues + width * 3 * y; - - for (int x = 0; x < width; ++x) { - dest[x] = *(src + 0) << 16 - | *(src + 1) << 8 - | *(src + 2); - - src += 3; - } - } - } - } else { - qErrnoWarning("%s: CreateAlphaTexture failed", __FUNCTION__); - } - } else { - glyphAnalysis->Release(); - qWarning("%s: Glyph has no bounds", __FUNCTION__); - } -} - -QImage QWindowsFontEngineDirectWrite::alphaRGBMapForGlyph(glyph_t t, - QFixed subPixelPosition, - const QTransform &xform) -{ - QImage mask = imageForGlyph(t, - subPixelPosition, - glyphMargin(QFontEngine::Format_A32), - xform); - - return mask.depth() == 32 - ? mask - : mask.convertToFormat(QImage::Format_RGB32); -} - -QFontEngine *QWindowsFontEngineDirectWrite::cloneWithSize(qreal pixelSize) const -{ - QWindowsFontEngineDirectWrite *fontEngine = new QWindowsFontEngineDirectWrite(m_directWriteFontFace, - pixelSize, - m_fontEngineData); - - fontEngine->fontDef = fontDef; - fontEngine->fontDef.pixelSize = pixelSize; - if (!m_uniqueFamilyName.isEmpty()) { - fontEngine->setUniqueFamilyName(m_uniqueFamilyName); - QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase(); - static_cast(pfdb)->refUniqueFont(m_uniqueFamilyName); - } - - return fontEngine; -} - -Qt::HANDLE QWindowsFontEngineDirectWrite::handle() const -{ - return m_directWriteFontFace; -} - -void QWindowsFontEngineDirectWrite::initFontInfo(const QFontDef &request, - int dpi) -{ - fontDef = request; - - if (fontDef.pointSize < 0) - fontDef.pointSize = fontDef.pixelSize * 72. / dpi; - else if (fontDef.pixelSize == -1) - fontDef.pixelSize = qRound(fontDef.pointSize * dpi / 72.); -} - -QString QWindowsFontEngineDirectWrite::fontNameSubstitute(const QString &familyName) -{ - const QString substitute = - QWinRegistryKey(HKEY_LOCAL_MACHINE, - LR"(Software\Microsoft\Windows NT\CurrentVersion\FontSubstitutes)") - .stringValue(familyName); - return substitute.isEmpty() ? familyName : substitute; -} - -glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph, - QFixed subPixelPosition, - const QTransform &originalTransform, - GlyphFormat format) -{ - Q_UNUSED(format); - - QTransform matrix = originalTransform; - if (fontDef.stretch != 100 && fontDef.stretch != QFont::AnyStretch) - matrix.scale(fontDef.stretch / 100.0, 1.0); - - glyph_metrics_t bbox = QFontEngine::boundingBox(glyph, matrix); // To get transformed advance - - UINT16 glyphIndex = glyph; - FLOAT glyphAdvance = 0; - - DWRITE_GLYPH_OFFSET glyphOffset; - glyphOffset.advanceOffset = 0; - glyphOffset.ascenderOffset = 0; - - DWRITE_GLYPH_RUN glyphRun; - glyphRun.fontFace = m_directWriteFontFace; - glyphRun.fontEmSize = fontDef.pixelSize; - glyphRun.glyphCount = 1; - glyphRun.glyphIndices = &glyphIndex; - glyphRun.glyphAdvances = &glyphAdvance; - glyphRun.isSideways = false; - glyphRun.bidiLevel = 0; - glyphRun.glyphOffsets = &glyphOffset; - - DWRITE_MATRIX transform; - transform.dx = subPixelPosition.toReal(); - transform.dy = 0; - transform.m11 = matrix.m11(); - transform.m12 = matrix.m12(); - transform.m21 = matrix.m21(); - transform.m22 = matrix.m22(); - - DWRITE_RENDERING_MODE renderMode = - hintingPreferenceToRenderingMode(QFont::HintingPreference(fontDef.hintingPreference)); - DWRITE_MEASURING_MODE measureMode = renderModeToMeasureMode(renderMode); - - IDWriteGlyphRunAnalysis *glyphAnalysis = NULL; - HRESULT hr = m_fontEngineData->directWriteFactory->CreateGlyphRunAnalysis( - &glyphRun, - 1.0f, - &transform, - renderMode, - measureMode, - 0.0, 0.0, - &glyphAnalysis - ); - - if (SUCCEEDED(hr)) { - RECT rect; - glyphAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect); - glyphAnalysis->Release(); - - int margin = glyphMargin(format); - - if (rect.left == rect.right || rect.top == rect.bottom) - return glyph_metrics_t(); - - return glyph_metrics_t(rect.left, - rect.top, - rect.right - rect.left + margin * 2, - rect.bottom - rect.top + margin * 2, - bbox.xoff, bbox.yoff); - } else { - return glyph_metrics_t(); - } -} - -QImage QWindowsFontEngineDirectWrite::bitmapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t, const QColor &color) -{ - return imageForGlyph(glyph, subPixelPosition, glyphMargin(QFontEngine::Format_ARGB), t, color); -} - -QT_END_NAMESPACE - -#endif // QT_NO_DIRECTWRITE diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite_p.h deleted file mode 100644 index 6e79190ce4..0000000000 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite_p.h +++ /dev/null @@ -1,152 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module 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$ -** -****************************************************************************/ - -#ifndef QWINDOWSFONTENGINEDIRECTWRITE_H -#define QWINDOWSFONTENGINEDIRECTWRITE_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -#ifndef QT_NO_DIRECTWRITE - -#include -#include - -struct IDWriteFont; -struct IDWriteFontFace; -struct IDWriteFontFile; -struct IDWriteFactory; -struct IDWriteBitmapRenderTarget; -struct IDWriteGdiInterop; -struct IDWriteGlyphRunAnalysis; - -QT_BEGIN_NAMESPACE - -class QWindowsFontEngineData; - -class QWindowsFontEngineDirectWrite : public QFontEngine -{ - Q_DISABLE_COPY_MOVE(QWindowsFontEngineDirectWrite) -public: - explicit QWindowsFontEngineDirectWrite(IDWriteFontFace *directWriteFontFace, - qreal pixelSize, - const QSharedPointer &d); - ~QWindowsFontEngineDirectWrite() override; - - void initFontInfo(const QFontDef &request, int dpi); - - QFixed lineThickness() const override; - QFixed underlinePosition() const override; - bool getSfntTableData(uint tag, uchar *buffer, uint *length) const override; - QFixed emSquareSize() const override; - - glyph_t glyphIndex(uint ucs4) const override; - bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, - ShaperFlags flags) const override; - void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags) const override; - - void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, - QPainterPath *path, QTextItem::RenderFlags flags) override; - - glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) override; - glyph_metrics_t boundingBox(glyph_t g) override; - glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed, - const QTransform &matrix, GlyphFormat) override; - - QFixed capHeight() const override; - QFixed xHeight() const override; - qreal maxCharWidth() const override; - FaceId faceId() const override; - - bool supportsSubPixelPositions() const override; - - QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition) override; - QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) override; - QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, const QTransform &xform) override; - QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t, const QColor &color) override; - - QFontEngine *cloneWithSize(qreal pixelSize) const override; - Qt::HANDLE handle() const override; - - const QSharedPointer &fontEngineData() const { return m_fontEngineData; } - - static QString fontNameSubstitute(const QString &familyName); - - IDWriteFontFace *directWriteFontFace() const { return m_directWriteFontFace; } - - void setUniqueFamilyName(const QString &newName) { m_uniqueFamilyName = newName; } - - void initializeHeightMetrics() const override; - -private: - QImage imageForGlyph(glyph_t t, QFixed subPixelPosition, int margin, const QTransform &xform, const QColor &color = QColor()); - void collectMetrics(); - void renderGlyphRun(QImage *destination, float r, float g, float b, float a, IDWriteGlyphRunAnalysis *glyphAnalysis, const QRect &boundingRect); - static QString filenameFromFontFile(IDWriteFontFile *fontFile); - - const QSharedPointer m_fontEngineData; - - IDWriteFontFace *m_directWriteFontFace; - IDWriteBitmapRenderTarget *m_directWriteBitmapRenderTarget; - - QFixed m_lineThickness; - QFixed m_underlinePosition; - int m_unitsPerEm; - QFixed m_capHeight; - QFixed m_xHeight; - QFixed m_maxAdvanceWidth; - FaceId m_faceId; - QString m_uniqueFamilyName; -}; - -QT_END_NAMESPACE - -#endif // QT_NO_DIRECTWRITE - -#endif // QWINDOWSFONTENGINEDIRECTWRITE_H diff --git a/src/platformsupport/fontdatabases/windows/qwindowsnativeimage.cpp b/src/platformsupport/fontdatabases/windows/qwindowsnativeimage.cpp deleted file mode 100644 index ad277ea7cd..0000000000 --- a/src/platformsupport/fontdatabases/windows/qwindowsnativeimage.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#include "qwindowsnativeimage_p.h" - -#include -#include - -QT_BEGIN_NAMESPACE - -typedef struct { - BITMAPINFOHEADER bmiHeader; - DWORD redMask; - DWORD greenMask; - DWORD blueMask; -} BITMAPINFO_MASK; - -/*! - \class QWindowsNativeImage - \brief Windows Native image - - Note that size can be 0 (widget autotests with zero size), which - causes CreateDIBSection() to fail. - - \sa QWindowsBackingStore - \internal -*/ - -static inline HDC createDC() -{ - HDC display_dc = GetDC(0); - HDC hdc = CreateCompatibleDC(display_dc); - ReleaseDC(0, display_dc); - Q_ASSERT(hdc); - return hdc; -} - -static inline HBITMAP createDIB(HDC hdc, int width, int height, - QImage::Format format, - uchar **bitsIn) -{ - BITMAPINFO_MASK bmi; - memset(&bmi, 0, sizeof(bmi)); - bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biWidth = width; - bmi.bmiHeader.biHeight = -height; // top-down. - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biSizeImage = 0; - - if (format == QImage::Format_RGB16) { - bmi.bmiHeader.biBitCount = 16; - bmi.bmiHeader.biCompression = BI_BITFIELDS; - bmi.redMask = 0xF800; - bmi.greenMask = 0x07E0; - bmi.blueMask = 0x001F; - } else { - bmi.bmiHeader.biBitCount = 32; - bmi.bmiHeader.biCompression = BI_RGB; - bmi.redMask = 0; - bmi.greenMask = 0; - bmi.blueMask = 0; - } - - uchar *bits = nullptr; - HBITMAP bitmap = CreateDIBSection(hdc, reinterpret_cast(&bmi), - DIB_RGB_COLORS, reinterpret_cast(&bits), 0, 0); - if (Q_UNLIKELY(!bitmap || !bits)) { - qFatal("%s: CreateDIBSection failed (%dx%d, format: %d)", __FUNCTION__, - width, height, int(format)); - } - - *bitsIn = bits; - return bitmap; -} - -QWindowsNativeImage::QWindowsNativeImage(int width, int height, - QImage::Format format) : - m_hdc(createDC()) -{ - if (width != 0 && height != 0) { - uchar *bits; - m_bitmap = createDIB(m_hdc, width, height, format, &bits); - m_null_bitmap = static_cast(SelectObject(m_hdc, m_bitmap)); - m_image = QImage(bits, width, height, format); - Q_ASSERT(m_image.paintEngine()->type() == QPaintEngine::Raster); - static_cast(m_image.paintEngine())->setDC(m_hdc); - } else { - m_image = QImage(width, height, format); - } - - GdiFlush(); -} - -QWindowsNativeImage::~QWindowsNativeImage() -{ - if (m_hdc) { - if (m_bitmap) { - if (m_null_bitmap) - SelectObject(m_hdc, m_null_bitmap); - DeleteObject(m_bitmap); - } - DeleteDC(m_hdc); - } -} - -QImage::Format QWindowsNativeImage::systemFormat() -{ - static int depth = -1; - if (depth == -1) { - if (HDC defaultDC = GetDC(0)) { - depth = GetDeviceCaps(defaultDC, BITSPIXEL); - ReleaseDC(0, defaultDC); - } else { - // FIXME Same remark as in QWindowsFontDatabase::defaultVerticalDPI() - // BONUS FIXME: Is 32 too generous/optimistic? - depth = 32; - } - } - return depth == 16 ? QImage::Format_RGB16 : QImage::Format_RGB32; -} - -QT_END_NAMESPACE diff --git a/src/platformsupport/fontdatabases/windows/qwindowsnativeimage_p.h b/src/platformsupport/fontdatabases/windows/qwindowsnativeimage_p.h deleted file mode 100644 index ed68ac2644..0000000000 --- a/src/platformsupport/fontdatabases/windows/qwindowsnativeimage_p.h +++ /dev/null @@ -1,89 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef QWINDOWSNATIVEIMAGE_H -#define QWINDOWSNATIVEIMAGE_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class QWindowsNativeImage -{ - Q_DISABLE_COPY_MOVE(QWindowsNativeImage) -public: - QWindowsNativeImage(int width, int height, - QImage::Format format); - - ~QWindowsNativeImage(); - - inline int width() const { return m_image.width(); } - inline int height() const { return m_image.height(); } - - QImage &image() { return m_image; } - const QImage &image() const { return m_image; } - - HDC hdc() const { return m_hdc; } - - static QImage::Format systemFormat(); - -private: - const HDC m_hdc; - QImage m_image; - - HBITMAP m_bitmap = 0; - HBITMAP m_null_bitmap = 0; -}; - -QT_END_NAMESPACE - -#endif // QWINDOWSNATIVEIMAGE_H diff --git a/src/platformsupport/fontdatabases/windows/windows.pri b/src/platformsupport/fontdatabases/windows/windows.pri deleted file mode 100644 index c8466a1d2b..0000000000 --- a/src/platformsupport/fontdatabases/windows/windows.pri +++ /dev/null @@ -1,43 +0,0 @@ -QT *= gui-private - -SOURCES += \ - $$PWD/qwindowsfontdatabase.cpp \ - $$PWD/qwindowsfontdatabasebase.cpp \ - $$PWD/qwindowsfontengine.cpp \ - $$PWD/qwindowsnativeimage.cpp - -HEADERS += \ - $$PWD/qwindowsfontdatabase_p.h \ - $$PWD/qwindowsfontdatabasebase_p.h \ - $$PWD/qwindowsfontengine_p.h \ - $$PWD/qwindowsnativeimage_p.h - -qtConfig(freetype) { - SOURCES += $$PWD/qwindowsfontdatabase_ft.cpp - HEADERS += $$PWD/qwindowsfontdatabase_ft_p.h - QMAKE_USE_PRIVATE += freetype -} - -qtConfig(directwrite):qtConfig(direct2d) { - qtConfig(directwrite3) { - QMAKE_USE_PRIVATE += dwrite_3 - DEFINES *= QT_USE_DIRECTWRITE3 QT_USE_DIRECTWRITE2 - - SOURCES += $$PWD/qwindowsdirectwritefontdatabase.cpp - HEADERS += $$PWD/qwindowsdirectwritefontdatabase_p.h - } else: qtConfig(directwrite2) { - QMAKE_USE_PRIVATE += dwrite_2 - DEFINES *= QT_USE_DIRECTWRITE2 - } else { - QMAKE_USE_PRIVATE += dwrite - } - QMAKE_USE_PRIVATE += d2d1 - - SOURCES += $$PWD/qwindowsfontenginedirectwrite.cpp - HEADERS += $$PWD/qwindowsfontenginedirectwrite_p.h -} else { - DEFINES *= QT_NO_DIRECTWRITE -} - -QMAKE_USE_PRIVATE += advapi32 ole32 user32 gdi32 -mingw: QMAKE_USE_PRIVATE += uuid -- cgit v1.2.3