File indexing completed on 2024-05-19 04:29:20
0001 /* 0002 * SPDX-FileCopyrightText: 2016 The Qt Company Ltd. 0003 * SPDX-FileCopyrightText: 2020 Halla Rempt <halla@valdyas.org> 0004 * SPDX-FileCopyrightText: 2021 Alvin Wong <alvin@alvinhc.com> 0005 * 0006 * SPDX-License-Identifier: GPL-3.0-or-later 0007 * 0008 * 0009 * This file contains code that was borrowed and modified from the Qt Project, 0010 * originally licensed under LGPL-3.0-or-later or GPL-2.0-or-later. 0011 */ 0012 0013 #include "KisUiFont.h" 0014 0015 #include <kis_config.h> 0016 0017 #include <boost/optional.hpp> 0018 0019 #include <QtGlobal> 0020 #include <QFontDatabase> 0021 0022 #if defined(Q_OS_WIN) && QT_VERSION < 0x060000 0023 # include <qt_windows.h> 0024 #endif 0025 0026 namespace KisUiFont 0027 { 0028 0029 static const QString useCustomSystemFontCfgName = QStringLiteral("use_custom_system_font"); 0030 static const QString customSystemFontCfgName = QStringLiteral("custom_system_font"); 0031 static const QString customFontSizeCfgName = QStringLiteral("custom_font_size"); 0032 0033 /** 0034 * @brief Gets the system default UI font. 0035 * @return the system default UI font. 0036 */ 0037 static QFont systemDefaultUiFont(); 0038 0039 /** 0040 * @brief Returns the font the user has configured. 0041 * @return the user font if it has been set, otherwise `boost::none`. 0042 */ 0043 static boost::optional<QFont> userCfgUiFont(); 0044 0045 #if defined(Q_OS_WIN) && QT_VERSION < 0x060000 0046 static QFont windowsSystemUiFont(); 0047 #endif 0048 0049 QFont systemDefaultUiFont() 0050 { 0051 #if defined(Q_OS_WIN) && QT_VERSION < 0x060000 0052 return windowsSystemUiFont(); 0053 #else 0054 return QFontDatabase::systemFont(QFontDatabase::GeneralFont); 0055 #endif 0056 } 0057 0058 boost::optional<QFont> userCfgUiFont() 0059 { 0060 KisConfig cfg(true); 0061 if (cfg.readEntry<bool>(useCustomSystemFontCfgName, false)) { 0062 QString fontName = cfg.readEntry<QString>(customSystemFontCfgName, QString()); 0063 if (fontName.isEmpty()) { 0064 return boost::none; 0065 } 0066 int fontSize = cfg.readEntry<int>(customFontSizeCfgName, -1); 0067 if (fontSize <= 6) { 0068 fontSize = systemDefaultUiFont().pointSize(); 0069 } 0070 return QFont(fontName, fontSize); 0071 } else { 0072 return boost::none; 0073 } 0074 } 0075 0076 QFont normalFont() 0077 { 0078 QFont font; 0079 if (boost::optional<QFont> userFont = userCfgUiFont()) { 0080 font = *userFont; 0081 } else { 0082 font = systemDefaultUiFont(); 0083 } 0084 #ifdef Q_OS_WIN 0085 // XXX: Forces Qt to use full hinting for UI text, otherwise the default 0086 // will cause Qt to do vertical hinting only when High-DPI is active, 0087 // which makes some UI text extremely blurry on CJK systems. 0088 font.setHintingPreference(QFont::PreferFullHinting); 0089 #endif 0090 return font; 0091 } 0092 0093 QFont dockFont() 0094 { 0095 QFont font = normalFont(); 0096 font.setPointSizeF(font.pointSizeF() * 0.9); 0097 return font; 0098 } 0099 0100 #if defined(Q_OS_WIN) && QT_VERSION < 0x060000 0101 0102 // From qtbase/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp 0103 static int defaultVerticalDPI() 0104 { 0105 static int vDPI = -1; 0106 if (vDPI == -1) { 0107 if (HDC defaultDC = GetDC(0)) { 0108 vDPI = GetDeviceCaps(defaultDC, LOGPIXELSY); 0109 ReleaseDC(0, defaultDC); 0110 } else { 0111 // FIXME: Resolve now or return 96 and keep unresolved? 0112 vDPI = 96; 0113 } 0114 } 0115 return vDPI; 0116 } 0117 0118 // From qtbase/src/gui/text/qplatformfontdatabase.cpp 0119 QFont::Weight weightFromInteger(int weight) 0120 { 0121 if (weight < 150) { 0122 return QFont::Thin; 0123 } 0124 if (weight < 250) { 0125 return QFont::ExtraLight; 0126 } 0127 if (weight < 350) { 0128 return QFont::Light; 0129 } 0130 if (weight < 450) { 0131 return QFont::Normal; 0132 } 0133 if (weight < 550) { 0134 return QFont::Medium; 0135 } 0136 if (weight < 650) { 0137 return QFont::DemiBold; 0138 } 0139 if (weight < 750) { 0140 return QFont::Bold; 0141 } 0142 if (weight < 850) { 0143 return QFont::ExtraBold; 0144 } 0145 return QFont::Black; 0146 } 0147 0148 // From qtbase/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp 0149 static QFont LOGFONT_to_QFont(const LOGFONTW& logFont) 0150 { 0151 const int verticalDPI_In = defaultVerticalDPI(); 0152 QFont qFont(QString::fromWCharArray(logFont.lfFaceName)); 0153 qFont.setItalic(logFont.lfItalic); 0154 if (logFont.lfWeight != FW_DONTCARE) { 0155 qFont.setWeight(weightFromInteger(logFont.lfWeight)); 0156 } 0157 const qreal logFontHeight = qAbs(logFont.lfHeight); 0158 qFont.setPointSizeF(logFontHeight * 72.0 / qreal(verticalDPI_In)); 0159 qFont.setUnderline(logFont.lfUnderline); 0160 qFont.setOverline(false); 0161 qFont.setStrikeOut(logFont.lfStrikeOut); 0162 return qFont; 0163 } 0164 0165 // From qtbase/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp 0166 static QFont windowsSystemUiFont() 0167 { 0168 // Qt 6: Obtain default GUI font (typically "Segoe UI, 9pt", see QTBUG-58610) 0169 NONCLIENTMETRICSW ncm; 0170 ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICSW, lfMessageFont) + sizeof(LOGFONTW); 0171 SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0); 0172 const QFont systemFont = LOGFONT_to_QFont(ncm.lfMessageFont); 0173 return systemFont; 0174 } 0175 #endif 0176 0177 } // namespace KisUiFont