mirror of
https://github.com/kotatogram/kotatogram-desktop
synced 2025-09-03 16:15:13 +00:00
Build fixes
This commit is contained in:
@@ -10,6 +10,7 @@ https://github.com/kotatogram/kotatogram-desktop/blob/dev/LEGAL
|
|||||||
#include "ui/widgets/checkbox.h"
|
#include "ui/widgets/checkbox.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "ui/widgets/input_fields.h"
|
#include "ui/widgets/input_fields.h"
|
||||||
|
#include "styles/style_layers.h"
|
||||||
#include "styles/style_boxes.h"
|
#include "styles/style_boxes.h"
|
||||||
#include "boxes/confirm_box.h"
|
#include "boxes/confirm_box.h"
|
||||||
#include "core/kotato_settings.h"
|
#include "core/kotato_settings.h"
|
||||||
|
@@ -14,7 +14,7 @@ class Checkbox;
|
|||||||
class InputField;
|
class InputField;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
class FontsBox : public BoxContent {
|
class FontsBox : public Ui::BoxContent {
|
||||||
public:
|
public:
|
||||||
FontsBox(QWidget* parent);
|
FontsBox(QWidget* parent);
|
||||||
|
|
||||||
|
@@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "ui/widgets/checkbox.h"
|
#include "ui/widgets/checkbox.h"
|
||||||
#include "ui/widgets/labels.h"
|
#include "ui/widgets/labels.h"
|
||||||
|
#include "styles/style_layers.h"
|
||||||
#include "styles/style_boxes.h"
|
#include "styles/style_boxes.h"
|
||||||
#include "boxes/confirm_box.h"
|
#include "boxes/confirm_box.h"
|
||||||
#include "core/kotato_settings.h"
|
#include "core/kotato_settings.h"
|
||||||
|
@@ -15,7 +15,7 @@ class Radiobutton;
|
|||||||
class FlatLabel;
|
class FlatLabel;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
class NetBoostBox : public BoxContent {
|
class NetBoostBox : public Ui::BoxContent {
|
||||||
public:
|
public:
|
||||||
NetBoostBox(QWidget* parent);
|
NetBoostBox(QWidget* parent);
|
||||||
|
|
||||||
|
@@ -11,6 +11,7 @@ https://github.com/kotatogram/kotatogram-desktop/blob/dev/LEGAL
|
|||||||
#include "settings/settings_chat.h"
|
#include "settings/settings_chat.h"
|
||||||
#include "ui/wrap/vertical_layout.h"
|
#include "ui/wrap/vertical_layout.h"
|
||||||
#include "ui/wrap/slide_wrap.h"
|
#include "ui/wrap/slide_wrap.h"
|
||||||
|
#include "ui/widgets/buttons.h"
|
||||||
#include "ui/widgets/labels.h"
|
#include "ui/widgets/labels.h"
|
||||||
#include "ui/widgets/checkbox.h"
|
#include "ui/widgets/checkbox.h"
|
||||||
#include "ui/widgets/continuous_sliders.h"
|
#include "ui/widgets/continuous_sliders.h"
|
||||||
@@ -20,9 +21,7 @@ https://github.com/kotatogram/kotatogram-desktop/blob/dev/LEGAL
|
|||||||
#include "boxes/net_boost_box.h"
|
#include "boxes/net_boost_box.h"
|
||||||
#include "boxes/about_box.h"
|
#include "boxes/about_box.h"
|
||||||
#include "boxes/confirm_box.h"
|
#include "boxes/confirm_box.h"
|
||||||
#include "info/profile/info_profile_button.h"
|
|
||||||
#include "platform/platform_specific.h"
|
#include "platform/platform_specific.h"
|
||||||
#include "platform/platform_info.h"
|
|
||||||
#include "window/window_session_controller.h"
|
#include "window/window_session_controller.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "core/update_checker.h"
|
#include "core/update_checker.h"
|
||||||
|
@@ -1,257 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Telegram Desktop,
|
|
||||||
the official desktop application for the Telegram messaging service.
|
|
||||||
|
|
||||||
For license and copyright information please follow this link:
|
|
||||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|
||||||
*/
|
|
||||||
#include "ui/style/style_core.h"
|
|
||||||
|
|
||||||
#include "ui/effects/animation_value.h"
|
|
||||||
#include "ui/painter.h"
|
|
||||||
#include "styles/style_basic.h"
|
|
||||||
#include "styles/palette.h"
|
|
||||||
|
|
||||||
#include <QtGui/QPainter>
|
|
||||||
#include <QtGui/QFontDatabase>
|
|
||||||
|
|
||||||
#include <rpl/event_stream.h>
|
|
||||||
#include <rpl/variable.h>
|
|
||||||
|
|
||||||
namespace style {
|
|
||||||
namespace internal {
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
constexpr auto kMinContrastAlpha = 64;
|
|
||||||
constexpr auto kMinContrastDistance = 64 * 64 * 4;
|
|
||||||
constexpr auto kContrastDeltaL = 64;
|
|
||||||
|
|
||||||
auto PaletteChanges = rpl::event_stream<>();
|
|
||||||
auto ShortAnimationRunning = rpl::variable<bool>(false);
|
|
||||||
auto RunningShortAnimations = 0;
|
|
||||||
auto ResolvedMonospaceFont = style::font();
|
|
||||||
QString CustomMonospaceFont;
|
|
||||||
|
|
||||||
std::vector<internal::ModuleBase*> &StyleModules() {
|
|
||||||
static auto result = std::vector<internal::ModuleBase*>();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void startModules(int scale) {
|
|
||||||
for (const auto module : StyleModules()) {
|
|
||||||
module->start(scale);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ResolveMonospaceFont() {
|
|
||||||
auto family = QString();
|
|
||||||
const auto tryFont = [&](const QString &attempt) {
|
|
||||||
if (family.isEmpty()
|
|
||||||
&& !QFontInfo(QFont(attempt)).family().trimmed().compare(
|
|
||||||
attempt,
|
|
||||||
Qt::CaseInsensitive)) {
|
|
||||||
family = attempt;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (!CustomMonospaceFont.isEmpty()) {
|
|
||||||
tryFont(CustomMonospaceFont);
|
|
||||||
}
|
|
||||||
tryFont("Consolas");
|
|
||||||
tryFont("Liberation Mono");
|
|
||||||
tryFont("Menlo");
|
|
||||||
tryFont("Courier");
|
|
||||||
if (family.isEmpty()) {
|
|
||||||
const auto type = QFontDatabase::FixedFont;
|
|
||||||
family = QFontDatabase::systemFont(type).family();
|
|
||||||
}
|
|
||||||
const auto size = st::normalFont->f.pixelSize();
|
|
||||||
ResolvedMonospaceFont = style::font(size, 0, family);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void SetMonospaceFont(const QString &familyName) {
|
|
||||||
CustomMonospaceFont = familyName;
|
|
||||||
}
|
|
||||||
|
|
||||||
void registerModule(ModuleBase *module) {
|
|
||||||
StyleModules().push_back(module);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StartShortAnimation() {
|
|
||||||
if (++RunningShortAnimations == 1) {
|
|
||||||
ShortAnimationRunning = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void StopShortAnimation() {
|
|
||||||
if (--RunningShortAnimations == 0) {
|
|
||||||
ShortAnimationRunning = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace internal
|
|
||||||
|
|
||||||
void startManager(int scale) {
|
|
||||||
internal::registerFontFamily("Open Sans");
|
|
||||||
internal::startModules(scale);
|
|
||||||
internal::ResolveMonospaceFont();
|
|
||||||
}
|
|
||||||
|
|
||||||
void stopManager() {
|
|
||||||
internal::destroyFonts();
|
|
||||||
internal::destroyIcons();
|
|
||||||
}
|
|
||||||
|
|
||||||
rpl::producer<> PaletteChanged() {
|
|
||||||
return internal::PaletteChanges.events();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotifyPaletteChanged() {
|
|
||||||
internal::PaletteChanges.fire({});
|
|
||||||
}
|
|
||||||
|
|
||||||
rpl::producer<bool> ShortAnimationPlaying() {
|
|
||||||
return internal::ShortAnimationRunning.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
const style::font &MonospaceFont() {
|
|
||||||
return internal::ResolvedMonospaceFont;
|
|
||||||
}
|
|
||||||
|
|
||||||
void colorizeImage(const QImage &src, QColor c, QImage *outResult, QRect srcRect, QPoint dstPoint) {
|
|
||||||
// In background_box ColorizePattern we use the fact that
|
|
||||||
// colorizeImage takes only first byte of the mask, so it
|
|
||||||
// could be used for wallpaper patterns, which have values
|
|
||||||
// in ranges (0, 0, 0, 0) to (0, 0, 0, 255) (only 'alpha').
|
|
||||||
if (srcRect.isNull()) {
|
|
||||||
srcRect = src.rect();
|
|
||||||
} else {
|
|
||||||
Assert(src.rect().contains(srcRect));
|
|
||||||
}
|
|
||||||
auto width = srcRect.width();
|
|
||||||
auto height = srcRect.height();
|
|
||||||
Assert(outResult && outResult->rect().contains(QRect(dstPoint, srcRect.size())));
|
|
||||||
|
|
||||||
auto pattern = anim::shifted(c);
|
|
||||||
|
|
||||||
auto resultBytesPerPixel = (src.depth() >> 3);
|
|
||||||
constexpr auto resultIntsPerPixel = 1;
|
|
||||||
auto resultIntsPerLine = (outResult->bytesPerLine() >> 2);
|
|
||||||
auto resultIntsAdded = resultIntsPerLine - width * resultIntsPerPixel;
|
|
||||||
auto resultInts = reinterpret_cast<uint32*>(outResult->bits()) + dstPoint.y() * resultIntsPerLine + dstPoint.x() * resultIntsPerPixel;
|
|
||||||
Assert(resultIntsAdded >= 0);
|
|
||||||
Assert(outResult->depth() == static_cast<int>((resultIntsPerPixel * sizeof(uint32)) << 3));
|
|
||||||
Assert(outResult->bytesPerLine() == (resultIntsPerLine << 2));
|
|
||||||
|
|
||||||
auto maskBytesPerPixel = (src.depth() >> 3);
|
|
||||||
auto maskBytesPerLine = src.bytesPerLine();
|
|
||||||
auto maskBytesAdded = maskBytesPerLine - width * maskBytesPerPixel;
|
|
||||||
auto maskBytes = src.constBits() + srcRect.y() * maskBytesPerLine + srcRect.x() * maskBytesPerPixel;
|
|
||||||
Assert(maskBytesAdded >= 0);
|
|
||||||
Assert(src.depth() == (maskBytesPerPixel << 3));
|
|
||||||
for (int y = 0; y != height; ++y) {
|
|
||||||
for (int x = 0; x != width; ++x) {
|
|
||||||
auto maskOpacity = static_cast<anim::ShiftedMultiplier>(*maskBytes) + 1;
|
|
||||||
*resultInts = anim::unshifted(pattern * maskOpacity);
|
|
||||||
maskBytes += maskBytesPerPixel;
|
|
||||||
resultInts += resultIntsPerPixel;
|
|
||||||
}
|
|
||||||
maskBytes += maskBytesAdded;
|
|
||||||
resultInts += resultIntsAdded;
|
|
||||||
}
|
|
||||||
|
|
||||||
outResult->setDevicePixelRatio(src.devicePixelRatio());
|
|
||||||
}
|
|
||||||
|
|
||||||
QBrush transparentPlaceholderBrush() {
|
|
||||||
auto size = st::transparentPlaceholderSize * DevicePixelRatio();
|
|
||||||
auto transparent = QImage(2 * size, 2 * size, QImage::Format_ARGB32_Premultiplied);
|
|
||||||
transparent.fill(st::mediaviewTransparentBg->c);
|
|
||||||
{
|
|
||||||
QPainter p(&transparent);
|
|
||||||
p.fillRect(0, size, size, size, st::mediaviewTransparentFg);
|
|
||||||
p.fillRect(size, 0, size, size, st::mediaviewTransparentFg);
|
|
||||||
}
|
|
||||||
transparent.setDevicePixelRatio(DevicePixelRatio());
|
|
||||||
return QBrush(transparent);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
QImage createCircleMask(int size, QColor bg, QColor fg) {
|
|
||||||
int realSize = size * DevicePixelRatio();
|
|
||||||
#ifndef OS_MAC_OLD
|
|
||||||
auto result = QImage(realSize, realSize, QImage::Format::Format_Grayscale8);
|
|
||||||
#else // OS_MAC_OLD
|
|
||||||
auto result = QImage(realSize, realSize, QImage::Format::Format_RGB32);
|
|
||||||
#endif // OS_MAC_OLD
|
|
||||||
{
|
|
||||||
QPainter p(&result);
|
|
||||||
PainterHighQualityEnabler hq(p);
|
|
||||||
|
|
||||||
p.fillRect(0, 0, realSize, realSize, bg);
|
|
||||||
p.setPen(Qt::NoPen);
|
|
||||||
p.setBrush(fg);
|
|
||||||
p.drawEllipse(0, 0, realSize, realSize);
|
|
||||||
}
|
|
||||||
result.setDevicePixelRatio(DevicePixelRatio());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool GoodForContrast(const QColor &c1, const QColor &c2) {
|
|
||||||
auto r1 = 0;
|
|
||||||
auto g1 = 0;
|
|
||||||
auto b1 = 0;
|
|
||||||
auto r2 = 0;
|
|
||||||
auto g2 = 0;
|
|
||||||
auto b2 = 0;
|
|
||||||
c1.getRgb(&r1, &g1, &b1);
|
|
||||||
c2.getRgb(&r2, &g2, &b2);
|
|
||||||
const auto rMean = (r1 + r2) / 2;
|
|
||||||
const auto r = r1 - r2;
|
|
||||||
const auto g = g1 - g2;
|
|
||||||
const auto b = b1 - b2;
|
|
||||||
const auto distance = (((512 + rMean) * r * r) >> 8)
|
|
||||||
+ (4 * g * g)
|
|
||||||
+ (((767 - rMean) * b * b) >> 8);
|
|
||||||
return (distance > kMinContrastDistance);
|
|
||||||
}
|
|
||||||
|
|
||||||
QColor EnsureContrast(const QColor &over, const QColor &under) {
|
|
||||||
auto overH = 0;
|
|
||||||
auto overS = 0;
|
|
||||||
auto overL = 0;
|
|
||||||
auto overA = 0;
|
|
||||||
auto underH = 0;
|
|
||||||
auto underS = 0;
|
|
||||||
auto underL = 0;
|
|
||||||
over.getHsl(&overH, &overS, &overL, &overA);
|
|
||||||
under.getHsl(&underH, &underS, &underL);
|
|
||||||
const auto good = GoodForContrast(over, under);
|
|
||||||
if (overA >= kMinContrastAlpha && good) {
|
|
||||||
return over;
|
|
||||||
}
|
|
||||||
const auto newA = std::max(overA, kMinContrastAlpha);
|
|
||||||
const auto newL = (overL > underL && overL + kContrastDeltaL <= 255)
|
|
||||||
? (overL + kContrastDeltaL)
|
|
||||||
: (overL < underL && overL - kContrastDeltaL >= 0)
|
|
||||||
? (overL - kContrastDeltaL)
|
|
||||||
: (underL > 128)
|
|
||||||
? (underL - kContrastDeltaL)
|
|
||||||
: (underL + kContrastDeltaL);
|
|
||||||
return QColor::fromHsl(overH, overS, newL, newA).toRgb();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnsureContrast(ColorData &over, const ColorData &under) {
|
|
||||||
const auto good = EnsureContrast(over.c, under.c);
|
|
||||||
if (over.c != good) {
|
|
||||||
over.c = good;
|
|
||||||
over.p = QPen(good);
|
|
||||||
over.b = QBrush(good);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace internal
|
|
||||||
} // namespace style
|
|
@@ -1,82 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Telegram Desktop,
|
|
||||||
the official desktop application for the Telegram messaging service.
|
|
||||||
|
|
||||||
For license and copyright information please follow this link:
|
|
||||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "ui/style/style_core_scale.h"
|
|
||||||
#include "ui/style/style_core_types.h"
|
|
||||||
#include "ui/style/style_core_direction.h"
|
|
||||||
|
|
||||||
#include <rpl/producer.h>
|
|
||||||
|
|
||||||
namespace style {
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
// Objects of derived classes are created in global scope.
|
|
||||||
// They call [un]registerModule() in [de|con]structor.
|
|
||||||
class ModuleBase {
|
|
||||||
public:
|
|
||||||
virtual void start(int scale) = 0;
|
|
||||||
|
|
||||||
virtual ~ModuleBase() = default;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
void SetMonospaceFont(const QString &familyName);
|
|
||||||
|
|
||||||
void registerModule(ModuleBase *module);
|
|
||||||
|
|
||||||
[[nodiscard]] QColor EnsureContrast(const QColor &over, const QColor &under);
|
|
||||||
void EnsureContrast(ColorData &over, const ColorData &under);
|
|
||||||
|
|
||||||
void StartShortAnimation();
|
|
||||||
void StopShortAnimation();
|
|
||||||
|
|
||||||
} // namespace internal
|
|
||||||
|
|
||||||
void startManager(int scale);
|
|
||||||
void stopManager();
|
|
||||||
|
|
||||||
[[nodiscard]] rpl::producer<> PaletteChanged();
|
|
||||||
void NotifyPaletteChanged();
|
|
||||||
|
|
||||||
[[nodiscard]] rpl::producer<bool> ShortAnimationPlaying();
|
|
||||||
|
|
||||||
const style::font &MonospaceFont();
|
|
||||||
|
|
||||||
// *outResult must be r.width() x r.height(), ARGB32_Premultiplied.
|
|
||||||
// QRect(0, 0, src.width(), src.height()) must contain r.
|
|
||||||
void colorizeImage(const QImage &src, QColor c, QImage *outResult, QRect srcRect = QRect(), QPoint dstPoint = QPoint(0, 0));
|
|
||||||
|
|
||||||
inline QImage colorizeImage(const QImage &src, QColor c, QRect srcRect = QRect()) {
|
|
||||||
if (srcRect.isNull()) srcRect = src.rect();
|
|
||||||
auto result = QImage(srcRect.size(), QImage::Format_ARGB32_Premultiplied);
|
|
||||||
colorizeImage(src, c, &result, srcRect);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QImage colorizeImage(const QImage &src, const color &c, QRect srcRect = QRect()) {
|
|
||||||
return colorizeImage(src, c->c, srcRect);
|
|
||||||
}
|
|
||||||
|
|
||||||
QBrush transparentPlaceholderBrush();
|
|
||||||
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
QImage createCircleMask(int size, QColor bg, QColor fg);
|
|
||||||
|
|
||||||
} // namespace internal
|
|
||||||
|
|
||||||
inline QImage createCircleMask(int size) {
|
|
||||||
return internal::createCircleMask(size, QColor(0, 0, 0), QColor(255, 255, 255));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QImage createInvertedCircleMask(int size) {
|
|
||||||
return internal::createCircleMask(size, QColor(255, 255, 255), QColor(0, 0, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace style
|
|
@@ -1,273 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Telegram Desktop,
|
|
||||||
the official desktop application for the Telegram messaging service.
|
|
||||||
|
|
||||||
For license and copyright information please follow this link:
|
|
||||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|
||||||
*/
|
|
||||||
#include "ui/style/style_core_font.h"
|
|
||||||
|
|
||||||
#include "base/algorithm.h"
|
|
||||||
#include "ui/ui_log.h"
|
|
||||||
|
|
||||||
#include <QtCore/QMap>
|
|
||||||
#include <QtCore/QVector>
|
|
||||||
#include <QtGui/QFontInfo>
|
|
||||||
#include <QtGui/QFontDatabase>
|
|
||||||
|
|
||||||
namespace style {
|
|
||||||
namespace internal {
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
QMap<QString, int> fontFamilyMap;
|
|
||||||
QVector<QString> fontFamilies;
|
|
||||||
QMap<uint32, FontData*> fontsMap;
|
|
||||||
|
|
||||||
uint32 fontKey(int size, uint32 flags, int family) {
|
|
||||||
return (((uint32(family) << 10) | uint32(size)) << 4) | flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ValidateFont(const QString &familyName, int flags = 0) {
|
|
||||||
QFont checkFont(familyName);
|
|
||||||
checkFont.setPixelSize(13);
|
|
||||||
checkFont.setBold(flags & style::internal::FontBold);
|
|
||||||
checkFont.setItalic(flags & style::internal::FontItalic);
|
|
||||||
checkFont.setUnderline(flags & style::internal::FontUnderline);
|
|
||||||
checkFont.setStyleStrategy(QFont::PreferQuality);
|
|
||||||
auto realFamily = QFontInfo(checkFont).family();
|
|
||||||
if (realFamily.trimmed().compare(familyName, Qt::CaseInsensitive)) {
|
|
||||||
UI_LOG(("Font Error: could not resolve '%1' font, got '%2'.").arg(familyName).arg(realFamily));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto metrics = QFontMetrics(checkFont);
|
|
||||||
if (!metrics.height()) {
|
|
||||||
UI_LOG(("Font Error: got a zero height in '%1'.").arg(familyName));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LoadCustomFont(const QString &filePath, const QString &familyName, int flags = 0) {
|
|
||||||
auto regularId = QFontDatabase::addApplicationFont(filePath);
|
|
||||||
if (regularId < 0) {
|
|
||||||
UI_LOG(("Font Error: could not add '%1'.").arg(filePath));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto found = [&familyName, regularId] {
|
|
||||||
for (auto &family : QFontDatabase::applicationFontFamilies(regularId)) {
|
|
||||||
if (!family.trimmed().compare(familyName, Qt::CaseInsensitive)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
if (!found()) {
|
|
||||||
UI_LOG(("Font Error: could not locate '%1' font in '%2'.").arg(familyName).arg(filePath));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ValidateFont(familyName, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Started = false;
|
|
||||||
QString OpenSansOverride;
|
|
||||||
QString OpenSansSemiboldOverride;
|
|
||||||
|
|
||||||
QString CustomMainFont;
|
|
||||||
QString CustomSemiboldFont;
|
|
||||||
bool CustomSemiboldIsBold = false;
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void SetMainFont(const QString &familyName) {
|
|
||||||
CustomMainFont = familyName;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetSemiboldFont(const QString &familyName) {
|
|
||||||
CustomSemiboldFont = familyName;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetSemiboldIsBold(bool isBold) {
|
|
||||||
CustomSemiboldIsBold = isBold;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StartFonts() {
|
|
||||||
if (Started) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Started = true;
|
|
||||||
|
|
||||||
auto regular = LoadCustomFont(":/gui/fonts/OpenSans-Regular.ttf", "Open Sans");
|
|
||||||
auto bold = LoadCustomFont(":/gui/fonts/OpenSans-Bold.ttf", "Open Sans", style::internal::FontBold);
|
|
||||||
auto semibold = LoadCustomFont(":/gui/fonts/OpenSans-Semibold.ttf", "Open Sans Semibold");
|
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
// Attempt to workaround a strange font bug with Open Sans Semibold not loading.
|
|
||||||
// See https://github.com/telegramdesktop/tdesktop/issues/3276 for details.
|
|
||||||
// Crash happens on "options.maxh / _t->_st->font->height" with "division by zero".
|
|
||||||
// In that place "_t->_st->font" is "semiboldFont" is "font(13 "Open Sans Semibold").
|
|
||||||
if (!regular || !bold) {
|
|
||||||
if (ValidateFont("Segoe UI") && ValidateFont("Segoe UI", style::internal::FontBold)) {
|
|
||||||
OpenSansOverride = "Segoe UI";
|
|
||||||
UI_LOG(("Fonts Info: Using Segoe UI instead of Open Sans."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!semibold) {
|
|
||||||
if (ValidateFont("Segoe UI Semibold")) {
|
|
||||||
OpenSansSemiboldOverride = "Segoe UI Semibold";
|
|
||||||
UI_LOG(("Fonts Info: Using Segoe UI Semibold instead of Open Sans Semibold."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Disable default fallbacks to Segoe UI, see:
|
|
||||||
// https://github.com/telegramdesktop/tdesktop/issues/5368
|
|
||||||
//
|
|
||||||
//QFont::insertSubstitution("Open Sans", "Segoe UI");
|
|
||||||
//QFont::insertSubstitution("Open Sans Semibold", "Segoe UI Semibold");
|
|
||||||
#elif defined Q_OS_MAC // Q_OS_WIN
|
|
||||||
auto list = QStringList();
|
|
||||||
list.append(".SF NS Text");
|
|
||||||
list.append("Helvetica Neue");
|
|
||||||
list.append("Lucida Grande");
|
|
||||||
QFont::insertSubstitutions("Open Sans", list);
|
|
||||||
QFont::insertSubstitutions("Open Sans Semibold", list);
|
|
||||||
#endif // Q_OS_WIN || Q_OS_MAC
|
|
||||||
|
|
||||||
if (!CustomMainFont.isEmpty() && ValidateFont(CustomMainFont)) {
|
|
||||||
OpenSansOverride = CustomMainFont;
|
|
||||||
}
|
|
||||||
if (!CustomSemiboldFont.isEmpty() && ValidateFont(CustomSemiboldFont)) {
|
|
||||||
OpenSansSemiboldOverride = CustomSemiboldFont;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString GetFontOverride(const QString &familyName) {
|
|
||||||
if (familyName == qstr("Open Sans")) {
|
|
||||||
return OpenSansOverride.isEmpty() ? familyName : OpenSansOverride;
|
|
||||||
} else if (familyName == qstr("Open Sans Semibold")) {
|
|
||||||
return OpenSansSemiboldOverride.isEmpty() ? familyName : OpenSansSemiboldOverride;
|
|
||||||
}
|
|
||||||
return familyName;
|
|
||||||
}
|
|
||||||
|
|
||||||
void destroyFonts() {
|
|
||||||
for (auto fontData : fontsMap) {
|
|
||||||
delete fontData;
|
|
||||||
}
|
|
||||||
fontsMap.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
int registerFontFamily(const QString &family) {
|
|
||||||
auto result = fontFamilyMap.value(family, -1);
|
|
||||||
if (result < 0) {
|
|
||||||
result = fontFamilies.size();
|
|
||||||
fontFamilyMap.insert(family, result);
|
|
||||||
fontFamilies.push_back(family);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
FontData::FontData(int size, uint32 flags, int family, Font *other)
|
|
||||||
: f(GetFontOverride(fontFamilies[family]))
|
|
||||||
, m(f)
|
|
||||||
, _size(size)
|
|
||||||
, _flags(flags)
|
|
||||||
, _family(family) {
|
|
||||||
if (other) {
|
|
||||||
memcpy(modified, other, sizeof(modified));
|
|
||||||
} else {
|
|
||||||
memset(modified, 0, sizeof(modified));
|
|
||||||
}
|
|
||||||
modified[_flags] = Font(this);
|
|
||||||
|
|
||||||
f.setPixelSize(size);
|
|
||||||
if (_flags & FontBold) {
|
|
||||||
f.setBold(true);
|
|
||||||
} else if (fontFamilies[family] == "Open Sans Semibold" && CustomSemiboldIsBold) {
|
|
||||||
f.setBold(true);
|
|
||||||
}
|
|
||||||
f.setItalic(_flags & FontItalic);
|
|
||||||
f.setUnderline(_flags & FontUnderline);
|
|
||||||
f.setStrikeOut(_flags & FontStrikeOut);
|
|
||||||
f.setStyleStrategy(QFont::PreferQuality);
|
|
||||||
|
|
||||||
m = QFontMetrics(f);
|
|
||||||
height = m.height();
|
|
||||||
ascent = m.ascent();
|
|
||||||
descent = m.descent();
|
|
||||||
spacew = width(QLatin1Char(' '));
|
|
||||||
elidew = width("...");
|
|
||||||
}
|
|
||||||
|
|
||||||
Font FontData::bold(bool set) const {
|
|
||||||
return otherFlagsFont(FontBold, set);
|
|
||||||
}
|
|
||||||
|
|
||||||
Font FontData::italic(bool set) const {
|
|
||||||
return otherFlagsFont(FontItalic, set);
|
|
||||||
}
|
|
||||||
|
|
||||||
Font FontData::underline(bool set) const {
|
|
||||||
return otherFlagsFont(FontUnderline, set);
|
|
||||||
}
|
|
||||||
|
|
||||||
Font FontData::strikeout(bool set) const {
|
|
||||||
return otherFlagsFont(FontStrikeOut, set);
|
|
||||||
}
|
|
||||||
|
|
||||||
int FontData::size() const {
|
|
||||||
return _size;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 FontData::flags() const {
|
|
||||||
return _flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FontData::family() const {
|
|
||||||
return _family;
|
|
||||||
}
|
|
||||||
|
|
||||||
Font FontData::otherFlagsFont(uint32 flag, bool set) const {
|
|
||||||
int32 newFlags = set ? (_flags | flag) : (_flags & ~flag);
|
|
||||||
if (!modified[newFlags].v()) {
|
|
||||||
modified[newFlags] = Font(_size, newFlags, _family, modified);
|
|
||||||
}
|
|
||||||
return modified[newFlags];
|
|
||||||
}
|
|
||||||
|
|
||||||
Font::Font(int size, uint32 flags, const QString &family) {
|
|
||||||
if (fontFamilyMap.isEmpty()) {
|
|
||||||
for (uint32 i = 0, s = fontFamilies.size(); i != s; ++i) {
|
|
||||||
fontFamilyMap.insert(fontFamilies.at(i), i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto i = fontFamilyMap.constFind(family);
|
|
||||||
if (i == fontFamilyMap.cend()) {
|
|
||||||
fontFamilies.push_back(family);
|
|
||||||
i = fontFamilyMap.insert(family, fontFamilies.size() - 1);
|
|
||||||
}
|
|
||||||
init(size, flags, i.value(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Font::Font(int size, uint32 flags, int family) {
|
|
||||||
init(size, flags, family, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Font::Font(int size, uint32 flags, int family, Font *modified) {
|
|
||||||
init(size, flags, family, modified);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Font::init(int size, uint32 flags, int family, Font *modified) {
|
|
||||||
uint32 key = fontKey(size, flags, family);
|
|
||||||
auto i = fontsMap.constFind(key);
|
|
||||||
if (i == fontsMap.cend()) {
|
|
||||||
i = fontsMap.insert(key, new FontData(size, flags, family, modified));
|
|
||||||
}
|
|
||||||
ptr = i.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace internal
|
|
||||||
} // namespace style
|
|
@@ -1,130 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Telegram Desktop,
|
|
||||||
the official desktop application for the Telegram messaging service.
|
|
||||||
|
|
||||||
For license and copyright information please follow this link:
|
|
||||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "base/basic_types.h"
|
|
||||||
|
|
||||||
#include <QtGui/QFont>
|
|
||||||
#include <QtGui/QFontMetrics>
|
|
||||||
|
|
||||||
namespace style {
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
void SetMainFont(const QString &familyName);
|
|
||||||
void SetSemiboldFont(const QString &familyName);
|
|
||||||
void SetSemiboldIsBold(bool isBold);
|
|
||||||
|
|
||||||
void StartFonts();
|
|
||||||
[[nodiscard]] QString GetFontOverride(const QString &familyName);
|
|
||||||
|
|
||||||
void destroyFonts();
|
|
||||||
int registerFontFamily(const QString &family);
|
|
||||||
|
|
||||||
class FontData;
|
|
||||||
class Font {
|
|
||||||
public:
|
|
||||||
Font(Qt::Initialization = Qt::Uninitialized) : ptr(0) {
|
|
||||||
}
|
|
||||||
Font(int size, uint32 flags, const QString &family);
|
|
||||||
Font(int size, uint32 flags, int family);
|
|
||||||
|
|
||||||
Font &operator=(const Font &other) {
|
|
||||||
ptr = other.ptr;
|
|
||||||
return (*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
FontData *operator->() const {
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
FontData *v() const {
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
operator bool() const {
|
|
||||||
return !!ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
operator const QFont &() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
FontData *ptr;
|
|
||||||
|
|
||||||
void init(int size, uint32 flags, int family, Font *modified);
|
|
||||||
friend void startManager();
|
|
||||||
|
|
||||||
Font(FontData *p) : ptr(p) {
|
|
||||||
}
|
|
||||||
Font(int size, uint32 flags, int family, Font *modified);
|
|
||||||
friend class FontData;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
enum FontFlags {
|
|
||||||
FontBold = 0x01,
|
|
||||||
FontItalic = 0x02,
|
|
||||||
FontUnderline = 0x04,
|
|
||||||
FontStrikeOut = 0x08,
|
|
||||||
|
|
||||||
FontDifferentFlags = 0x10,
|
|
||||||
};
|
|
||||||
|
|
||||||
class FontData {
|
|
||||||
public:
|
|
||||||
|
|
||||||
int32 width(const QString &str) const {
|
|
||||||
return m.width(str);
|
|
||||||
}
|
|
||||||
int32 width(const QString &str, int32 from, int32 to) const {
|
|
||||||
return width(str.mid(from, to));
|
|
||||||
}
|
|
||||||
int32 width(QChar ch) const {
|
|
||||||
return m.width(ch);
|
|
||||||
}
|
|
||||||
QString elided(const QString &str, int32 width, Qt::TextElideMode mode = Qt::ElideRight) const {
|
|
||||||
return m.elidedText(str, mode, width);
|
|
||||||
}
|
|
||||||
|
|
||||||
Font bold(bool set = true) const;
|
|
||||||
Font italic(bool set = true) const;
|
|
||||||
Font underline(bool set = true) const;
|
|
||||||
Font strikeout(bool set = true) const;
|
|
||||||
|
|
||||||
int size() const;
|
|
||||||
uint32 flags() const;
|
|
||||||
int family() const;
|
|
||||||
|
|
||||||
QFont f;
|
|
||||||
QFontMetrics m;
|
|
||||||
int32 height, ascent, descent, spacew, elidew;
|
|
||||||
|
|
||||||
private:
|
|
||||||
mutable Font modified[FontDifferentFlags];
|
|
||||||
|
|
||||||
Font otherFlagsFont(uint32 flag, bool set) const;
|
|
||||||
FontData(int size, uint32 flags, int family, Font *other);
|
|
||||||
|
|
||||||
friend class Font;
|
|
||||||
int _size;
|
|
||||||
uint32 _flags;
|
|
||||||
int _family;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
inline bool operator==(const Font &a, const Font &b) {
|
|
||||||
return a.v() == b.v();
|
|
||||||
}
|
|
||||||
inline bool operator!=(const Font &a, const Font &b) {
|
|
||||||
return a.v() != b.v();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Font::operator const QFont &() const {
|
|
||||||
return ptr->f;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace internal
|
|
||||||
} // namespace style
|
|
@@ -74,7 +74,7 @@
|
|||||||
'configurations': {
|
'configurations': {
|
||||||
'Debug': {
|
'Debug': {
|
||||||
'xcode_settings': {
|
'xcode_settings': {
|
||||||
'PRODUCT_BUNDLE_IDENTIFIER': 'io.github.KotatogramDebugOld',
|
'PRODUCT_BUNDLE_IDENTIFIER': 'io.github.KotatogramDebugOsx',
|
||||||
},
|
},
|
||||||
'library_dirs': [
|
'library_dirs': [
|
||||||
'<(libs_loc)/crashpad/out/Debug',
|
'<(libs_loc)/crashpad/out/Debug',
|
||||||
|
Reference in New Issue
Block a user