Merge remote-tracking branch 'tdesktop/master' into v2.1.10

This commit is contained in:
Ilya Fedin 2020-06-08 03:56:11 +04:00
commit 5534b37e6f
5 changed files with 205 additions and 104 deletions

View file

@ -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

View file

@ -0,0 +1,93 @@
// 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 <QFontDatabase>
namespace style {
namespace {
using namespace internal;
auto RegularFont = CustomFont();
auto BoldFont = CustomFont();
} // namespace
void SetCustomFonts(const CustomFont &regular, const CustomFont &bold) {
RegularFont = regular;
BoldFont = bold;
}
QFont ResolveFont(uint32 flags, int size) {
static auto Database = QFontDatabase();
const auto fontOverride = ParseFamilyName(GetFontOverride(flags));
const auto overrideIsEmpty = GetPossibleEmptyOverride(flags).isEmpty();
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 if (!UseSystemFont || !overrideIsEmpty) {
result.setFamily(fontOverride);
if (bold) {
if (CustomSemiboldIsBold) {
result.setBold(true);
#ifdef DESKTOP_APP_USE_PACKAGED_FONTS
} else {
result.setWeight(QFont::DemiBold);
#else // DESKTOP_APP_USE_PACKAGED_FONTS
} else if (UseSystemFont) {
result.setWeight(QFont::DemiBold);
} else {
result.setBold(true);
#endif // !DESKTOP_APP_USE_PACKAGED_FONTS
}
if (!CustomSemiboldIsBold) {
if (flags & FontItalic) {
result.setStyleName("Semibold Italic");
} else {
result.setStyleName("Semibold");
}
}
}
if (IsRealSemibold(fontOverride)) {
if (_flags & FontItalic) {
f.setStyleName("Semibold Italic");
} else {
f.setStyleName("Semibold");
}
}
}
if (italic) {
result.setItalic(true);
}
result.setUnderline(flags & FontUnderline);
result.setStrikeOut(flags & FontStrikeOut);
result.setPixelSize(size);
return result;
}
} // namespace style

View file

@ -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 &regular, const CustomFont &bold);
[[nodiscard]] QFont ResolveFont(uint32 flags, int size);
} // namespace style

View file

