diff --git a/CMakeLists.txt b/CMakeLists.txt index c117a78..87d41a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,6 +90,8 @@ PRIVATE ui/style/style_core.h ui/style/style_core_color.cpp ui/style/style_core_color.h + ui/style/style_core_custom_font.cpp + ui/style/style_core_custom_font.h ui/style/style_core_direction.cpp ui/style/style_core_direction.h ui/style/style_core_font.cpp diff --git a/ui/style/style_core_custom_font.cpp b/ui/style/style_core_custom_font.cpp new file mode 100644 index 0000000..570d169 --- /dev/null +++ b/ui/style/style_core_custom_font.cpp @@ -0,0 +1,73 @@ +// This file is part of Desktop App Toolkit, +// a set of libraries for developing nice desktop applications. +// +// For license and copyright information please follow this link: +// https://github.com/desktop-app/legal/blob/master/LEGAL +// +#include "ui/style/style_core_custom_font.h" + +#include "ui/style/style_core_font.h" + +#include + +namespace style { +namespace { + +using namespace internal; + +auto RegularFont = CustomFont(); +auto BoldFont = CustomFont(); + +} // namespace + +void SetCustomFonts(const CustomFont ®ular, const CustomFont &bold) { + RegularFont = regular; + BoldFont = bold; +} + +QFont ResolveFont(uint32 flags, int size) { + static auto Database = QFontDatabase(); + + const auto bold = ((flags & FontBold) || (flags & FontSemibold)); + const auto italic = (flags & FontItalic); + const auto &custom = bold ? BoldFont : RegularFont; + const auto useCustom = !custom.family.isEmpty(); + + auto result = QFont(); + if (flags & FontMonospace) { + result.setFamily(MonospaceFont()); + } else if (useCustom) { + const auto sizes = Database.smoothSizes(custom.family, custom.style); + const auto good = sizes.isEmpty() + ? Database.pointSizes(custom.family, custom.style) + : sizes; + const auto point = good.isEmpty() ? size : good.front(); + result = Database.font(custom.family, custom.style, point); + } else { + result.setFamily(GetFontOverride(flags)); + if (bold) { +#ifdef DESKTOP_APP_USE_PACKAGED_FONTS + result.setWeight(QFont::DemiBold); +#else // DESKTOP_APP_USE_PACKAGED_FONTS + result.setBold(true); +#endif // !DESKTOP_APP_USE_PACKAGED_FONTS + + if (flags & FontItalic) { + result.setStyleName("Semibold Italic"); + } else { + result.setStyleName("Semibold"); + } + } + } + if (italic) { + result.setItalic(true); + } + + result.setUnderline(flags & FontUnderline); + result.setStrikeOut(flags & FontStrikeOut); + result.setPixelSize(size); + + return result; +} + +} // namespace style diff --git a/ui/style/style_core_custom_font.h b/ui/style/style_core_custom_font.h new file mode 100644 index 0000000..14ee48b --- /dev/null +++ b/ui/style/style_core_custom_font.h @@ -0,0 +1,45 @@ +// This file is part of Desktop App Toolkit, +// a set of libraries for developing nice desktop applications. +// +// For license and copyright information please follow this link: +// https://github.com/desktop-app/legal/blob/master/LEGAL +// +#pragma once + +namespace style { + +struct CustomFont { + QString family; + QString style; +}; + +inline bool operator==(const CustomFont &a, const CustomFont &b) { + return (a.family == b.family) && (a.style == b.style); +} + +inline bool operator<(const CustomFont &a, const CustomFont &b) { + return (a.family < b.family) + || (a.family == b.family && a.style < b.style); +} + +inline bool operator!=(const CustomFont &a, const CustomFont &b) { + return !(a == b); +} + +inline bool operator>(const CustomFont &a, const CustomFont &b) { + return (b < a); +} + +inline bool operator<=(const CustomFont &a, const CustomFont &b) { + return !(b < a); +} + +inline bool operator>=(const CustomFont &a, const CustomFont &b) { + return !(a < b); +} + +void SetCustomFonts(const CustomFont ®ular, const CustomFont &bold); + +[[nodiscard]] QFont ResolveFont(uint32 flags, int size); + +} // namespace style diff --git a/ui/style/style_core_font.cpp b/ui/style/style_core_font.cpp index 391c565..6da92d9 100644 --- a/ui/style/style_core_font.cpp +++ b/ui/style/style_core_font.cpp @@ -6,6 +6,7 @@ // #include "ui/style/style_core_font.h" +#include "ui/style/style_core_custom_font.h" #include "ui/ui_log.h" #include "base/algorithm.h" #include "ui/integration.h" @@ -106,26 +107,6 @@ bool LoadCustomFont(const QString &filePath, const QString &familyName, int flag return QString(); } -QString MonospaceFont() { - static const auto family = [&]() -> QString { - const auto manual = ManualMonospaceFont(); - const auto system = SystemMonospaceFont(); - -#if defined Q_OS_WIN || defined Q_OS_MAC - // Prefer our monospace font. - const auto useSystem = manual.isEmpty(); -#else // Q_OS_WIN || Q_OS_MAC - // Prefer system monospace font. - const auto metrics = QFontMetrics(QFont(system)); - const auto useSystem = manual.isEmpty() - || (metrics.charWidth("i", 0) == metrics.charWidth("W", 0)); -#endif // Q_OS_WIN || Q_OS_MAC - return useSystem ? system : manual; - }(); - - return family; -} - enum { FontTypeRegular = 0, FontTypeRegularItalic, @@ -277,6 +258,26 @@ QString GetFontOverride(int32 flags) { return result.isEmpty() ? "Open Sans" : result; } +QString MonospaceFont() { + static const auto family = [&]() -> QString { + const auto manual = ManualMonospaceFont(); + const auto system = SystemMonospaceFont(); + +#if defined Q_OS_WIN || defined Q_OS_MAC + // Prefer our monospace font. + const auto useSystem = manual.isEmpty(); +#else // Q_OS_WIN || Q_OS_MAC + // Prefer system monospace font. + const auto metrics = QFontMetrics(QFont(system)); + const auto useSystem = manual.isEmpty() + || (metrics.charWidth("i", 0) == metrics.charWidth("W", 0)); +#endif // Q_OS_WIN || Q_OS_MAC + return useSystem ? system : manual; + }(); + + return family; +} + void destroyFonts() { for (auto fontData : fontsMap) { delete fontData; @@ -295,7 +296,8 @@ int registerFontFamily(const QString &family) { } FontData::FontData(int size, uint32 flags, int family, Font *other) -: m(f) +: f(ResolveFont(flags, size)) +, m(f) , _size(size) , _flags(flags) , _family(family) { @@ -306,32 +308,6 @@ FontData::FontData(int size, uint32 flags, int family, Font *other) } modified[_flags] = Font(this); - if (_flags & FontMonospace) { - f.setFamily(MonospaceFont()); - } else { - f.setFamily(GetFontOverride(flags)); - } - - f.setPixelSize(size); - f.setItalic(_flags & FontItalic); - f.setUnderline(_flags & FontUnderline); - f.setStrikeOut(_flags & FontStrikeOut); - - if ((_flags & FontBold) || (_flags & FontSemibold)) { -#ifdef DESKTOP_APP_USE_PACKAGED_FONTS - f.setWeight(QFont::DemiBold); -#else // DESKTOP_APP_USE_PACKAGED_FONTS - f.setBold(true); -#endif // !DESKTOP_APP_USE_PACKAGED_FONTS - - if (_flags & FontItalic) { - f.setStyleName("Semibold Italic"); - } else { - f.setStyleName("Semibold"); - } - } - - m = QFontMetrics(f); height = m.height(); ascent = m.ascent(); descent = m.descent(); diff --git a/ui/style/style_core_font.h b/ui/style/style_core_font.h index 29e5299..5b72baf 100644 --- a/ui/style/style_core_font.h +++ b/ui/style/style_core_font.h @@ -16,6 +16,7 @@ namespace internal { void StartFonts(); [[nodiscard]] QString GetFontOverride(int32 flags = 0); +[[nodiscard]] QString MonospaceFont(); void destroyFonts(); int registerFontFamily(const QString &family); @@ -67,17 +68,19 @@ enum FontFlags { class FontData { public: - - int32 width(const QString &str) const { + int width(const QString &str) const { return m.width(str); } - int32 width(const QString &str, int32 from, int32 to) const { + int width(const QString &str, int32 from, int32 to) const { return width(str.mid(from, to)); } - int32 width(QChar ch) const { + int width(QChar ch) const { return m.width(ch); } - QString elided(const QString &str, int32 width, Qt::TextElideMode mode = Qt::ElideRight) const { + QString elided( + const QString &str, + int width, + Qt::TextElideMode mode = Qt::ElideRight) const { return m.elidedText(str, mode, width); }