@ -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"
@ -47,33 +48,6 @@ QString RemoveSemiboldFromName(const QString &familyName) {
return removedSemibold.trimmed();
}
bool IsRealSemibold(const QString &familyName) {
const auto removedSemibold = RemoveSemiboldFromName(familyName);
QFont originalFont(familyName);
QFont withoutSemiboldFont(removedSemibold);
withoutSemiboldFont.setStyleName("Semibold");
QFontInfo originalFontInfo(originalFont);
QFontInfo withoutSemiboldInfo(withoutSemiboldFont);
if (originalFontInfo.family().trimmed().compare(familyName, Qt::CaseInsensitive) &&
!withoutSemiboldInfo.family().trimmed().compare(removedSemibold, Qt::CaseInsensitive) &&
!withoutSemiboldInfo.styleName().trimmed().compare("Semibold", Qt::CaseInsensitive)) {
return true;
} else {
return false;
}
}
QString ParseFamilyName(const QString &familyName) {
if (IsRealSemibold(familyName)) {
return RemoveSemiboldFromName(familyName);
} else {
return familyName;
}
}
bool ValidateFont(const QString &familyName, int flags = 0) {
const auto parsedFamily = ParseFamilyName(familyName);
@ -150,30 +124,6 @@ bool TryFont(const QString &attempt) {
return QString();
}
QString MonospaceFont() {
static const auto family = [&]() -> QString {
if (TryFont(CustomMonospaceFont)) {
return CustomMonospaceFont;
}
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 || UseSystemFont) ? system : manual;
}();
return family;
}
QFontMetrics GetFontMetrics(int size) {
#ifdef DESKTOP_APP_USE_PACKAGED_FONTS
QFont originalFont("Open Sans");
@ -355,6 +305,57 @@ QString GetFontOverride(int32 flags) {
return result.isEmpty() ? "Open Sans" : result;
}
bool IsRealSemibold(const QString &familyName) {
const auto removedSemibold = RemoveSemiboldFromName(familyName);
QFont originalFont(familyName);
QFont withoutSemiboldFont(removedSemibold);
withoutSemiboldFont.setStyleName("Semibold");
QFontInfo originalFontInfo(originalFont);
QFontInfo withoutSemiboldInfo(withoutSemiboldFont);
if (originalFontInfo.family().trimmed().compare(familyName, Qt::CaseInsensitive) &&
!withoutSemiboldInfo.family().trimmed().compare(removedSemibold, Qt::CaseInsensitive) &&
!withoutSemiboldInfo.styleName().trimmed().compare("Semibold", Qt::CaseInsensitive)) {
return true;
} else {
return false;
}
}
QString ParseFamilyName(const QString &familyName) {
if (IsRealSemibold(familyName)) {
return RemoveSemiboldFromName(familyName);
} else {
return familyName;
}
}
QString MonospaceFont() {
static const auto family = [&]() -> QString {
if (TryFont(CustomMonospaceFont)) {
return CustomMonospaceFont;
}
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 || UseSystemFont) ? system : manual;
}();
return family;
}
void destroyFonts() {
for (auto fontData : fontsMap) {
delete fontData;
@ -373,13 +374,11 @@ 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) {
const auto fontOverride = ParseFamilyName(GetFontOverride(flags));
const auto overrideIsEmpty = GetPossibleEmptyOverride(flags).isEmpty();
if (other) {
memcpy(modified, other, sizeof(modified));
} else {
@ -387,50 +386,6 @@ FontData::FontData(int size, uint32 flags, int family, Font *other)
}
modified[_flags] = Font(this);
if (_flags & FontMonospace) {
f.setFamily(MonospaceFont());
} else if (!UseSystemFont || !overrideIsEmpty) {
f.setFamily(fontOverride);
}
f.setPixelSize(size);
f.setItalic(_flags & FontItalic);
f.setUnderline(_flags & FontUnderline);
f.setStrikeOut(_flags & FontStrikeOut);
if ((_flags & FontBold) || (_flags & FontSemibold)) {
if (CustomSemiboldIsBold) {
f.setBold(true);
#ifdef DESKTOP_APP_USE_PACKAGED_FONTS
} else {
f.setWeight(QFont::DemiBold);
#else // DESKTOP_APP_USE_PACKAGED_FONTS
} else if (UseSystemFont) {
f.setWeight(QFont::DemiBold);
} else {
f.setBold(true);
#endif // !DESKTOP_APP_USE_PACKAGED_FONTS
}
if (!CustomSemiboldIsBold) {
if (_flags & FontItalic) {
f.setStyleName("Semibold Italic");
} else {
f.setStyleName("Semibold");
}
}
}
if (IsRealSemibold(fontOverride)) {
if (_flags & FontItalic) {
f.setStyleName("Semibold Italic");
} else {
f.setStyleName("Semibold");
}
}
m = QFontMetrics(f);
if (UseOriginalMetrics && !(_flags & FontMonospace)) {
const auto mOrig = GetFontMetrics(size);

View file

@ -22,7 +22,11 @@ extern bool UseSystemFont;
extern bool UseOriginalMetrics;
void StartFonts();
[[nodiscard]] QString GetPossibleEmptyOverride(int32 flags = 0);
[[nodiscard]] QString GetFontOverride(int32 flags = 0);
[[nodiscard]] bool IsRealSemibold(const QString &familyName);
[[nodiscard]] QString ParseFamilyName(const QString &familyName);
[[nodiscard]] QString MonospaceFont();
void destroyFonts();
int registerFontFamily(const QString &family);
@ -74,17 +78,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);
}