From e2f54eb3e9bcb1b529ab832e53617b807a64d508 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 13 Sep 2019 13:24:06 +0300 Subject: [PATCH] Move some style code to lib_ui. --- Telegram/SourceFiles/base/assertion.h | 3 + Telegram/SourceFiles/base/base_pch.cpp | 1 + Telegram/SourceFiles/boxes/edit_color_box.cpp | 4 +- .../chat_helpers/emoji_list_widget.cpp | 29 +- .../chat_helpers/emoji_list_widget.h | 9 +- .../chat_helpers/emoji_suggestions_widget.cpp | 2 +- .../chat_helpers/message_field.cpp | 2 +- .../SourceFiles/codegen/common/cpp_file.cpp | 5 + .../SourceFiles/codegen/common/cpp_file.h | 1 + .../SourceFiles/codegen/emoji/generator.cpp | 55 ++-- .../SourceFiles/codegen/style/generator.cpp | 65 ++++- .../SourceFiles/codegen/style/generator.h | 1 + Telegram/SourceFiles/codegen/style/module.cpp | 4 +- Telegram/SourceFiles/codegen/style/module.h | 4 +- Telegram/SourceFiles/core/application.cpp | 5 +- .../SourceFiles/core/crash_report_window.cpp | 12 +- Telegram/SourceFiles/core/launcher.cpp | 2 +- Telegram/SourceFiles/core/sandbox.cpp | 5 +- .../dialogs/dialogs_inner_widget.cpp | 2 +- Telegram/SourceFiles/export/export_pch.cpp | 1 + .../view/media/history_view_document.cpp | 4 +- .../history/view/media/history_view_gif.cpp | 4 +- .../history/view/media/history_view_photo.cpp | 11 +- .../media/history_view_theme_document.cpp | 12 +- .../history/view/media/history_view_video.cpp | 6 +- .../view/media/history_view_web_page.cpp | 4 +- .../inline_bot_layout_internal.cpp | 17 +- .../media/view/media_view_overlay_widget.cpp | 14 +- Telegram/SourceFiles/mtproto/mtp_pch.cpp | 1 + .../SourceFiles/overview/overview_layout.cpp | 11 +- .../SourceFiles/platform/mac/mac_touchbar.mm | 14 +- Telegram/SourceFiles/settings.cpp | 142 ++++++++- Telegram/SourceFiles/settings.h | 80 +++--- .../SourceFiles/settings/settings_main.cpp | 10 +- Telegram/SourceFiles/stdafx.h | 3 - Telegram/SourceFiles/storage/localstorage.cpp | 8 +- .../storage/storage_media_prepare.cpp | 2 +- Telegram/SourceFiles/storage/storage_pch.cpp | 1 + .../SourceFiles/ui/effects/animation_value.h | 2 +- Telegram/SourceFiles/ui/emoji_config.cpp | 269 +++--------------- Telegram/SourceFiles/ui/emoji_config.h | 20 +- Telegram/SourceFiles/ui/painter.h | 118 ++++++++ Telegram/SourceFiles/ui/style/style_core.cpp | 69 +++-- Telegram/SourceFiles/ui/style/style_core.h | 28 +- .../SourceFiles/ui/style/style_core_color.cpp | 2 + .../SourceFiles/ui/style/style_core_color.h | 4 + .../SourceFiles/ui/style/style_core_font.cpp | 123 +++++++- .../SourceFiles/ui/style/style_core_font.h | 8 + .../SourceFiles/ui/style/style_core_icon.cpp | 83 +++--- .../SourceFiles/ui/style/style_core_icon.h | 20 +- .../SourceFiles/ui/style/style_core_scale.cpp | 38 +++ .../SourceFiles/ui/style/style_core_scale.h | 50 ++++ Telegram/SourceFiles/ui/text/text.h | 1 + Telegram/SourceFiles/ui/text/text_entity.h | 4 + Telegram/SourceFiles/ui/twidget.cpp | 108 ------- Telegram/SourceFiles/ui/twidget.h | 131 ++------- Telegram/SourceFiles/ui/ui_pch.cpp | 10 + Telegram/SourceFiles/ui/ui_pch.h | 21 ++ .../SourceFiles/ui/widgets/input_fields.cpp | 3 +- .../window/themes/window_theme.cpp | 2 +- .../window/themes/window_theme_preview.cpp | 4 +- .../SourceFiles/window/window_main_menu.cpp | 2 +- .../window/window_media_preview.cpp | 2 +- Telegram/gyp/Telegram.gyp | 10 +- Telegram/gyp/codegen_rules.gypi | 93 +----- Telegram/gyp/codegen_rules_ui.gypi | 58 ++++ Telegram/gyp/codegen_styles_rule.gypi | 54 ++++ Telegram/gyp/lib_scheme.gyp | 4 +- Telegram/gyp/lib_ui.gyp | 78 +++++ 69 files changed, 1119 insertions(+), 856 deletions(-) create mode 100644 Telegram/SourceFiles/ui/painter.h create mode 100644 Telegram/SourceFiles/ui/style/style_core_scale.cpp create mode 100644 Telegram/SourceFiles/ui/style/style_core_scale.h create mode 100644 Telegram/SourceFiles/ui/ui_pch.cpp create mode 100644 Telegram/SourceFiles/ui/ui_pch.h create mode 100644 Telegram/gyp/codegen_rules_ui.gypi create mode 100644 Telegram/gyp/codegen_styles_rule.gypi create mode 100644 Telegram/gyp/lib_ui.gyp diff --git a/Telegram/SourceFiles/base/assertion.h b/Telegram/SourceFiles/base/assertion.h index c354915d0..d7907a583 100644 --- a/Telegram/SourceFiles/base/assertion.h +++ b/Telegram/SourceFiles/base/assertion.h @@ -9,6 +9,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include +// Ensures/Expects. +#include + namespace base { namespace assertion { diff --git a/Telegram/SourceFiles/base/base_pch.cpp b/Telegram/SourceFiles/base/base_pch.cpp index 56aa55468..33c7d3279 100644 --- a/Telegram/SourceFiles/base/base_pch.cpp +++ b/Telegram/SourceFiles/base/base_pch.cpp @@ -7,3 +7,4 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "base/base_pch.h" +// Precompiled header helper. diff --git a/Telegram/SourceFiles/boxes/edit_color_box.cpp b/Telegram/SourceFiles/boxes/edit_color_box.cpp index 4232a02e2..6efe374c8 100644 --- a/Telegram/SourceFiles/boxes/edit_color_box.cpp +++ b/Telegram/SourceFiles/boxes/edit_color_box.cpp @@ -65,8 +65,8 @@ private: }; QCursor EditColorBox::Picker::generateCursor() { - auto diameter = ConvertScale(16); - auto line = ConvertScale(1); + auto diameter = style::ConvertScale(16); + auto line = style::ConvertScale(1); auto size = ((diameter + 2 * line) >= 32) ? 64 : 32; auto cursor = QImage(QSize(size, size) * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied); cursor.setDevicePixelRatio(cRetinaFactor()); diff --git a/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp index 28b24a205..69e94913a 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp @@ -393,7 +393,10 @@ EmojiListWidget::EmojiListWidget( _esize = Ui::Emoji::GetSizeLarge(); for (auto i = 0; i != kEmojiSectionCount; ++i) { - _counts[i] = Ui::Emoji::GetSectionCount(static_cast
(i)); + const auto section = static_cast
(i); + _counts[i] = (section == Section::Recent) + ? GetRecentEmoji().size() + : Ui::Emoji::GetSectionCount(section); } _picker->chosen( @@ -488,10 +491,13 @@ int EmojiListWidget::countDesiredHeight(int newWidth) { void EmojiListWidget::ensureLoaded(int section) { Expects(section >= 0 && section < kEmojiSectionCount); + if (!_emoji[section].isEmpty()) { return; } - _emoji[section] = Ui::Emoji::GetSection(static_cast
(section)); + _emoji[section] = (static_cast
(section) == Section::Recent) + ? GetRecentEmojiSection() + : Ui::Emoji::GetSection(static_cast
(section)); _counts[section] = _emoji[section].size(); if (static_cast
(section) == Section::Recent) { return; @@ -531,7 +537,7 @@ void EmojiListWidget::paintEvent(QPaintEvent *e) { if (info.section > 0 && r.top() < info.rowsTop) { p.setFont(st::emojiPanHeaderFont); p.setPen(st::emojiPanHeaderFg); - p.drawTextLeft(st::emojiPanHeaderLeft - st::buttonRadius, info.top + st::emojiPanHeaderTop, width(), Ui::Emoji::CategoryTitle(info.section)(tr::now)); + p.drawTextLeft(st::emojiPanHeaderLeft - st::buttonRadius, info.top + st::emojiPanHeaderTop, width(), ChatHelpers::EmojiCategoryTitle(info.section)(tr::now)); } if (r.top() + r.height() > info.rowsTop) { ensureLoaded(info.section); @@ -640,7 +646,7 @@ void EmojiListWidget::mouseReleaseEvent(QMouseEvent *e) { } void EmojiListWidget::selectEmoji(EmojiPtr emoji) { - Ui::Emoji::AddRecent(emoji); + AddRecentEmoji(emoji); _chosen.fire_copy(emoji); } @@ -776,7 +782,7 @@ void EmojiListWidget::processHideFinished() { void EmojiListWidget::refreshRecent() { clearSelection(); - _emoji[0] = Ui::Emoji::GetSection(Section::Recent); + _emoji[0] = GetRecentEmojiSection(); _counts[0] = _emoji[0].size(); resizeToWidth(width()); } @@ -859,4 +865,17 @@ void EmojiListWidget::showEmojiSection(Section section) { update(); } +tr::phrase<> EmojiCategoryTitle(int index) { + switch (index) { + case 1: return tr::lng_emoji_category1; + case 2: return tr::lng_emoji_category2; + case 3: return tr::lng_emoji_category3; + case 4: return tr::lng_emoji_category4; + case 5: return tr::lng_emoji_category5; + case 6: return tr::lng_emoji_category6; + case 7: return tr::lng_emoji_category7; + } + Unexpected("Index in CategoryTitle."); +} + } // namespace ChatHelpers diff --git a/Telegram/SourceFiles/chat_helpers/emoji_list_widget.h b/Telegram/SourceFiles/chat_helpers/emoji_list_widget.h index 277e810e9..564b53e16 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_list_widget.h +++ b/Telegram/SourceFiles/chat_helpers/emoji_list_widget.h @@ -11,6 +11,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/tooltip.h" #include "base/timer.h" +namespace tr { +template +struct phrase; +} // namespace tr + namespace Ui { namespace Emoji { enum class Section; @@ -23,7 +28,7 @@ class SessionController; namespace ChatHelpers { -constexpr auto kEmojiSectionCount = 8; +inline constexpr auto kEmojiSectionCount = 8; class EmojiColorPicker; @@ -120,4 +125,6 @@ private: }; +tr::phrase<> EmojiCategoryTitle(int index); + } // namespace ChatHelpers diff --git a/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp b/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp index e1a918dc8..b6787e4c3 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp @@ -114,7 +114,7 @@ auto SuggestionsWidget::getRowsByQuery() const -> std::vector { }) | ranges::to_vector; auto lastRecent = begin(result); - const auto &recent = GetRecent(); + const auto &recent = GetRecentEmoji(); for (const auto &item : recent) { const auto emoji = item.first->original() ? item.first->original() diff --git a/Telegram/SourceFiles/chat_helpers/message_field.cpp b/Telegram/SourceFiles/chat_helpers/message_field.cpp index c8ff1d161..f5410896f 100644 --- a/Telegram/SourceFiles/chat_helpers/message_field.cpp +++ b/Telegram/SourceFiles/chat_helpers/message_field.cpp @@ -384,7 +384,7 @@ void InitMessageField( field->setTagMimeProcessor(std::make_unique()); field->document()->setDocumentMargin(4.); - field->setAdditionalMargin(ConvertScale(4) - 4); + field->setAdditionalMargin(style::ConvertScale(4) - 4); field->customTab(true); field->setInstantReplaces(Ui::InstantReplaces::Default()); diff --git a/Telegram/SourceFiles/codegen/common/cpp_file.cpp b/Telegram/SourceFiles/codegen/common/cpp_file.cpp index 3a986bb0f..842f1e8d2 100644 --- a/Telegram/SourceFiles/codegen/common/cpp_file.cpp +++ b/Telegram/SourceFiles/codegen/common/cpp_file.cpp @@ -53,6 +53,11 @@ CppFile &CppFile::include(const QString &header) { return newline(); } +CppFile &CppFile::includeFromLibrary(const QString &header) { + stream() << "#include <" << header << ">"; + return newline(); +} + CppFile &CppFile::pushNamespace(const QString &name) { namespaces_.push_back(name); diff --git a/Telegram/SourceFiles/codegen/common/cpp_file.h b/Telegram/SourceFiles/codegen/common/cpp_file.h index 0b199e44b..e2731b32a 100644 --- a/Telegram/SourceFiles/codegen/common/cpp_file.h +++ b/Telegram/SourceFiles/codegen/common/cpp_file.h @@ -36,6 +36,7 @@ public: return *this; } CppFile &include(const QString &header); + CppFile &includeFromLibrary(const QString &header); // Empty name adds anonymous namespace. CppFile &pushNamespace(const QString &name = QString()); diff --git a/Telegram/SourceFiles/codegen/emoji/generator.cpp b/Telegram/SourceFiles/codegen/emoji/generator.cpp index 1453c41e8..2ef7b6a25 100644 --- a/Telegram/SourceFiles/codegen/emoji/generator.cpp +++ b/Telegram/SourceFiles/codegen/emoji/generator.cpp @@ -396,6 +396,22 @@ void Init() {\n\ bool Generator::writeHeader() { auto header = std::make_unique(outputPath_ + ".h", project_); + header->includeFromLibrary("QtCore/QChar"); + header->includeFromLibrary("QtCore/QString"); + header->includeFromLibrary("QtCore/QVector"); + header->newline(); + header->includeFromLibrary("vector"); + header->newline(); + + header->pushNamespace("Ui").pushNamespace("Emoji"); + header->stream() << "class One;\n"; + header->popNamespace().popNamespace().newline(); + + header->stream() << "\ +using EmojiPtr = const Ui::Emoji::One*;\n\ +using EmojiPack = QVector;\n\ +\n"; + header->pushNamespace("Ui").pushNamespace("Emoji").pushNamespace("internal"); header->stream() << "\ \n\ @@ -406,20 +422,6 @@ EmojiPtr ByIndex(int index);\n\ \n\ EmojiPtr Find(const QChar *ch, const QChar *end, int *outLength = nullptr);\n\ \n\ -inline bool IsReplaceEdge(const QChar *ch) {\n\ - return true;\n\ -\n\ -// switch (ch->unicode()) {\n\ -// case '.': case ',': case ':': case ';': case '!': case '?': case '#': case '@':\n\ -// case '(': case ')': case '[': case ']': case '{': case '}': case '<': case '>':\n\ -// case '+': case '=': case '-': case '_': case '*': case '/': case '\\\\': case '^': case '$':\n\ -// case '\"': case '\\'':\n\ -// case 8212: case 171: case 187: // --, <<, >>\n\ -// return true;\n\ -// }\n\ -// return false;\n\ -}\n\ -\n\ const std::vector> GetReplacementPairs();\n\ EmojiPtr FindReplace(const QChar *ch, const QChar *end, int *outLength = nullptr);\n\ \n"; @@ -439,7 +441,7 @@ enum class Section {\n\ };\n\ \n\ int GetSectionCount(Section section);\n\ -EmojiPack GetSection(Section section);\n\ +QVector GetSection(Section section);\n\ \n"; return header->finalize(); } @@ -558,8 +560,9 @@ bool Generator::writeGetSections() { source_->stream() << "\ \n\ int GetSectionCount(Section section) {\n\ - switch (section) {\n\ - case Section::Recent: return GetRecent().size();\n"; + Expects(section != Section::Recent);\n\ +\n\ + switch (section) {\n"; auto countIndex = 0; for (auto name : sectionNames) { if (countIndex >= int(data_.categories.size())) { @@ -575,15 +578,9 @@ int GetSectionCount(Section section) {\n\ }\n\ \n\ EmojiPack GetSection(Section section) {\n\ - switch (section) {\n\ - case Section::Recent: {\n\ - auto result = EmojiPack();\n\ - result.reserve(GetRecent().size());\n\ - for (auto &item : GetRecent()) {\n\ - result.push_back(item.first);\n\ - }\n\ - return result;\n\ - } break;\n"; + Expects(section != Section::Recent);\n\ +\n\ + switch (section) {\n"; auto index = 0; auto offset = 0; for (auto name : sectionNames) { @@ -614,7 +611,7 @@ bool Generator::writeFindReplace() { const std::vector> ReplacementPairs = {\n"; for (const auto &[what, index] : data_.replaces) { source_->stream() << "\ - { qsl(\"" << what << "\"), " << index << " },\n"; + { \"" << what << "\", " << index << " },\n"; } source_->stream() << "\ };\n\ @@ -766,10 +763,6 @@ bool Generator::writeFindFromDictionary( source_->stream() << tabs(tabsUsed) << "if (outLength) *outLength = (ch - start);\n"; } - // While IsReplaceEdge() currently is always true we just return the value. - //source_->stream() << tabs(1 + chars.size()) << "if (ch + " << chars.size() << " == end || IsReplaceEdge(*(ch + " << chars.size() << ")) || (ch + " << chars.size() << ")->unicode() == ' ') {\n"; - //source_->stream() << tabs(1 + chars.size()) << "\treturn &Items[" << item.second << "];\n"; - //source_->stream() << tabs(1 + chars.size()) << "}\n"; source_->stream() << tabs(tabsUsed) << "return " << (item.second + 1) << ";\n"; } finishChecksTillKey(QString()); diff --git a/Telegram/SourceFiles/codegen/style/generator.cpp b/Telegram/SourceFiles/codegen/style/generator.cpp index 547b12abd..d18a64962 100644 --- a/Telegram/SourceFiles/codegen/style/generator.cpp +++ b/Telegram/SourceFiles/codegen/style/generator.cpp @@ -210,6 +210,9 @@ bool Generator::writeHeader() { header_->include("ui/style/style_core.h").newline(); + if (!writeHeaderRequiredIncludes()) { + return false; + } if (!writeHeaderStyleNamespace()) { return false; } @@ -233,12 +236,9 @@ bool inited = false;\n\ class Module_" << baseName_ << " : public style::internal::ModuleBase {\n\ public:\n\ Module_" << baseName_ << "() { style::internal::registerModule(this); }\n\ - ~Module_" << baseName_ << "() { style::internal::unregisterModule(this); }\n\ \n\ - void start() override {\n\ - style::internal::init_" << baseName_ << "();\n\ - }\n\ - void stop() override {\n\ + void start(int scale) override {\n\ + style::internal::init_" << baseName_ << "(scale);\n\ }\n\ };\n\ Module_" << baseName_ << " registrator;\n"; @@ -397,6 +397,50 @@ QString Generator::valueAssignmentCode(structure::Value value) const { return QString(); } +bool Generator::writeHeaderRequiredIncludes() { + std::function findInIncludes = [&](const Module &module, const structure::FullName &name) { + auto result = QString(); + module.enumIncludes([&](const Module &included) { + if (Module::findStructInModule(name, included)) { + result = moduleBaseName(included); + return false; + } + result = findInIncludes(included, name); + return true; + }); + return result; + }; + + auto includes = QStringList(); + const auto written = module_.enumStructs([&](const Struct &value) -> bool { + for (const auto &field : value.fields) { + if (field.type.tag == structure::TypeTag::Struct) { + const auto name = field.type.name; + if (!module_.findStructInModule(name, module_)) { + const auto base = findInIncludes(module_, name); + if (base.isEmpty()) { + return false; + } + if (!includes.contains(base)) { + includes.push_back(base); + } + } + } + } + return true; + }); + if (!written) { + return false; + } else if (includes.isEmpty()) { + return true; + } + for (const auto base : includes) { + header_->include(base + ".h"); + } + header_->newline(); + return true; +} + bool Generator::writeHeaderStyleNamespace() { if (!module_.hasStructs() && !module_.hasVariables()) { return true; @@ -405,7 +449,7 @@ bool Generator::writeHeaderStyleNamespace() { if (module_.hasVariables()) { header_->pushNamespace("internal").newline(); - header_->stream() << "void init_" << baseName_ << "();\n\n"; + header_->stream() << "void init_" << baseName_ << "(int scale);\n\n"; header_->popNamespace(); } bool wroteForwardDeclarations = writeStructsForwardDeclarations(); @@ -1076,7 +1120,7 @@ bool Generator::writeVariableInit() { } source_->stream() << "\ -void init_" << baseName_ << "() {\n\ +void init_" << baseName_ << "(int scale) {\n\ if (inited) return;\n\ inited = true;\n\n"; @@ -1084,7 +1128,7 @@ void init_" << baseName_ << "() {\n\ bool writtenAtLeastOne = false; bool result = module_.enumIncludes([&](const Module &module) -> bool { if (module.hasVariables()) { - source_->stream() << "\tinit_" + moduleBaseName(module) + "();\n"; + source_->stream() << "\tinit_" + moduleBaseName(module) + "(scale);\n"; writtenAtLeastOne = true; } return true; @@ -1099,7 +1143,7 @@ void init_" << baseName_ << "() {\n\ if (!pxValues_.isEmpty() || !fontFamilies_.isEmpty()) { if (!pxValues_.isEmpty()) { - source_->stream() << "\tinitPxValues();\n"; + source_->stream() << "\tinitPxValues(scale);\n"; } if (!fontFamilies_.isEmpty()) { source_->stream() << "\tinitFontFamilies();\n"; @@ -1134,8 +1178,7 @@ bool Generator::writePxValuesInit() { source_->stream() << "int " << pxValueName(i.key()) << " = " << i.key() << ";\n"; } source_->stream() << "\ -void initPxValues() {\n\ - const auto scale = cScale();\n"; +void initPxValues(int scale) {\n"; for (auto it = pxValues_.cbegin(), e = pxValues_.cend(); it != e; ++it) { auto value = it.key(); source_->stream() << "\t" << pxValueName(value) << " = ConvertScale(" << value << ", scale);\n"; diff --git a/Telegram/SourceFiles/codegen/style/generator.h b/Telegram/SourceFiles/codegen/style/generator.h index f5f214707..062c0cbc8 100644 --- a/Telegram/SourceFiles/codegen/style/generator.h +++ b/Telegram/SourceFiles/codegen/style/generator.h @@ -35,6 +35,7 @@ private: QString typeToDefaultValue(structure::Type type) const; QString valueAssignmentCode(structure::Value value) const; + bool writeHeaderRequiredIncludes(); bool writeHeaderStyleNamespace(); bool writeStructsForwardDeclarations(); bool writeStructsDefinitions(); diff --git a/Telegram/SourceFiles/codegen/style/module.cpp b/Telegram/SourceFiles/codegen/style/module.cpp index cef20c2cf..120a8a4f4 100644 --- a/Telegram/SourceFiles/codegen/style/module.cpp +++ b/Telegram/SourceFiles/codegen/style/module.cpp @@ -69,7 +69,7 @@ const Variable *Module::findVariable(const FullName &name, bool *outFromThisModu return nullptr; } -const Struct *Module::findStructInModule(const FullName &name, const Module &module) const { +const Struct *Module::findStructInModule(const FullName &name, const Module &module) { auto index = module.structsByName_.value(fullNameKey(name), -1); if (index < 0) { return nullptr; @@ -77,7 +77,7 @@ const Struct *Module::findStructInModule(const FullName &name, const Module &mod return &module.structs_.at(index); } -const Variable *Module::findVariableInModule(const FullName &name, const Module &module) const { +const Variable *Module::findVariableInModule(const FullName &name, const Module &module) { auto index = module.variablesByName_.value(fullNameKey(name), -1); if (index < 0) { return nullptr; diff --git a/Telegram/SourceFiles/codegen/style/module.h b/Telegram/SourceFiles/codegen/style/module.h index df7eadde1..b97916526 100644 --- a/Telegram/SourceFiles/codegen/style/module.h +++ b/Telegram/SourceFiles/codegen/style/module.h @@ -81,8 +81,8 @@ public: return !fullpath_.isEmpty(); } - const Struct *findStructInModule(const FullName &name, const Module &module) const; - const Variable *findVariableInModule(const FullName &name, const Module &module) const; + static const Struct *findStructInModule(const FullName &name, const Module &module); + static const Variable *findVariableInModule(const FullName &name, const Module &module); private: QString fullpath_; diff --git a/Telegram/SourceFiles/core/application.cpp b/Telegram/SourceFiles/core/application.cpp index ea3ea786a..5f7d8164b 100644 --- a/Telegram/SourceFiles/core/application.cpp +++ b/Telegram/SourceFiles/core/application.cpp @@ -157,13 +157,14 @@ Application::~Application() { } void Application::run() { - Fonts::Start(); + style::internal::StartFonts(); ThirdParty::start(); Global::start(); refreshGlobalProxy(); // Depends on Global::started(). startLocalStorage(); + ValidateScale(); if (Local::oldSettingsVersion() < AppVersion) { psNewVersion(); @@ -178,7 +179,7 @@ void Application::run() { _translator = std::make_unique(); QCoreApplication::instance()->installTranslator(_translator.get()); - style::startManager(); + style::startManager(cScale()); Ui::InitTextOptions(); Ui::Emoji::Init(); Media::Player::start(_audio.get()); diff --git a/Telegram/SourceFiles/core/crash_report_window.cpp b/Telegram/SourceFiles/core/crash_report_window.cpp index 3f7aeb862..68ba1d90a 100644 --- a/Telegram/SourceFiles/core/crash_report_window.cpp +++ b/Telegram/SourceFiles/core/crash_report_window.cpp @@ -31,7 +31,7 @@ constexpr auto kDefaultProxyPort = 80; PreLaunchWindow *PreLaunchWindowInstance = nullptr; PreLaunchWindow::PreLaunchWindow(QString title) { - Fonts::Start(); + style::internal::StartFonts(); setWindowIcon(Window::CreateIcon()); setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint); @@ -74,7 +74,7 @@ PreLaunchWindow::~PreLaunchWindow() { PreLaunchLabel::PreLaunchLabel(QWidget *parent) : QLabel(parent) { QFont labelFont(font()); - labelFont.setFamily(Fonts::GetOverride(qsl("Open Sans Semibold"))); + labelFont.setFamily(style::internal::GetFontOverride(qsl("Open Sans Semibold"))); labelFont.setPixelSize(static_cast(parent)->basicSize()); setFont(labelFont); @@ -92,7 +92,7 @@ void PreLaunchLabel::setText(const QString &text) { PreLaunchInput::PreLaunchInput(QWidget *parent, bool password) : QLineEdit(parent) { QFont logFont(font()); - logFont.setFamily(Fonts::GetOverride(qsl("Open Sans"))); + logFont.setFamily(style::internal::GetFontOverride(qsl("Open Sans"))); logFont.setPixelSize(static_cast(parent)->basicSize()); setFont(logFont); @@ -110,7 +110,7 @@ PreLaunchInput::PreLaunchInput(QWidget *parent, bool password) : QLineEdit(paren PreLaunchLog::PreLaunchLog(QWidget *parent) : QTextEdit(parent) { QFont logFont(font()); - logFont.setFamily(Fonts::GetOverride(qsl("Open Sans"))); + logFont.setFamily(style::internal::GetFontOverride(qsl("Open Sans"))); logFont.setPixelSize(static_cast(parent)->basicSize()); setFont(logFont); @@ -132,7 +132,7 @@ PreLaunchButton::PreLaunchButton(QWidget *parent, bool confirm) : QPushButton(pa setObjectName(confirm ? "confirm" : "cancel"); QFont closeFont(font()); - closeFont.setFamily(Fonts::GetOverride(qsl("Open Sans Semibold"))); + closeFont.setFamily(style::internal::GetFontOverride(qsl("Open Sans Semibold"))); closeFont.setPixelSize(static_cast(parent)->basicSize()); setFont(closeFont); @@ -151,7 +151,7 @@ PreLaunchCheckbox::PreLaunchCheckbox(QWidget *parent) : QCheckBox(parent) { setCheckState(Qt::Checked); QFont closeFont(font()); - closeFont.setFamily(Fonts::GetOverride(qsl("Open Sans Semibold"))); + closeFont.setFamily(style::internal::GetFontOverride(qsl("Open Sans Semibold"))); closeFont.setPixelSize(static_cast(parent)->basicSize()); setFont(closeFont); diff --git a/Telegram/SourceFiles/core/launcher.cpp b/Telegram/SourceFiles/core/launcher.cpp index 9237e629d..702401a7c 100644 --- a/Telegram/SourceFiles/core/launcher.cpp +++ b/Telegram/SourceFiles/core/launcher.cpp @@ -445,7 +445,7 @@ void Launcher::processArguments() { if (scaleKey.size() > 0) { const auto value = scaleKey[0].toInt(); gConfigScale = ((value < 75) || (value > 300)) - ? kInterfaceScaleAuto + ? style::kScaleAuto : value; } } diff --git a/Telegram/SourceFiles/core/sandbox.cpp b/Telegram/SourceFiles/core/sandbox.cpp index f6dbccd38..16e14254c 100644 --- a/Telegram/SourceFiles/core/sandbox.cpp +++ b/Telegram/SourceFiles/core/sandbox.cpp @@ -190,9 +190,8 @@ void Sandbox::setupScreenScale() { LOG(("Environmental variables: QT_AUTO_SCREEN_SCALE_FACTOR='%1'").arg(QString::fromLatin1(qgetenv("QT_AUTO_SCREEN_SCALE_FACTOR")))); LOG(("Environmental variables: QT_SCREEN_SCALE_FACTORS='%1'").arg(QString::fromLatin1(qgetenv("QT_SCREEN_SCALE_FACTORS")))); } - cSetRetinaFactor(ratio); - cSetIntRetinaFactor(int32(ratio)); - cSetScreenScale(kInterfaceScaleDefault); + style::SetDevicePixelRatio(int(ratio)); + cSetScreenScale(style::kScaleDefault); } } diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 96d5bfd69..e7ccf5201 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -1075,7 +1075,7 @@ void InnerWidget::checkReorderPinnedStart(QPoint localPosition) { if (!_pressed || _dragging || _state != WidgetState::Default) { return; } else if (qAbs(localPosition.y() - _dragStart.y()) - < ConvertScale(kStartReorderThreshold)) { + < style::ConvertScale(kStartReorderThreshold)) { return; } _dragging = _pressed; diff --git a/Telegram/SourceFiles/export/export_pch.cpp b/Telegram/SourceFiles/export/export_pch.cpp index 8fc999432..712f6a0b6 100644 --- a/Telegram/SourceFiles/export/export_pch.cpp +++ b/Telegram/SourceFiles/export/export_pch.cpp @@ -7,3 +7,4 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "export/export_pch.h" +// Precompiled header helper. diff --git a/Telegram/SourceFiles/history/view/media/history_view_document.cpp b/Telegram/SourceFiles/history/view/media/history_view_document.cpp index ec4a45cba..07f54119c 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_document.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_document.cpp @@ -124,8 +124,8 @@ QSize Document::countOptimalSize() { auto thumbed = Get(); if (thumbed) { _data->loadThumbnail(_realParent->fullId()); - auto tw = ConvertScale(_data->thumbnail()->width()); - auto th = ConvertScale(_data->thumbnail()->height()); + auto tw = style::ConvertScale(_data->thumbnail()->width()); + auto th = style::ConvertScale(_data->thumbnail()->height()); if (tw > th) { thumbed->_thumbw = (tw * st::msgFileThumbSize) / th; } else { diff --git a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp index 45002a2f2..2f9d0f9ef 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp @@ -76,7 +76,7 @@ QSize Gif::countOptimalSize() { const auto maxSize = _data->isVideoMessage() ? st::maxVideoMessageSize : st::maxGifSize; - const auto size = ConvertScale(videoSize()); + const auto size = style::ConvertScale(videoSize()); auto tw = size.width(); auto th = size.height(); if (tw > maxSize) { @@ -125,7 +125,7 @@ QSize Gif::countCurrentSize(int newWidth) { const auto maxSize = _data->isVideoMessage() ? st::maxVideoMessageSize : st::maxGifSize; - const auto size = ConvertScale(videoSize()); + const auto size = style::ConvertScale(videoSize()); auto tw = size.width(); auto th = size.height(); if (tw > maxSize) { diff --git a/Telegram/SourceFiles/history/view/media/history_view_photo.cpp b/Telegram/SourceFiles/history/view/media/history_view_photo.cpp index c88066fc5..97971606e 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_photo.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_photo.cpp @@ -70,8 +70,8 @@ QSize Photo::countOptimalSize() { auto maxWidth = 0; auto minHeight = 0; - auto tw = ConvertScale(_data->width()); - auto th = ConvertScale(_data->height()); + auto tw = style::ConvertScale(_data->width()); + auto th = style::ConvertScale(_data->height()); if (!tw || !th) { tw = th = 1; } @@ -102,7 +102,8 @@ QSize Photo::countOptimalSize() { } QSize Photo::countCurrentSize(int newWidth) { - int tw = ConvertScale(_data->width()), th = ConvertScale(_data->height()); + auto tw = style::ConvertScale(_data->width()); + auto th = style::ConvertScale(_data->height()); if (tw > st::maxMediaSize) { th = (st::maxMediaSize * th) / tw; tw = st::maxMediaSize; @@ -511,8 +512,8 @@ void Photo::validateGroupedCache( return; } - const auto originalWidth = ConvertScale(_data->width()); - const auto originalHeight = ConvertScale(_data->height()); + const auto originalWidth = style::ConvertScale(_data->width()); + const auto originalHeight = style::ConvertScale(_data->height()); const auto pixSize = Ui::GetImageScaleSizeForGeometry( { originalWidth, originalHeight }, { width, height }); diff --git a/Telegram/SourceFiles/history/view/media/history_view_theme_document.cpp b/Telegram/SourceFiles/history/view/media/history_view_theme_document.cpp index 6d5990e13..aed5508fe 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_theme_document.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_theme_document.cpp @@ -56,8 +56,8 @@ QSize ThemeDocument::countOptimalSize() { if (_data->isTheme()) { return st::historyThemeSize; } - auto tw = ConvertScale(_data->thumbnail()->width()); - auto th = ConvertScale(_data->thumbnail()->height()); + auto tw = style::ConvertScale(_data->thumbnail()->width()); + auto th = style::ConvertScale(_data->thumbnail()->height()); if (!tw || !th) { tw = th = 1; } @@ -78,8 +78,8 @@ QSize ThemeDocument::countCurrentSize(int newWidth) { _pixh = st::historyThemeSize.height(); return st::historyThemeSize; } - auto tw = ConvertScale(_data->thumbnail()->width()); - auto th = ConvertScale(_data->thumbnail()->height()); + auto tw = style::ConvertScale(_data->thumbnail()->width()); + auto th = style::ConvertScale(_data->thumbnail()->height()); if (!tw || !th) { tw = th = 1; } @@ -215,8 +215,8 @@ void ThemeDocument::prepareThumbnailFrom( ? Images::Option::TransparentBackground : Images::Option(0)); auto original = image->original(); - auto tw = isTheme ? _pixw : ConvertScale(_data->thumbnail()->width()); - auto th = isTheme ? _pixh : ConvertScale(_data->thumbnail()->height()); + auto tw = isTheme ? _pixw : style::ConvertScale(_data->thumbnail()->width()); + auto th = isTheme ? _pixh : style::ConvertScale(_data->thumbnail()->height()); if (!tw || !th) { tw = th = 1; } diff --git a/Telegram/SourceFiles/history/view/media/history_view_video.cpp b/Telegram/SourceFiles/history/view/media/history_view_video.cpp index 3036f82b5..c1119fc46 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_video.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_video.cpp @@ -57,7 +57,7 @@ QSize Video::sizeForAspectRatio() const { } QSize Video::countOptimalDimensions() const { - const auto desired = ConvertScale(_data->dimensions); + const auto desired = style::ConvertScale(_data->dimensions); const auto size = desired.isEmpty() ? sizeForAspectRatio() : desired; auto tw = size.width(); auto th = size.height(); @@ -554,8 +554,8 @@ void Video::validateGroupedCache( } const auto original = sizeForAspectRatio(); - const auto originalWidth = ConvertScale(original.width()); - const auto originalHeight = ConvertScale(original.height()); + const auto originalWidth = style::ConvertScale(original.width()); + const auto originalHeight = style::ConvertScale(original.height()); const auto pixSize = Ui::GetImageScaleSizeForGeometry( { originalWidth, originalHeight }, { width, height }); diff --git a/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp b/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp index 2fd09d339..06e19b7a0 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp @@ -446,8 +446,8 @@ void WebPage::draw(Painter &p, const QRect &r, TextSelection selection, crl::tim auto pw = qMax(_pixw, lineHeight); auto ph = _pixh; auto pixw = _pixw, pixh = articleThumbHeight(_data->photo, _pixw); - const auto maxw = ConvertScale(_data->photo->thumbnail()->width()); - const auto maxh = ConvertScale(_data->photo->thumbnail()->height()); + const auto maxw = style::ConvertScale(_data->photo->thumbnail()->width()); + const auto maxh = style::ConvertScale(_data->photo->thumbnail()->height()); if (pixw * ph != pixh * pw) { float64 coef = (pixw * ph > pixh * pw) ? qMin(ph / float64(pixh), maxh / float64(pixh)) : qMin(pw / float64(pixw), maxw / float64(pixw)); pixh = qRound(pixh * coef); diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp index d186b9751..cba573812 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp @@ -55,7 +55,7 @@ int FileBase::content_width() const { return document->dimensions.width(); } if (const auto thumb = document->thumbnail()) { - return ConvertScale(thumb->width()); + return style::ConvertScale(thumb->width()); } } return 0; @@ -67,7 +67,7 @@ int FileBase::content_height() const { return document->dimensions.height(); } if (const auto thumb = document->thumbnail()) { - return ConvertScale(thumb->height()); + return style::ConvertScale(thumb->height()); } } return 0; @@ -720,7 +720,8 @@ void Video::prepareThumbnail(QSize size) const { if (_thumb.size() != size * cIntRetinaFactor()) { const auto width = size.width(); const auto height = size.height(); - int32 w = qMax(ConvertScale(thumb->width()), 1), h = qMax(ConvertScale(thumb->height()), 1); + auto w = qMax(style::ConvertScale(thumb->width()), 1); + auto h = qMax(style::ConvertScale(thumb->height()), 1); if (w * height > h * width) { if (height < h) { w = w * height / h; @@ -1034,7 +1035,8 @@ void Contact::prepareThumbnail(int width, int height) const { const auto origin = fileOrigin(); if (thumb->loaded()) { if (_thumb.width() != width * cIntRetinaFactor() || _thumb.height() != height * cIntRetinaFactor()) { - int w = qMax(ConvertScale(thumb->width()), 1), h = qMax(ConvertScale(thumb->height()), 1); + auto w = qMax(style::ConvertScale(thumb->width()), 1); + auto h = qMax(style::ConvertScale(thumb->height()), 1); if (w * height > h * width) { if (height < h) { w = w * height / h; @@ -1183,7 +1185,8 @@ void Article::prepareThumbnail(int width, int height) const { const auto origin = fileOrigin(); if (thumb->loaded()) { if (_thumb.width() != width * cIntRetinaFactor() || _thumb.height() != height * cIntRetinaFactor()) { - int w = qMax(ConvertScale(thumb->width()), 1), h = qMax(ConvertScale(thumb->height()), 1); + auto w = qMax(style::ConvertScale(thumb->width()), 1); + auto h = qMax(style::ConvertScale(thumb->height()), 1); if (w * height > h * width) { if (height < h) { w = w * height / h; @@ -1371,8 +1374,8 @@ void Game::validateThumbnail(Image *image, QSize size, bool good) const { } const auto width = size.width(); const auto height = size.height(); - auto w = qMax(ConvertScale(image->width()), 1); - auto h = qMax(ConvertScale(image->height()), 1); + auto w = qMax(style::ConvertScale(image->width()), 1); + auto h = qMax(style::ConvertScale(image->height()), 1); auto resizeByHeight1 = (w * height > h * width) && (h >= height); auto resizeByHeight2 = (h * width >= w * height) && (w < width); if (resizeByHeight1 || resizeByHeight2) { diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp index f13ac5182..1c99a9065 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp +++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp @@ -1800,8 +1800,8 @@ void OverlayWidget::displayPhoto(not_null photo, HistoryItem *item) _blurred = true; _current = QPixmap(); _down = OverNone; - _w = ConvertScale(photo->width()); - _h = ConvertScale(photo->height()); + _w = style::ConvertScale(photo->width()); + _h = style::ConvertScale(photo->height()); contentSizeChanged(); refreshFromLabel(item); _photo->download(fileOrigin()); @@ -1937,10 +1937,10 @@ void OverlayWidget::displayDocument( updateThemePreviewGeometry(); } else if (!_current.isNull()) { _current.setDevicePixelRatio(cRetinaFactor()); - _w = ConvertScale(_current.width()); - _h = ConvertScale(_current.height()); + _w = style::ConvertScale(_current.width()); + _h = style::ConvertScale(_current.height()); } else if (videoShown()) { - const auto contentSize = ConvertScale(videoSize()); + const auto contentSize = style::ConvertScale(videoSize()); _w = contentSize.width(); _h = contentSize.height(); } @@ -2059,7 +2059,7 @@ void OverlayWidget::streamingReady(Streaming::Information &&info) { _streamed->info = std::move(info); validateStreamedGoodThumbnail(); if (videoShown()) { - const auto contentSize = ConvertScale(videoSize()); + const auto contentSize = style::ConvertScale(videoSize()); if (contentSize != QSize(_width, _height)) { update(contentRect()); _w = contentSize.width(); @@ -3088,7 +3088,7 @@ void OverlayWidget::setZoomLevel(int newZoom) { float64 nx, ny, z = (_zoom == ZoomToScreenLevel) ? _zoomToScreen : _zoom; const auto contentSize = videoShown() - ? ConvertScale(videoSize()) + ? style::ConvertScale(videoSize()) : QSize(_width, _height); _w = contentSize.width(); _h = contentSize.height(); diff --git a/Telegram/SourceFiles/mtproto/mtp_pch.cpp b/Telegram/SourceFiles/mtproto/mtp_pch.cpp index 7146195e1..3194b80c1 100644 --- a/Telegram/SourceFiles/mtproto/mtp_pch.cpp +++ b/Telegram/SourceFiles/mtproto/mtp_pch.cpp @@ -7,3 +7,4 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "mtproto/mtp_pch.h" +// Precompiled header helper. diff --git a/Telegram/SourceFiles/overview/overview_layout.cpp b/Telegram/SourceFiles/overview/overview_layout.cpp index 24b886764..89c202d64 100644 --- a/Telegram/SourceFiles/overview/overview_layout.cpp +++ b/Telegram/SourceFiles/overview/overview_layout.cpp @@ -892,7 +892,8 @@ Document::Document( if (withThumb()) { _data->loadThumbnail(parent->fullId()); - int32 tw = ConvertScale(_data->thumbnail()->width()), th = ConvertScale(_data->thumbnail()->height()); + auto tw = style::ConvertScale(_data->thumbnail()->width()); + auto th = style::ConvertScale(_data->thumbnail()->height()); if (tw > th) { _thumbw = (tw * _st.fileThumbSize) / th; } else { @@ -1407,13 +1408,13 @@ Link::Link( _page->photo->loadThumbnailSmall(parent->fullId()); } - tw = ConvertScale(_page->photo->width()); - th = ConvertScale(_page->photo->height()); + tw = style::ConvertScale(_page->photo->width()); + th = style::ConvertScale(_page->photo->height()); } else if (_page && _page->document && _page->document->hasThumbnail()) { _page->document->loadThumbnail(parent->fullId()); - tw = ConvertScale(_page->document->thumbnail()->width()); - th = ConvertScale(_page->document->thumbnail()->height()); + tw = style::ConvertScale(_page->document->thumbnail()->width()); + th = style::ConvertScale(_page->document->thumbnail()->height()); } if (tw > st::linksPhotoSize) { if (th > tw) { diff --git a/Telegram/SourceFiles/platform/mac/mac_touchbar.mm b/Telegram/SourceFiles/platform/mac/mac_touchbar.mm index 641b7a9d5..cdf6bc5b9 100644 --- a/Telegram/SourceFiles/platform/mac/mac_touchbar.mm +++ b/Telegram/SourceFiles/platform/mac/mac_touchbar.mm @@ -376,13 +376,15 @@ void AppendFavedStickers(std::vector &to) { void AppendEmojiPacks(std::vector &to) { for (auto i = 0; i != ChatHelpers::kEmojiSectionCount; ++i) { - const auto section = Ui::Emoji::GetSection( - static_cast(i)); - const auto title = i - ? Ui::Emoji::CategoryTitle(i)(tr::now) - : TitleRecentlyUsed(); + const auto section = static_cast(i); + const auto list = (section == Ui::Emoji::Section::Recent) + ? GetRecentEmojiSection() + : Ui::Emoji::GetSection(section); + const auto title = (section == Ui::Emoji::Section::Recent) + ? TitleRecentlyUsed() + : ChatHelpers::EmojiCategoryTitle(i)(tr::now); to.emplace_back(title); - for (const auto &emoji : section) { + for (const auto &emoji : list) { to.emplace_back(PickerScrubberItem(emoji)); } } diff --git a/Telegram/SourceFiles/settings.cpp b/Telegram/SourceFiles/settings.cpp index 38179caaf..1052fc7d1 100644 --- a/Telegram/SourceFiles/settings.cpp +++ b/Telegram/SourceFiles/settings.cpp @@ -7,8 +7,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "settings.h" -bool gRtl = false; -Qt::LayoutDirection gLangDir = gRtl ? Qt::RightToLeft : Qt::LeftToRight; +#include "ui/emoji_config.h" + +namespace { + +constexpr auto kRecentEmojiLimit = 42; + +auto UpdatesRecentEmoji = rpl::event_stream<>(); + +} // namespace + +Qt::LayoutDirection gLangDir = Qt::LeftToRight; bool gInstallBetaVersion = AppBetaVersion; uint64 gAlphaVersion = AppAlphaVersion; @@ -44,8 +53,8 @@ uint32 gConnectionsInSession = 1; QString gLoggedPhoneNumber; QByteArray gLocalSalt; -int gScreenScale = kInterfaceScaleAuto; -int gConfigScale = kInterfaceScaleAuto; +int gScreenScale = style::kScaleAuto; +int gConfigScale = style::kScaleAuto; QString gTimeFormat = qsl("hh:mm"); @@ -72,3 +81,128 @@ int gOtherOnline = 0; int32 gAutoDownloadPhoto = 0; // all auto download int32 gAutoDownloadAudio = 0; int32 gAutoDownloadGif = 0; + +RecentEmojiPack &GetRecentEmoji() { + if (cRecentEmoji().isEmpty()) { + RecentEmojiPack result; + auto haveAlready = [&result](EmojiPtr emoji) { + for (auto &row : result) { + if (row.first->id() == emoji->id()) { + return true; + } + } + return false; + }; + if (!cRecentEmojiPreload().isEmpty()) { + auto preload = cRecentEmojiPreload(); + cSetRecentEmojiPreload(RecentEmojiPreload()); + result.reserve(preload.size()); + for (auto i = preload.cbegin(), e = preload.cend(); i != e; ++i) { + if (auto emoji = Ui::Emoji::Find(i->first)) { + if (!haveAlready(emoji)) { + result.push_back(qMakePair(emoji, i->second)); + } + } + } + } + const auto defaultRecent = { + 0xD83DDE02LLU, + 0xD83DDE18LLU, + 0x2764LLU, + 0xD83DDE0DLLU, + 0xD83DDE0ALLU, + 0xD83DDE01LLU, + 0xD83DDC4DLLU, + 0x263ALLU, + 0xD83DDE14LLU, + 0xD83DDE04LLU, + 0xD83DDE2DLLU, + 0xD83DDC8BLLU, + 0xD83DDE12LLU, + 0xD83DDE33LLU, + 0xD83DDE1CLLU, + 0xD83DDE48LLU, + 0xD83DDE09LLU, + 0xD83DDE03LLU, + 0xD83DDE22LLU, + 0xD83DDE1DLLU, + 0xD83DDE31LLU, + 0xD83DDE21LLU, + 0xD83DDE0FLLU, + 0xD83DDE1ELLU, + 0xD83DDE05LLU, + 0xD83DDE1ALLU, + 0xD83DDE4ALLU, + 0xD83DDE0CLLU, + 0xD83DDE00LLU, + 0xD83DDE0BLLU, + 0xD83DDE06LLU, + 0xD83DDC4CLLU, + 0xD83DDE10LLU, + 0xD83DDE15LLU, + }; + for (const auto emoji : Ui::Emoji::GetDefaultRecent()) { + if (result.size() >= kRecentEmojiLimit) break; + + if (!haveAlready(emoji)) { + result.push_back(qMakePair(emoji, 1)); + } + } + cSetRecentEmoji(result); + } + return cRefRecentEmoji(); +} + +EmojiPack GetRecentEmojiSection() { + const auto &recent = GetRecentEmoji(); + + auto result = EmojiPack(); + result.reserve(recent.size()); + for (const auto &item : recent) { + result.push_back(item.first); + } + return result; +} + +void AddRecentEmoji(EmojiPtr emoji) { + auto &recent = GetRecentEmoji(); + auto i = recent.begin(), e = recent.end(); + for (; i != e; ++i) { + if (i->first == emoji) { + ++i->second; + if (i->second > 0x8000) { + for (auto j = recent.begin(); j != e; ++j) { + if (j->second > 1) { + j->second /= 2; + } else { + j->second = 1; + } + } + } + for (; i != recent.begin(); --i) { + if ((i - 1)->second > i->second) { + break; + } + std::swap(*i, *(i - 1)); + } + break; + } + } + if (i == e) { + while (recent.size() >= kRecentEmojiLimit) { + recent.pop_back(); + } + recent.push_back(qMakePair(emoji, 1)); + for (i = recent.end() - 1; i != recent.begin(); --i) { + if ((i - 1)->second > i->second) { + break; + } + std::swap(*i, *(i - 1)); + } + } + UpdatesRecentEmoji.fire({}); +} + +rpl::producer<> UpdatedRecentEmoji() { + return UpdatesRecentEmoji.events(); +} diff --git a/Telegram/SourceFiles/settings.h b/Telegram/SourceFiles/settings.h index 8ed4fc87f..b33e80119 100644 --- a/Telegram/SourceFiles/settings.h +++ b/Telegram/SourceFiles/settings.h @@ -7,6 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "ui/style/style_core.h" +#include "emoji.h" + #define DeclareReadSetting(Type, Name) extern Type g##Name; \ inline const Type &c##Name() { \ return g##Name; \ @@ -22,10 +25,9 @@ inline Type &cRef##Name() { \ return g##Name; \ } -DeclareSetting(bool, Rtl); DeclareSetting(Qt::LayoutDirection, LangDir); inline bool rtl() { - return cRtl(); + return style::RightToLeft(); } DeclareSetting(bool, InstallBetaVersion); @@ -94,19 +96,6 @@ DeclareSetting(int, ScreenScale); DeclareSetting(int, ConfigScale); DeclareSetting(QString, TimeFormat); -inline void cChangeTimeFormat(const QString &newFormat) { - if (!newFormat.isEmpty()) cSetTimeFormat(newFormat); -} - -namespace Ui { -namespace Emoji { -class One; -} // namespace Emoji -} // namespace Ui - -using EmojiPtr = const Ui::Emoji::One*; - -using EmojiPack = QVector; using RecentEmojiPreloadOldOld = QVector>; using RecentEmojiPreloadOld = QVector>; using RecentEmojiPreload = QVector>; @@ -138,6 +127,20 @@ DeclareSetting(bool, PasswordRecovered); DeclareSetting(int32, PasscodeBadTries); DeclareSetting(crl::time, PasscodeLastTry); +DeclareSetting(QStringList, SendPaths); +DeclareSetting(QString, StartUrl); + +DeclareSetting(int, OtherOnline); + +inline void cChangeTimeFormat(const QString &newFormat) { + if (!newFormat.isEmpty()) cSetTimeFormat(newFormat); +} + +RecentEmojiPack &GetRecentEmoji(); +QVector GetRecentEmojiSection(); +void AddRecentEmoji(EmojiPtr emoji); +[[nodiscard]] rpl::producer<> UpdatedRecentEmoji(); + inline bool passcodeCanTry() { if (cPasscodeBadTries() < 3) return true; auto dt = crl::now() - cPasscodeLastTry(); @@ -151,46 +154,27 @@ inline bool passcodeCanTry() { return dt >= 30000; } -DeclareSetting(QStringList, SendPaths); -DeclareSetting(QString, StartUrl); +inline float64 cRetinaFactor() { + return style::DevicePixelRatio(); +} -DeclareSetting(float64, RetinaFactor); -DeclareSetting(int32, IntRetinaFactor); - -DeclareSetting(int, OtherOnline); - -constexpr auto kInterfaceScaleAuto = 0; -constexpr auto kInterfaceScaleMin = 100; -constexpr auto kInterfaceScaleDefault = 100; -constexpr auto kInterfaceScaleMax = 300; +inline int32 cIntRetinaFactor() { + return style::DevicePixelRatio(); +} inline int cEvalScale(int scale) { - return (scale == kInterfaceScaleAuto) ? cScreenScale() : scale; + return (scale == style::kScaleAuto) ? cScreenScale() : scale; } inline int cScale() { - return cEvalScale(cConfigScale()); -} - -template -inline T ConvertScale(T value, int scale) { - return (value < 0.) - ? (-ConvertScale(-value, scale)) - : T(std::round((float64(value) * scale / 100.) - 0.01)); -} - -template -inline T ConvertScale(T value) { - return ConvertScale(value, cScale()); -} - -inline QSize ConvertScale(QSize size) { - return QSize(ConvertScale(size.width()), ConvertScale(size.height())); + return style::Scale(); } inline void SetScaleChecked(int scale) { - const auto checked = (scale == kInterfaceScaleAuto) - ? kInterfaceScaleAuto - : snap(scale, kInterfaceScaleMin, kInterfaceScaleMax / cIntRetinaFactor()); - cSetConfigScale(checked); + cSetConfigScale(style::CheckScale(scale)); +} + +inline void ValidateScale() { + SetScaleChecked(cConfigScale()); + style::SetScale(cEvalScale(cConfigScale())); } diff --git a/Telegram/SourceFiles/settings/settings_main.cpp b/Telegram/SourceFiles/settings/settings_main.cpp index daa1f033b..331a1ac16 100644 --- a/Telegram/SourceFiles/settings/settings_main.cpp +++ b/Telegram/SourceFiles/settings/settings_main.cpp @@ -124,7 +124,7 @@ void SetupInterfaceScale( const auto toggled = Ui::CreateChild>( container.get()); - const auto switched = (cConfigScale() == kInterfaceScaleAuto); + const auto switched = (cConfigScale() == style::kScaleAuto); const auto button = AddButton( container, tr::lng_settings_default_scale(), @@ -140,7 +140,7 @@ void SetupInterfaceScale( auto values = (cIntRetinaFactor() > 1) ? std::vector{ 100, 110, 120, 130, 140, 150 } : std::vector{ 100, 125, 150, 200, 250, 300 }; - if (cConfigScale() == kInterfaceScaleAuto) { + if (cConfigScale() == style::kScaleAuto) { return values; } if (ranges::find(values, cConfigScale()) == end(values)) { @@ -167,7 +167,7 @@ void SetupInterfaceScale( *inSetScale = true; const auto guard = gsl::finally([=] { *inSetScale = false; }); - toggled->fire(scale == kInterfaceScaleAuto); + toggled->fire(scale == style::kScaleAuto); slider->setActiveSection(sectionFromScale(scale)); if (cEvalScale(scale) != cEvalScale(cConfigScale())) { const auto confirmed = crl::guard(button, [=] { @@ -208,13 +208,13 @@ void SetupInterfaceScale( return scaleByIndex(section); }) | rpl::start_with_next([=](int scale) { (*setScale)((scale == cScreenScale()) - ? kInterfaceScaleAuto + ? style::kScaleAuto : scale); }, slider->lifetime()); button->toggledValue( ) | rpl::map([](bool checked) { - return checked ? kInterfaceScaleAuto : cEvalScale(cConfigScale()); + return checked ? style::kScaleAuto : cEvalScale(cConfigScale()); }) | rpl::start_with_next([=](int scale) { (*setScale)(scale); }, button->lifetime()); diff --git a/Telegram/SourceFiles/stdafx.h b/Telegram/SourceFiles/stdafx.h index 0498e0fdf..f687fa9a5 100644 --- a/Telegram/SourceFiles/stdafx.h +++ b/Telegram/SourceFiles/stdafx.h @@ -99,9 +99,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include -// Ensures/Expects. -#include - // Redefine Ensures/Expects by our own assertions. #include "base/assertion.h" diff --git a/Telegram/SourceFiles/storage/localstorage.cpp b/Telegram/SourceFiles/storage/localstorage.cpp index f4690977e..4ce04ab92 100644 --- a/Telegram/SourceFiles/storage/localstorage.cpp +++ b/Telegram/SourceFiles/storage/localstorage.cpp @@ -1476,7 +1476,7 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version, ReadSetting constexpr auto kOneAndHalf = 3; constexpr auto kTwo = 4; switch (v) { - case kAuto: return kInterfaceScaleAuto; + case kAuto: return style::kScaleAuto; case kOne: return 100; case kOneAndQuarter: return 125; case kOneAndHalf: return 150; @@ -1492,7 +1492,7 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version, ReadSetting if (!_checkStreamStatus(stream)) return false; // If cConfigScale() has value then it was set via command line. - if (cConfigScale() == kInterfaceScaleAuto) { + if (cConfigScale() == style::kScaleAuto) { SetScaleChecked(v); } } break; @@ -2045,8 +2045,8 @@ void _writeUserSettings() { auto recentEmojiPreloadData = cRecentEmojiPreload(); if (recentEmojiPreloadData.isEmpty()) { - recentEmojiPreloadData.reserve(Ui::Emoji::GetRecent().size()); - for (auto &item : Ui::Emoji::GetRecent()) { + recentEmojiPreloadData.reserve(GetRecentEmoji().size()); + for (auto &item : GetRecentEmoji()) { recentEmojiPreloadData.push_back(qMakePair(item.first->id(), item.second)); } } diff --git a/Telegram/SourceFiles/storage/storage_media_prepare.cpp b/Telegram/SourceFiles/storage/storage_media_prepare.cpp index dbefcaf23..45a81fdc8 100644 --- a/Telegram/SourceFiles/storage/storage_media_prepare.cpp +++ b/Telegram/SourceFiles/storage/storage_media_prepare.cpp @@ -90,7 +90,7 @@ bool PrepareAlbumMediaIsWaiting( if (ValidPhotoForAlbum(*image, file.mime)) { file.shownDimensions = PrepareShownDimensions(image->data); file.preview = Images::prepareOpaque(image->data.scaledToWidth( - std::min(previewWidth, ConvertScale(image->data.width())) + std::min(previewWidth, style::ConvertScale(image->data.width())) * cIntRetinaFactor(), Qt::SmoothTransformation)); Assert(!file.preview.isNull()); diff --git a/Telegram/SourceFiles/storage/storage_pch.cpp b/Telegram/SourceFiles/storage/storage_pch.cpp index 3bdcc4cfb..484defbf1 100644 --- a/Telegram/SourceFiles/storage/storage_pch.cpp +++ b/Telegram/SourceFiles/storage/storage_pch.cpp @@ -7,3 +7,4 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "storage/storage_pch.h" +// Precompiled header helper. diff --git a/Telegram/SourceFiles/ui/effects/animation_value.h b/Telegram/SourceFiles/ui/effects/animation_value.h index e9e6a06f8..78d74ea5c 100644 --- a/Telegram/SourceFiles/ui/effects/animation_value.h +++ b/Telegram/SourceFiles/ui/effects/animation_value.h @@ -164,7 +164,7 @@ TG_FORCE_INLINE Shifted non_premultiplied(QColor color) { } TG_FORCE_INLINE QColor color(QColor a, QColor b, float64 b_ratio) { - auto bOpacity = snap(interpolate(0, 255, b_ratio), 0, 255) + 1; + auto bOpacity = std::clamp(interpolate(0, 255, b_ratio), 0, 255) + 1; auto aOpacity = (256 - bOpacity); auto components = (non_premultiplied(a) * aOpacity + non_premultiplied(b) * bOpacity); return { diff --git a/Telegram/SourceFiles/ui/emoji_config.cpp b/Telegram/SourceFiles/ui/emoji_config.cpp index a7c1eaaa4..c365497c8 100644 --- a/Telegram/SourceFiles/ui/emoji_config.cpp +++ b/Telegram/SourceFiles/ui/emoji_config.cpp @@ -24,7 +24,6 @@ namespace Ui { namespace Emoji { namespace { -constexpr auto kSaveRecentEmojiTimeout = 3000; constexpr auto kUniversalSize = 72; constexpr auto kImagesPerRow = 32; constexpr auto kImageRowsPerSprite = 16; @@ -74,7 +73,6 @@ auto InstanceLarge = std::unique_ptr(); auto Universal = std::shared_ptr(); auto CanClearUniversal = false; auto Updates = rpl::event_stream<>(); -auto UpdatesRecent = rpl::event_stream<>(); #if defined Q_OS_MAC && !defined OS_MAC_OLD auto TouchbarSize = -1; @@ -345,47 +343,6 @@ std::vector LoadAndValidateSprites(int id) { return result; } -void AppendPartToResult(TextWithEntities &result, const QChar *start, const QChar *from, const QChar *to) { - if (to <= from) { - return; - } - for (auto &entity : result.entities) { - if (entity.offset() >= to - start) break; - if (entity.offset() + entity.length() < from - start) continue; - if (entity.offset() >= from - start) { - entity.extendToLeft(from - start - result.text.size()); - } - if (entity.offset() + entity.length() <= to - start) { - entity.shrinkFromRight(from - start - result.text.size()); - } - } - result.text.append(from, to - from); -} - -bool IsReplacementPart(ushort ch) { - return (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || (ch == '-') || (ch == '+') || (ch == '_'); -} - -EmojiPtr FindReplacement(const QChar *start, const QChar *end, int *outLength) { - if (start != end && *start == ':') { - auto maxLength = GetSuggestionMaxLength(); - for (auto till = start + 1; till != end; ++till) { - if (*till == ':') { - auto text = QString::fromRawData(start, till + 1 - start); - auto emoji = GetSuggestionEmoji(QStringToUTF16(text)); - auto result = Find(QStringFromUTF16(emoji)); - if (result) { - if (outLength) *outLength = (till + 1 - start); - } - return result; - } else if (!IsReplacementPart(till->unicode()) || (till - start) > maxLength) { - break; - } - } - } - return internal::FindReplace(start, end, outLength); -} - void ClearUniversalChecked() { Expects(InstanceNormal != nullptr && InstanceLarge != nullptr); @@ -513,8 +470,8 @@ void Init() { const auto persprite = kImagesPerRow * kImageRowsPerSprite; SpritesCount = (count / persprite) + ((count % persprite) ? 1 : 0); - SizeNormal = ConvertScale(18, cScale() * cIntRetinaFactor()); - SizeLarge = int(ConvertScale(18 * 4 / 3., cScale() * cIntRetinaFactor())); + SizeNormal = style::ConvertScale(18, cScale() * cIntRetinaFactor()); + SizeLarge = int(style::ConvertScale(18 * 4 / 3., cScale() * cIntRetinaFactor())); Universal = std::make_shared(ReadCurrentSetId()); CanClearUniversal = false; @@ -523,7 +480,7 @@ void Init() { #if defined Q_OS_MAC && !defined OS_MAC_OLD if (cScale() != kScaleForTouchBar) { - TouchbarSize = int(ConvertScale(18 * 4 / 3., + TouchbarSize = int(style::ConvertScale(18 * 4 / 3., kScaleForTouchBar * cIntRetinaFactor())); TouchbarInstance = std::make_unique(TouchbarSize); TouchbarEmoji = TouchbarInstance.get(); @@ -566,19 +523,6 @@ void ClearIrrelevantCache() { }); } -tr::phrase<> CategoryTitle(int index) { - switch (index) { - case 1: return tr::lng_emoji_category1; - case 2: return tr::lng_emoji_category2; - case 3: return tr::lng_emoji_category3; - case 4: return tr::lng_emoji_category4; - case 5: return tr::lng_emoji_category5; - case 6: return tr::lng_emoji_category6; - case 7: return tr::lng_emoji_category7; - } - Unexpected("Index in CategoryTitle."); -} - std::vector Sets() { return kSets | ranges::to_vector; } @@ -714,173 +658,50 @@ QString IdFromOldKey(uint64 oldKey) { return QString(); } -void ReplaceInText(TextWithEntities &result) { - auto newText = TextWithEntities(); - newText.entities = std::move(result.entities); - auto currentEntity = newText.entities.begin(); - auto entitiesEnd = newText.entities.end(); - auto emojiStart = result.text.constData(); - auto emojiEnd = emojiStart; - auto end = emojiStart + result.text.size(); - auto canFindEmoji = true; - for (auto ch = emojiEnd; ch != end;) { - auto emojiLength = 0; - auto emoji = canFindEmoji ? FindReplacement(ch, end, &emojiLength) : nullptr; - auto newEmojiEnd = ch + emojiLength; - - while (currentEntity != entitiesEnd && ch >= emojiStart + currentEntity->offset() + currentEntity->length()) { - ++currentEntity; - } - if (emoji && - (ch == emojiStart || !ch->isLetterOrNumber() || !(ch - 1)->isLetterOrNumber()) && - (newEmojiEnd == end || !newEmojiEnd->isLetterOrNumber() || newEmojiEnd == emojiStart || !(newEmojiEnd - 1)->isLetterOrNumber()) && - (currentEntity == entitiesEnd || (ch < emojiStart + currentEntity->offset() && newEmojiEnd <= emojiStart + currentEntity->offset()) || (ch >= emojiStart + currentEntity->offset() + currentEntity->length() && newEmojiEnd > emojiStart + currentEntity->offset() + currentEntity->length())) - ) { - if (newText.text.isEmpty()) newText.text.reserve(result.text.size()); - - AppendPartToResult(newText, emojiStart, emojiEnd, ch); - - if (emoji->hasVariants()) { - auto it = cEmojiVariants().constFind(emoji->nonColoredId()); - if (it != cEmojiVariants().cend()) { - emoji = emoji->variant(it.value()); - } - } - newText.text.append(emoji->text()); - - ch = emojiEnd = newEmojiEnd; - canFindEmoji = true; - } else { - if (internal::IsReplaceEdge(ch)) { - canFindEmoji = true; - } else { - canFindEmoji = false; - } - ++ch; +QVector GetDefaultRecent() { + const auto defaultRecent = { + 0xD83DDE02LLU, + 0xD83DDE18LLU, + 0x2764LLU, + 0xD83DDE0DLLU, + 0xD83DDE0ALLU, + 0xD83DDE01LLU, + 0xD83DDC4DLLU, + 0x263ALLU, + 0xD83DDE14LLU, + 0xD83DDE04LLU, + 0xD83DDE2DLLU, + 0xD83DDC8BLLU, + 0xD83DDE12LLU, + 0xD83DDE33LLU, + 0xD83DDE1CLLU, + 0xD83DDE48LLU, + 0xD83DDE09LLU, + 0xD83DDE03LLU, + 0xD83DDE22LLU, + 0xD83DDE1DLLU, + 0xD83DDE31LLU, + 0xD83DDE21LLU, + 0xD83DDE0FLLU, + 0xD83DDE1ELLU, + 0xD83DDE05LLU, + 0xD83DDE1ALLU, + 0xD83DDE4ALLU, + 0xD83DDE0CLLU, + 0xD83DDE00LLU, + 0xD83DDE0BLLU, + 0xD83DDE06LLU, + 0xD83DDC4CLLU, + 0xD83DDE10LLU, + 0xD83DDE15LLU, + }; + auto result = QVector(); + for (const auto oldKey : defaultRecent) { + if (const auto emoji = Ui::Emoji::FromOldKey(oldKey)) { + result.push_back(emoji); } } - if (newText.text.isEmpty()) { - result.entities = std::move(newText.entities); - } else { - AppendPartToResult(newText, emojiStart, emojiEnd, end); - result = std::move(newText); - } -} - -RecentEmojiPack &GetRecent() { - if (cRecentEmoji().isEmpty()) { - RecentEmojiPack result; - auto haveAlready = [&result](EmojiPtr emoji) { - for (auto &row : result) { - if (row.first->id() == emoji->id()) { - return true; - } - } - return false; - }; - if (!cRecentEmojiPreload().isEmpty()) { - auto preload = cRecentEmojiPreload(); - cSetRecentEmojiPreload(RecentEmojiPreload()); - result.reserve(preload.size()); - for (auto i = preload.cbegin(), e = preload.cend(); i != e; ++i) { - if (auto emoji = Ui::Emoji::Find(i->first)) { - if (!haveAlready(emoji)) { - result.push_back(qMakePair(emoji, i->second)); - } - } - } - } - auto defaultRecent = { - 0xD83DDE02LLU, - 0xD83DDE18LLU, - 0x2764LLU, - 0xD83DDE0DLLU, - 0xD83DDE0ALLU, - 0xD83DDE01LLU, - 0xD83DDC4DLLU, - 0x263ALLU, - 0xD83DDE14LLU, - 0xD83DDE04LLU, - 0xD83DDE2DLLU, - 0xD83DDC8BLLU, - 0xD83DDE12LLU, - 0xD83DDE33LLU, - 0xD83DDE1CLLU, - 0xD83DDE48LLU, - 0xD83DDE09LLU, - 0xD83DDE03LLU, - 0xD83DDE22LLU, - 0xD83DDE1DLLU, - 0xD83DDE31LLU, - 0xD83DDE21LLU, - 0xD83DDE0FLLU, - 0xD83DDE1ELLU, - 0xD83DDE05LLU, - 0xD83DDE1ALLU, - 0xD83DDE4ALLU, - 0xD83DDE0CLLU, - 0xD83DDE00LLU, - 0xD83DDE0BLLU, - 0xD83DDE06LLU, - 0xD83DDC4CLLU, - 0xD83DDE10LLU, - 0xD83DDE15LLU, - }; - for (auto oldKey : defaultRecent) { - if (result.size() >= kRecentLimit) break; - - if (auto emoji = Ui::Emoji::FromOldKey(oldKey)) { - if (!haveAlready(emoji)) { - result.push_back(qMakePair(emoji, 1)); - } - } - } - cSetRecentEmoji(result); - } - return cRefRecentEmoji(); -} - -void AddRecent(EmojiPtr emoji) { - auto &recent = GetRecent(); - auto i = recent.begin(), e = recent.end(); - for (; i != e; ++i) { - if (i->first == emoji) { - ++i->second; - if (i->second > 0x8000) { - for (auto j = recent.begin(); j != e; ++j) { - if (j->second > 1) { - j->second /= 2; - } else { - j->second = 1; - } - } - } - for (; i != recent.begin(); --i) { - if ((i - 1)->second > i->second) { - break; - } - qSwap(*i, *(i - 1)); - } - break; - } - } - if (i == e) { - while (recent.size() >= kRecentLimit) { - recent.pop_back(); - } - recent.push_back(qMakePair(emoji, 1)); - for (i = recent.end() - 1; i != recent.begin(); --i) { - if ((i - 1)->second > i->second) { - break; - } - qSwap(*i, *(i - 1)); - } - } - UpdatesRecent.fire({}); -} - -rpl::producer<> UpdatedRecent() { - return UpdatesRecent.events(); + return result; } const QPixmap &SinglePixmap(EmojiPtr emoji, int fontHeight) { diff --git a/Telegram/SourceFiles/ui/emoji_config.h b/Telegram/SourceFiles/ui/emoji_config.h index e4eeaf0d3..393cae0be 100644 --- a/Telegram/SourceFiles/ui/emoji_config.h +++ b/Telegram/SourceFiles/ui/emoji_config.h @@ -7,9 +7,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "base/basic_types.h" #include "base/binary_guard.h" #include "emoji.h" -#include "lang/lang_keys.h" + +#include +#include + +#include + +using EmojiPtr = const Ui::Emoji::One*; namespace Ui { namespace Emoji { @@ -20,8 +27,6 @@ namespace internal { } // namespace internal -constexpr auto kRecentLimit = 42; - void Init(); void Clear(); @@ -38,8 +43,6 @@ struct Set { // Thread safe, callback is called on main thread. void SwitchToSet(int id, Fn callback); -tr::phrase<> CategoryTitle(int index); - std::vector Sets(); int CurrentSetId(); bool SetIsReady(int id); @@ -108,7 +111,7 @@ public: } QString toUrl() const { - return qsl("emoji://e.") + QString::number(index()); + return "emoji://e." + QString::number(index()); } private: @@ -159,10 +162,7 @@ inline int ColorIndexFromOldKey(uint64 oldKey) { return ColorIndexFromCode(uint32(oldKey & 0xFFFFFFFFLLU)); } -void ReplaceInText(TextWithEntities &result); -RecentEmojiPack &GetRecent(); -void AddRecent(EmojiPtr emoji); -rpl::producer<> UpdatedRecent(); +QVector GetDefaultRecent(); const QPixmap &SinglePixmap(EmojiPtr emoji, int fontHeight); void Draw(QPainter &p, EmojiPtr emoji, int size, int x, int y); diff --git a/Telegram/SourceFiles/ui/painter.h b/Telegram/SourceFiles/ui/painter.h new file mode 100644 index 000000000..627c88ea1 --- /dev/null +++ b/Telegram/SourceFiles/ui/painter.h @@ -0,0 +1,118 @@ +/* +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 "styles/style_basic.h" + +#include +#include + +class Painter : public QPainter { +public: + explicit Painter(QPaintDevice *device) : QPainter(device) { + } + + void drawTextLeft(int x, int y, int outerw, const QString &text, int textWidth = -1) { + QFontMetrics m(fontMetrics()); + if (style::RightToLeft() && textWidth < 0) textWidth = m.width(text); + drawText(style::RightToLeft() ? (outerw - x - textWidth) : x, y + m.ascent(), text); + } + void drawTextRight(int x, int y, int outerw, const QString &text, int textWidth = -1) { + QFontMetrics m(fontMetrics()); + if (!style::RightToLeft() && textWidth < 0) textWidth = m.width(text); + drawText(style::RightToLeft() ? x : (outerw - x - textWidth), y + m.ascent(), text); + } + void drawPixmapLeft(int x, int y, int outerw, const QPixmap &pix, const QRect &from) { + drawPixmap(QPoint(style::RightToLeft() ? (outerw - x - (from.width() / pix.devicePixelRatio())) : x, y), pix, from); + } + void drawPixmapLeft(const QPoint &p, int outerw, const QPixmap &pix, const QRect &from) { + return drawPixmapLeft(p.x(), p.y(), outerw, pix, from); + } + void drawPixmapLeft(int x, int y, int w, int h, int outerw, const QPixmap &pix, const QRect &from) { + drawPixmap(QRect(style::RightToLeft() ? (outerw - x - w) : x, y, w, h), pix, from); + } + void drawPixmapLeft(const QRect &r, int outerw, const QPixmap &pix, const QRect &from) { + return drawPixmapLeft(r.x(), r.y(), r.width(), r.height(), outerw, pix, from); + } + void drawPixmapLeft(int x, int y, int outerw, const QPixmap &pix) { + drawPixmap(QPoint(style::RightToLeft() ? (outerw - x - (pix.width() / pix.devicePixelRatio())) : x, y), pix); + } + void drawPixmapLeft(const QPoint &p, int outerw, const QPixmap &pix) { + return drawPixmapLeft(p.x(), p.y(), outerw, pix); + } + void drawPixmapRight(int x, int y, int outerw, const QPixmap &pix, const QRect &from) { + drawPixmap(QPoint(style::RightToLeft() ? x : (outerw - x - (from.width() / pix.devicePixelRatio())), y), pix, from); + } + void drawPixmapRight(const QPoint &p, int outerw, const QPixmap &pix, const QRect &from) { + return drawPixmapRight(p.x(), p.y(), outerw, pix, from); + } + void drawPixmapRight(int x, int y, int w, int h, int outerw, const QPixmap &pix, const QRect &from) { + drawPixmap(QRect(style::RightToLeft() ? x : (outerw - x - w), y, w, h), pix, from); + } + void drawPixmapRight(const QRect &r, int outerw, const QPixmap &pix, const QRect &from) { + return drawPixmapRight(r.x(), r.y(), r.width(), r.height(), outerw, pix, from); + } + void drawPixmapRight(int x, int y, int outerw, const QPixmap &pix) { + drawPixmap(QPoint(style::RightToLeft() ? x : (outerw - x - (pix.width() / pix.devicePixelRatio())), y), pix); + } + void drawPixmapRight(const QPoint &p, int outerw, const QPixmap &pix) { + return drawPixmapRight(p.x(), p.y(), outerw, pix); + } + + void setTextPalette(const style::TextPalette &palette) { + _textPalette = &palette; + } + void restoreTextPalette() { + _textPalette = nullptr; + } + const style::TextPalette &textPalette() const { + return _textPalette ? *_textPalette : st::defaultTextPalette; + } + +private: + const style::TextPalette *_textPalette = nullptr; + +}; + +class PainterHighQualityEnabler { +public: + PainterHighQualityEnabler(QPainter &p) : _painter(p) { + static constexpr QPainter::RenderHint Hints[] = { + QPainter::Antialiasing, + QPainter::SmoothPixmapTransform, + QPainter::TextAntialiasing, + QPainter::HighQualityAntialiasing + }; + + const auto hints = _painter.renderHints(); + for (const auto hint : Hints) { + if (!(hints & hint)) { + _hints |= hint; + } + } + if (_hints) { + _painter.setRenderHints(_hints); + } + } + + PainterHighQualityEnabler( + const PainterHighQualityEnabler &other) = delete; + PainterHighQualityEnabler &operator=( + const PainterHighQualityEnabler &other) = delete; + + ~PainterHighQualityEnabler() { + if (_hints) { + _painter.setRenderHints(_hints, false); + } + } + +private: + QPainter &_painter; + QPainter::RenderHints _hints = 0; + +}; diff --git a/Telegram/SourceFiles/ui/style/style_core.cpp b/Telegram/SourceFiles/ui/style/style_core.cpp index f55ce2d7b..3ee7635ed 100644 --- a/Telegram/SourceFiles/ui/style/style_core.cpp +++ b/Telegram/SourceFiles/ui/style/style_core.cpp @@ -8,6 +8,11 @@ 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 namespace style { namespace internal { @@ -17,52 +22,42 @@ constexpr auto kMinContrastAlpha = 64; constexpr auto kMinContrastDistance = 64 * 64 * 4; constexpr auto kContrastDeltaL = 64; -using ModulesList = QList; -NeverFreedPointer styleModules; +int DevicePixelRatioValue = 1; +bool RightToLeftValue = false; -void startModules() { - if (!styleModules) return; - - for_const (auto module, *styleModules) { - module->start(); - } +std::vector &StyleModules() { + static auto result = std::vector(); + return result; } -void stopModules() { - if (!styleModules) return; - - for_const (auto module, *styleModules) { - module->stop(); +void startModules(int scale) { + for (const auto module : StyleModules()) { + module->start(scale); } } } // namespace void registerModule(ModuleBase *module) { - styleModules.createIfNull(); - styleModules->push_back(module); -} - -void unregisterModule(ModuleBase *module) { - styleModules->removeOne(module); - if (styleModules->isEmpty()) { - styleModules.clear(); - } + StyleModules().push_back(module); } } // namespace internal -void startManager() { - if (cIntRetinaFactor() * cConfigScale() > kInterfaceScaleMax) { - cSetConfigScale(kInterfaceScaleDefault); - } +bool RightToLeft() { + return internal::RightToLeftValue; +} - internal::registerFontFamily(qsl("Open Sans")); - internal::startModules(); +void SetRightToLeft(bool rtl) { + internal::RightToLeftValue = rtl; +} + +void startManager(int scale) { + internal::registerFontFamily("Open Sans"); + internal::startModules(scale); } void stopManager() { - internal::stopModules(); internal::destroyFonts(); internal::destroyIcons(); } @@ -113,15 +108,15 @@ void colorizeImage(const QImage &src, QColor c, QImage *outResult, QRect srcRect } QBrush transparentPlaceholderBrush() { - auto size = st::transparentPlaceholderSize * cIntRetinaFactor(); + auto size = st::transparentPlaceholderSize * DevicePixelRatio(); auto transparent = QImage(2 * size, 2 * size, QImage::Format_ARGB32_Premultiplied); transparent.fill(st::mediaviewTransparentBg->c); { - Painter p(&transparent); - p.fillRect(rtlrect(0, size, size, size, 2 * size), st::mediaviewTransparentFg); - p.fillRect(rtlrect(size, 0, size, size, 2 * size), st::mediaviewTransparentFg); + QPainter p(&transparent); + p.fillRect(0, size, size, size, st::mediaviewTransparentFg); + p.fillRect(size, 0, size, size, st::mediaviewTransparentFg); } - transparent.setDevicePixelRatio(cRetinaFactor()); + transparent.setDevicePixelRatio(DevicePixelRatio()); return QBrush(transparent); } @@ -129,14 +124,14 @@ QBrush transparentPlaceholderBrush() { namespace internal { QImage createCircleMask(int size, QColor bg, QColor fg) { - int realSize = size * cIntRetinaFactor(); + 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 { - Painter p(&result); + QPainter p(&result); PainterHighQualityEnabler hq(p); p.fillRect(0, 0, realSize, realSize, bg); @@ -144,7 +139,7 @@ QImage createCircleMask(int size, QColor bg, QColor fg) { p.setBrush(fg); p.drawEllipse(0, 0, realSize, realSize); } - result.setDevicePixelRatio(cRetinaFactor()); + result.setDevicePixelRatio(DevicePixelRatio()); return result; } diff --git a/Telegram/SourceFiles/ui/style/style_core.h b/Telegram/SourceFiles/ui/style/style_core.h index 436895d81..90b8ae686 100644 --- a/Telegram/SourceFiles/ui/style/style_core.h +++ b/Telegram/SourceFiles/ui/style/style_core.h @@ -7,26 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "ui/style/style_core_scale.h" #include "ui/style/style_core_types.h" -inline QPoint rtlpoint(int x, int y, int outerw) { - return QPoint(rtl() ? (outerw - x) : x, y); -} -inline QPoint rtlpoint(const QPoint &p, int outerw) { - return rtl() ? QPoint(outerw - p.x(), p.y()) : p; -} -inline QPointF rtlpoint(const QPointF &p, int outerw) { - return rtl() ? QPointF(outerw - p.x(), p.y()) : p; -} -inline QRect rtlrect(int x, int y, int w, int h, int outerw) { - return QRect(rtl() ? (outerw - x - w) : x, y, w, h); -} -inline QRect rtlrect(const QRect &r, int outerw) { - return rtl() ? QRect(outerw - r.x() - r.width(), r.y(), r.width(), r.height()) : r; -} -inline QRectF rtlrect(const QRectF &r, int outerw) { - return rtl() ? QRectF(outerw - r.x() - r.width(), r.y(), r.width(), r.height()) : r; -} inline QRect centerrect(const QRect &inRect, const QRect &rect) { return QRect(inRect.x() + (inRect.width() - rect.width()) / 2, inRect.y() + (inRect.height() - rect.height()) / 2, rect.width(), rect.height()); } @@ -41,15 +24,13 @@ namespace internal { // They call [un]registerModule() in [de|con]structor. class ModuleBase { public: - virtual void start() = 0; - virtual void stop() = 0; + virtual void start(int scale) = 0; virtual ~ModuleBase() = default; }; void registerModule(ModuleBase *module); -void unregisterModule(ModuleBase *module); // This method is implemented in palette.cpp (codegen). bool setPaletteColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a); @@ -59,7 +40,10 @@ void EnsureContrast(ColorData &over, const ColorData &under); } // namespace internal -void startManager(); +[[nodiscard]] bool RightToLeft(); +void SetRightToLeft(bool rtl); + +void startManager(int scale); void stopManager(); // *outResult must be r.width() x r.height(), ARGB32_Premultiplied. diff --git a/Telegram/SourceFiles/ui/style/style_core_color.cpp b/Telegram/SourceFiles/ui/style/style_core_color.cpp index f562d07dd..658f743a2 100644 --- a/Telegram/SourceFiles/ui/style/style_core_color.cpp +++ b/Telegram/SourceFiles/ui/style/style_core_color.cpp @@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "ui/style/style_core_color.h" +#include "styles/palette.h" + namespace style { namespace internal { diff --git a/Telegram/SourceFiles/ui/style/style_core_color.h b/Telegram/SourceFiles/ui/style/style_core_color.h index f245815c5..7dbcfdecf 100644 --- a/Telegram/SourceFiles/ui/style/style_core_color.h +++ b/Telegram/SourceFiles/ui/style/style_core_color.h @@ -7,6 +7,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include +#include +#include + namespace style { class palette; diff --git a/Telegram/SourceFiles/ui/style/style_core_font.cpp b/Telegram/SourceFiles/ui/style/style_core_font.cpp index 11655abc6..84c50c38c 100644 --- a/Telegram/SourceFiles/ui/style/style_core_font.cpp +++ b/Telegram/SourceFiles/ui/style/style_core_font.cpp @@ -7,25 +7,128 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "ui/style/style_core_font.h" +#include "base/algorithm.h" +#include "logs.h" + +#include +#include +#include +#include + namespace style { namespace internal { namespace { -typedef QMap FontFamilyMap; -FontFamilyMap fontFamilyMap; - -typedef QVector FontFamilies; -FontFamilies fontFamilies; - -typedef QMap FontDatas; -FontDatas fontsMap; +QMap fontFamilyMap; +QVector fontFamilies; +QMap 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)) { + LOG(("Font Error: could not resolve '%1' font, got '%2'.").arg(familyName).arg(realFamily)); + return false; + } + + auto metrics = QFontMetrics(checkFont); + if (!metrics.height()) { + 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) { + 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()) { + 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; + } // namespace +void Start() { + 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"; + LOG(("Fonts Info: Using Segoe UI instead of Open Sans.")); + } + } + if (!semibold) { + if (ValidateFont("Segoe UI Semibold")) { + OpenSansSemiboldOverride = "Segoe UI Semibold"; + 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 +} + +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; @@ -44,7 +147,7 @@ int registerFontFamily(const QString &family) { } FontData::FontData(int size, uint32 flags, int family, Font *other) -: f(Fonts::GetOverride(fontFamilies[family])) +: f(GetFontOverride(fontFamilies[family])) , m(f) , _size(size) , _flags(flags) @@ -72,7 +175,7 @@ FontData::FontData(int size, uint32 flags, int family, Font *other) ascent = m.ascent(); descent = m.descent(); spacew = width(QLatin1Char(' ')); - elidew = width(qsl("...")); + elidew = width("..."); } Font FontData::bold(bool set) const { diff --git a/Telegram/SourceFiles/ui/style/style_core_font.h b/Telegram/SourceFiles/ui/style/style_core_font.h index 566a4fe63..a9cd5b1df 100644 --- a/Telegram/SourceFiles/ui/style/style_core_font.h +++ b/Telegram/SourceFiles/ui/style/style_core_font.h @@ -7,9 +7,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "base/basic_types.h" + +#include +#include + namespace style { namespace internal { +void StartFonts(); +[[nodiscard]] QString GetFontOverride(const QString &familyName); + void destroyFonts(); int registerFontFamily(const QString &family); diff --git a/Telegram/SourceFiles/ui/style/style_core_icon.cpp b/Telegram/SourceFiles/ui/style/style_core_icon.cpp index e124f711f..f80dfb487 100644 --- a/Telegram/SourceFiles/ui/style/style_core_icon.cpp +++ b/Telegram/SourceFiles/ui/style/style_core_icon.cpp @@ -7,7 +7,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "ui/style/style_core_icon.h" -#include "app.h" +#include "ui/style/style_core.h" +#include "base/basic_types.h" + +#include namespace style { namespace internal { @@ -17,22 +20,19 @@ uint32 colorKey(QColor c) { return (((((uint32(c.red()) << 8) | uint32(c.green())) << 8) | uint32(c.blue())) << 8) | uint32(c.alpha()); } -using IconMasks = QMap; -using IconPixmaps = QMap, QPixmap>; -using IconDatas = OrderedSet; -NeverFreedPointer iconMasks; -NeverFreedPointer iconPixmaps; -NeverFreedPointer iconData; +QMap iconMasks; +QMap, QPixmap> iconPixmaps; +OrderedSet iconData; QImage createIconMask(const IconMask *mask, int scale) { auto maskImage = QImage::fromData(mask->data(), mask->size(), "PNG"); - maskImage.setDevicePixelRatio(cRetinaFactor()); + maskImage.setDevicePixelRatio(DevicePixelRatio()); Assert(!maskImage.isNull()); // images are layouted like this: // 100x 200x // 300x - const auto factor = cIntRetinaFactor(); + const auto factor = DevicePixelRatio(); const auto realscale = scale * factor; const auto width = maskImage.width() / 3; const auto height = maskImage.height() / 5; @@ -120,7 +120,7 @@ QPoint MonoIcon::offset() const { void MonoIcon::paint(QPainter &p, const QPoint &pos, int outerw) const { int w = width(), h = height(); QPoint fullOffset = pos + offset(); - int partPosX = rtl() ? (outerw - fullOffset.x() - w) : fullOffset.x(); + int partPosX = RightToLeft() ? (outerw - fullOffset.x() - w) : fullOffset.x(); int partPosY = fullOffset.y(); ensureLoaded(); @@ -143,7 +143,7 @@ void MonoIcon::fill(QPainter &p, const QRect &rect) const { void MonoIcon::paint(QPainter &p, const QPoint &pos, int outerw, QColor colorOverride) const { int w = width(), h = height(); QPoint fullOffset = pos + offset(); - int partPosX = rtl() ? (outerw - fullOffset.x() - w) : fullOffset.x(); + int partPosX = RightToLeft() ? (outerw - fullOffset.x() - w) : fullOffset.x(); int partPosY = fullOffset.y(); ensureLoaded(); @@ -170,17 +170,17 @@ void MonoIcon::paint( const QPoint &pos, int outerw, const style::palette &paletteOverride) const { - auto size = readGeneratedSize(_mask, cScale()); + auto size = readGeneratedSize(_mask, Scale()); auto maskImage = QImage(); if (size.isEmpty()) { - maskImage = createIconMask(_mask, cScale()); - size = maskImage.size() / cIntRetinaFactor(); + maskImage = createIconMask(_mask, Scale()); + size = maskImage.size() / DevicePixelRatio(); } const auto w = size.width(); const auto h = size.height(); const auto fullOffset = pos + offset(); - const auto partPosX = rtl() ? (outerw - fullOffset.x() - w) : fullOffset.x(); + const auto partPosX = RightToLeft() ? (outerw - fullOffset.x() - w) : fullOffset.x(); const auto partPosY = fullOffset.y(); if (!maskImage.isNull()) { @@ -198,11 +198,11 @@ void MonoIcon::fill( QPainter &p, const QRect &rect, const style::palette &paletteOverride) const { - auto size = readGeneratedSize(_mask, cScale()); + auto size = readGeneratedSize(_mask, Scale()); auto maskImage = QImage(); if (size.isEmpty()) { - maskImage = createIconMask(_mask, cScale()); - size = maskImage.size() / cIntRetinaFactor(); + maskImage = createIconMask(_mask, Scale()); + size = maskImage.size() / DevicePixelRatio(); } if (!maskImage.isNull()) { auto colorizedImage = QImage( @@ -216,10 +216,10 @@ void MonoIcon::fill( } QImage MonoIcon::instance(QColor colorOverride, int scale) const { - if (scale == kInterfaceScaleAuto) { + if (scale == kScaleAuto) { ensureLoaded(); - auto result = QImage(size() * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied); - result.setDevicePixelRatio(cRetinaFactor()); + auto result = QImage(size() * DevicePixelRatio(), QImage::Format_ARGB32_Premultiplied); + result.setDevicePixelRatio(DevicePixelRatio()); if (_pixmap.isNull()) { result.fill(colorOverride); } else { @@ -229,14 +229,14 @@ QImage MonoIcon::instance(QColor colorOverride, int scale) const { } auto size = readGeneratedSize(_mask, scale); if (!size.isEmpty()) { - auto result = QImage(size * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied); - result.setDevicePixelRatio(cRetinaFactor()); + auto result = QImage(size * DevicePixelRatio(), QImage::Format_ARGB32_Premultiplied); + result.setDevicePixelRatio(DevicePixelRatio()); result.fill(colorOverride); return result; } auto mask = createIconMask(_mask, scale); auto result = QImage(mask.size(), QImage::Format_ARGB32_Premultiplied); - result.setDevicePixelRatio(cRetinaFactor()); + result.setDevicePixelRatio(DevicePixelRatio()); colorizeImage(mask, colorOverride, &result); return result; } @@ -250,12 +250,11 @@ void MonoIcon::ensureLoaded() const { return; } - _size = readGeneratedSize(_mask, cScale()); + _size = readGeneratedSize(_mask, Scale()); if (_size.isEmpty()) { - iconMasks.createIfNull(); - auto i = iconMasks->constFind(_mask); - if (i == iconMasks->cend()) { - i = iconMasks->insert(_mask, createIconMask(_mask, cScale())); + auto i = iconMasks.constFind(_mask); + if (i == iconMasks.cend()) { + i = iconMasks.insert(_mask, createIconMask(_mask, Scale())); } _maskImage = i.value(); @@ -269,27 +268,25 @@ void MonoIcon::ensureColorizedImage(QColor color) const { } void MonoIcon::createCachedPixmap() const { - iconPixmaps.createIfNull(); auto key = qMakePair(_mask, colorKey(_color->c)); - auto j = iconPixmaps->constFind(key); - if (j == iconPixmaps->cend()) { + auto j = iconPixmaps.constFind(key); + if (j == iconPixmaps.cend()) { auto image = colorizeImage(_maskImage, _color); - j = iconPixmaps->insert(key, App::pixmapFromImageInPlace(std::move(image))); + j = iconPixmaps.insert(key, QPixmap::fromImage(std::move(image))); } _pixmap = j.value(); - _size = _pixmap.size() / cIntRetinaFactor(); + _size = _pixmap.size() / DevicePixelRatio(); } void IconData::created() { - iconData.createIfNull(); - iconData->insert(this); + iconData.insert(this); } void IconData::fill(QPainter &p, const QRect &rect) const { if (_parts.empty()) return; auto partSize = _parts[0].size(); - for_const (auto &part, _parts) { + for (const auto &part : _parts) { Assert(part.offset() == QPoint(0, 0)); Assert(part.size() == partSize); part.fill(p, rect); @@ -300,7 +297,7 @@ void IconData::fill(QPainter &p, const QRect &rect, QColor colorOverride) const if (_parts.empty()) return; auto partSize = _parts[0].size(); - for_const (auto &part, _parts) { + for (const auto &part : _parts) { Assert(part.offset() == QPoint(0, 0)); Assert(part.size() == partSize); part.fill(p, rect, colorOverride); @@ -317,7 +314,7 @@ QImage IconData::instance(QColor colorOverride, int scale) const { int IconData::width() const { if (_width < 0) { _width = 0; - for_const (auto &part, _parts) { + for (const auto &part : _parts) { accumulate_max(_width, part.offset().x() + part.width()); } } @@ -327,7 +324,7 @@ int IconData::width() const { int IconData::height() const { if (_height < 0) { _height = 0; - for_const (auto &part, _parts) { + for (const auto &part : _parts) { accumulate_max(_height, part.offset().x() + part.height()); } } @@ -336,10 +333,8 @@ int IconData::height() const { void resetIcons() { iconPixmaps.clear(); - if (iconData) { - for (auto data : *iconData) { - data->reset(); - } + for (const auto data : iconData) { + data->reset(); } } diff --git a/Telegram/SourceFiles/ui/style/style_core_icon.h b/Telegram/SourceFiles/ui/style/style_core_icon.h index 43b0dce50..f19cdd813 100644 --- a/Telegram/SourceFiles/ui/style/style_core_icon.h +++ b/Telegram/SourceFiles/ui/style/style_core_icon.h @@ -8,6 +8,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "ui/style/style_core_color.h" +#include "ui/style/style_core_scale.h" +#include "base/algorithm.h" +#include "base/assertion.h" + #include namespace style { @@ -87,7 +91,7 @@ public: } void reset() { - for_const (auto &part, _parts) { + for (const auto &part : _parts) { part.reset(); } } @@ -96,21 +100,21 @@ public: } void paint(QPainter &p, const QPoint &pos, int outerw) const { - for_const (auto &part, _parts) { + for (const auto &part : _parts) { part.paint(p, pos, outerw); } } void fill(QPainter &p, const QRect &rect) const; void paint(QPainter &p, const QPoint &pos, int outerw, QColor colorOverride) const { - for_const (auto &part, _parts) { + for (const auto &part : _parts) { part.paint(p, pos, outerw, colorOverride); } } void fill(QPainter &p, const QRect &rect, QColor colorOverride) const; void paint(QPainter &p, const QPoint &pos, int outerw, const style::palette &paletteOverride) const { - for_const (auto &part, _parts) { + for (const auto &part : _parts) { part.paint(p, pos, outerw, paletteOverride); } } @@ -153,13 +157,15 @@ public: Icon(Icon &&other) : _data(base::take(other._data)), _owner(base::take(_owner)) { } Icon &operator=(const Icon &other) { - Assert(!_owner); + Expects(!_owner); + _data = other._data; _owner = false; return *this; } Icon &operator=(Icon &&other) { - Assert(!_owner); + Expects(!_owner); + _data = base::take(other._data); _owner = base::take(other._owner); return *this; @@ -205,7 +211,7 @@ public: return _data->fill(p, rect, colorOverride); } - QImage instance(QColor colorOverride, int scale = kInterfaceScaleAuto) const { + QImage instance(QColor colorOverride, int scale = kScaleAuto) const { return _data->instance(colorOverride, scale); } diff --git a/Telegram/SourceFiles/ui/style/style_core_scale.cpp b/Telegram/SourceFiles/ui/style/style_core_scale.cpp new file mode 100644 index 000000000..9e9f42142 --- /dev/null +++ b/Telegram/SourceFiles/ui/style/style_core_scale.cpp @@ -0,0 +1,38 @@ +/* +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_scale.h" + +#include "base/assertion.h" + +namespace style { +namespace { + +int DevicePixelRatioValue = 1; +int ScaleValue = kScaleDefault; + +} // namespace + +int DevicePixelRatio() { + return DevicePixelRatioValue; +} + +void SetDevicePixelRatio(int ratio) { + DevicePixelRatioValue = ratio; +} + +int Scale() { + return ScaleValue; +} + +void SetScale(int scale) { + Expects(scale != 0); + + ScaleValue = scale; +} + +} // namespace style diff --git a/Telegram/SourceFiles/ui/style/style_core_scale.h b/Telegram/SourceFiles/ui/style/style_core_scale.h new file mode 100644 index 000000000..ca7120a5c --- /dev/null +++ b/Telegram/SourceFiles/ui/style/style_core_scale.h @@ -0,0 +1,50 @@ +/* +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 + +#include +#include + +namespace style { + +inline constexpr auto kScaleAuto = 0; +inline constexpr auto kScaleMin = 100; +inline constexpr auto kScaleDefault = 100; +inline constexpr auto kScaleMax = 300; + +[[nodiscard]] int DevicePixelRatio(); +void SetDevicePixelRatio(int ratio); + +[[nodiscard]] int Scale(); +void SetScale(int scale); + +[[nodiscard]] inline int CheckScale(int scale) { + return (scale == kScaleAuto) + ? kScaleAuto + : std::clamp(scale, kScaleMin, kScaleMax / DevicePixelRatio()); +} + +template +[[nodiscard]] inline T ConvertScale(T value, int scale) { + return (value < 0.) + ? (-ConvertScale(-value, scale)) + : T(std::round((double(value) * scale / 100.) - 0.01)); +} + +template +[[nodiscard]] inline T ConvertScale(T value) { + return ConvertScale(value, Scale()); +} + +[[nodiscard]] inline QSize ConvertScale(QSize size) { + return QSize(ConvertScale(size.width()), ConvertScale(size.height())); +} + +} // namespace style diff --git a/Telegram/SourceFiles/ui/text/text.h b/Telegram/SourceFiles/ui/text/text.h index 537c0b60d..0df838338 100644 --- a/Telegram/SourceFiles/ui/text/text.h +++ b/Telegram/SourceFiles/ui/text/text.h @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "ui/text/text_entity.h" +#include "ui/painter.h" #include "core/click_handler.h" #include "base/flags.h" diff --git a/Telegram/SourceFiles/ui/text/text_entity.h b/Telegram/SourceFiles/ui/text/text_entity.h index 56ebcb9c0..921111edf 100644 --- a/Telegram/SourceFiles/ui/text/text_entity.h +++ b/Telegram/SourceFiles/ui/text/text_entity.h @@ -7,6 +7,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "base/basic_types.h" + +#include + enum class EntityType { Invalid = 0, diff --git a/Telegram/SourceFiles/ui/twidget.cpp b/Telegram/SourceFiles/ui/twidget.cpp index 37b2872a0..2884845b9 100644 --- a/Telegram/SourceFiles/ui/twidget.cpp +++ b/Telegram/SourceFiles/ui/twidget.cpp @@ -13,114 +13,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include -#include - -namespace Fonts { -namespace { - -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)) { - LOG(("Font Error: could not resolve '%1' font, got '%2'.").arg(familyName).arg(realFamily)); - return false; - } - - auto metrics = QFontMetrics(checkFont); - if (!metrics.height()) { - 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) { - 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()) { - 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; - -} // namespace - -void Start() { - if (Started) { - return; - } - Started = true; - - auto regular = LoadCustomFont(qsl(":/gui/fonts/OpenSans-Regular.ttf"), qsl("Open Sans")); - auto bold = LoadCustomFont(qsl(":/gui/fonts/OpenSans-Bold.ttf"), qsl("Open Sans"), style::internal::FontBold); - auto semibold = LoadCustomFont(qsl(":/gui/fonts/OpenSans-Semibold.ttf"), qsl("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(qsl("Segoe UI")) && ValidateFont(qsl("Segoe UI"), style::internal::FontBold)) { - OpenSansOverride = qsl("Segoe UI"); - LOG(("Fonts Info: Using Segoe UI instead of Open Sans.")); - } - } - if (!semibold) { - if (ValidateFont(qsl("Segoe UI Semibold"))) { - OpenSansSemiboldOverride = qsl("Segoe UI Semibold"); - 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(qsl("Open Sans"), qsl("Segoe UI")); - //QFont::insertSubstitution(qsl("Open Sans Semibold"), qsl("Segoe UI Semibold")); -#elif defined Q_OS_MAC // Q_OS_WIN - auto list = QStringList(); - list.append(qsl(".SF NS Text")); - list.append(qsl("Helvetica Neue")); - list.append(qsl("Lucida Grande")); - QFont::insertSubstitutions(qsl("Open Sans"), list); - QFont::insertSubstitutions(qsl("Open Sans Semibold"), list); -#endif // Q_OS_WIN || Q_OS_MAC -} - -QString GetOverride(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; -} - -} // Fonts namespace Ui { namespace { diff --git a/Telegram/SourceFiles/ui/twidget.h b/Telegram/SourceFiles/ui/twidget.h index 6202dc7cc..fbf11c4d6 100644 --- a/Telegram/SourceFiles/ui/twidget.h +++ b/Telegram/SourceFiles/ui/twidget.h @@ -9,18 +9,30 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/flags.h" -namespace Fonts { - -void Start(); -QString GetOverride(const QString &familyName); - -} // namespace - class TWidget; template class object_ptr; +inline QPoint rtlpoint(int x, int y, int outerw) { + return QPoint(rtl() ? (outerw - x) : x, y); +} +inline QPoint rtlpoint(const QPoint &p, int outerw) { + return rtl() ? QPoint(outerw - p.x(), p.y()) : p; +} +inline QPointF rtlpoint(const QPointF &p, int outerw) { + return rtl() ? QPointF(outerw - p.x(), p.y()) : p; +} +inline QRect rtlrect(int x, int y, int w, int h, int outerw) { + return QRect(rtl() ? (outerw - x - w) : x, y, w, h); +} +inline QRect rtlrect(const QRect &r, int outerw) { + return rtl() ? QRect(outerw - r.x() - r.width(), r.y(), r.width(), r.height()) : r; +} +inline QRectF rtlrect(const QRectF &r, int outerw) { + return rtl() ? QRectF(outerw - r.x() - r.width(), r.y(), r.width(), r.height()) : r; +} + namespace Ui { inline bool InFocusChain(not_null widget) { @@ -133,111 +145,6 @@ inline bool IsRightCorner(RectPart corner) { return (corner == RectPart::TopRight) || (corner == RectPart::BottomRight); } -class Painter : public QPainter { -public: - explicit Painter(QPaintDevice *device) : QPainter(device) { - } - - void drawTextLeft(int x, int y, int outerw, const QString &text, int textWidth = -1) { - QFontMetrics m(fontMetrics()); - if (rtl() && textWidth < 0) textWidth = m.width(text); - drawText(rtl() ? (outerw - x - textWidth) : x, y + m.ascent(), text); - } - void drawTextRight(int x, int y, int outerw, const QString &text, int textWidth = -1) { - QFontMetrics m(fontMetrics()); - if (!rtl() && textWidth < 0) textWidth = m.width(text); - drawText(rtl() ? x : (outerw - x - textWidth), y + m.ascent(), text); - } - void drawPixmapLeft(int x, int y, int outerw, const QPixmap &pix, const QRect &from) { - drawPixmap(QPoint(rtl() ? (outerw - x - (from.width() / pix.devicePixelRatio())) : x, y), pix, from); - } - void drawPixmapLeft(const QPoint &p, int outerw, const QPixmap &pix, const QRect &from) { - return drawPixmapLeft(p.x(), p.y(), outerw, pix, from); - } - void drawPixmapLeft(int x, int y, int w, int h, int outerw, const QPixmap &pix, const QRect &from) { - drawPixmap(QRect(rtl() ? (outerw - x - w) : x, y, w, h), pix, from); - } - void drawPixmapLeft(const QRect &r, int outerw, const QPixmap &pix, const QRect &from) { - return drawPixmapLeft(r.x(), r.y(), r.width(), r.height(), outerw, pix, from); - } - void drawPixmapLeft(int x, int y, int outerw, const QPixmap &pix) { - drawPixmap(QPoint(rtl() ? (outerw - x - (pix.width() / pix.devicePixelRatio())) : x, y), pix); - } - void drawPixmapLeft(const QPoint &p, int outerw, const QPixmap &pix) { - return drawPixmapLeft(p.x(), p.y(), outerw, pix); - } - void drawPixmapRight(int x, int y, int outerw, const QPixmap &pix, const QRect &from) { - drawPixmap(QPoint(rtl() ? x : (outerw - x - (from.width() / pix.devicePixelRatio())), y), pix, from); - } - void drawPixmapRight(const QPoint &p, int outerw, const QPixmap &pix, const QRect &from) { - return drawPixmapRight(p.x(), p.y(), outerw, pix, from); - } - void drawPixmapRight(int x, int y, int w, int h, int outerw, const QPixmap &pix, const QRect &from) { - drawPixmap(QRect(rtl() ? x : (outerw - x - w), y, w, h), pix, from); - } - void drawPixmapRight(const QRect &r, int outerw, const QPixmap &pix, const QRect &from) { - return drawPixmapRight(r.x(), r.y(), r.width(), r.height(), outerw, pix, from); - } - void drawPixmapRight(int x, int y, int outerw, const QPixmap &pix) { - drawPixmap(QPoint(rtl() ? x : (outerw - x - (pix.width() / pix.devicePixelRatio())), y), pix); - } - void drawPixmapRight(const QPoint &p, int outerw, const QPixmap &pix) { - return drawPixmapRight(p.x(), p.y(), outerw, pix); - } - - void setTextPalette(const style::TextPalette &palette) { - _textPalette = &palette; - } - void restoreTextPalette() { - _textPalette = nullptr; - } - const style::TextPalette &textPalette() const { - return _textPalette ? *_textPalette : st::defaultTextPalette; - } - -private: - const style::TextPalette *_textPalette = nullptr; - -}; - -class PainterHighQualityEnabler { -public: - PainterHighQualityEnabler(QPainter &p) : _painter(p) { - static constexpr QPainter::RenderHint Hints[] = { - QPainter::Antialiasing, - QPainter::SmoothPixmapTransform, - QPainter::TextAntialiasing, - QPainter::HighQualityAntialiasing - }; - - const auto hints = _painter.renderHints(); - for (const auto hint : Hints) { - if (!(hints & hint)) { - _hints |= hint; - } - } - if (_hints) { - _painter.setRenderHints(_hints); - } - } - - PainterHighQualityEnabler( - const PainterHighQualityEnabler &other) = delete; - PainterHighQualityEnabler &operator=( - const PainterHighQualityEnabler &other) = delete; - - ~PainterHighQualityEnabler() { - if (_hints) { - _painter.setRenderHints(_hints, false); - } - } - -private: - QPainter &_painter; - QPainter::RenderHints _hints = 0; - -}; - template class TWidgetHelper : public Base { public: diff --git a/Telegram/SourceFiles/ui/ui_pch.cpp b/Telegram/SourceFiles/ui/ui_pch.cpp new file mode 100644 index 000000000..7d110ee23 --- /dev/null +++ b/Telegram/SourceFiles/ui/ui_pch.cpp @@ -0,0 +1,10 @@ +/* +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/ui_pch.h" + +// Precompiled header helper. diff --git a/Telegram/SourceFiles/ui/ui_pch.h b/Telegram/SourceFiles/ui/ui_pch.h new file mode 100644 index 000000000..6e9250541 --- /dev/null +++ b/Telegram/SourceFiles/ui/ui_pch.h @@ -0,0 +1,21 @@ +/* +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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include diff --git a/Telegram/SourceFiles/ui/widgets/input_fields.cpp b/Telegram/SourceFiles/ui/widgets/input_fields.cpp index 1bbf31577..9522abad1 100644 --- a/Telegram/SourceFiles/ui/widgets/input_fields.cpp +++ b/Telegram/SourceFiles/ui/widgets/input_fields.cpp @@ -10,7 +10,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/popup_menu.h" #include "ui/countryinput.h" #include "ui/emoji_config.h" -#include "emoji_suggestions_data.h" #include "chat_helpers/emoji_suggestions_helper.h" #include "chat_helpers/message_field.h" // ConvertTextTagsToEntities #include "platform/platform_info.h" @@ -3072,7 +3071,7 @@ void InputField::commitInstantReplacement( ? emoji->variant(it.value()) : emoji; }(); - Ui::Emoji::AddRecent(use); + AddRecentEmoji(use); return PrepareEmojiFormat(use, _st.font); }(); const auto replacement = format.isImageFormat() diff --git a/Telegram/SourceFiles/window/themes/window_theme.cpp b/Telegram/SourceFiles/window/themes/window_theme.cpp index 19a753e8e..46846aac1 100644 --- a/Telegram/SourceFiles/window/themes/window_theme.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme.cpp @@ -634,7 +634,7 @@ void ChatBackground::set(const Data::WallPaper &paper, QImage image) { const auto scale = cScale() * cIntRetinaFactor(); if (scale != 100) { image = image.scaledToWidth( - ConvertScale(image.width(), scale), + style::ConvertScale(image.width(), scale), Qt::SmoothTransformation); } } else if (Data::IsDefaultWallPaper(_paper) diff --git a/Telegram/SourceFiles/window/themes/window_theme_preview.cpp b/Telegram/SourceFiles/window/themes/window_theme_preview.cpp index 5d105824a..6ed1c91d2 100644 --- a/Telegram/SourceFiles/window/themes/window_theme_preview.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme_preview.cpp @@ -293,8 +293,8 @@ void Generator::addDateBubble(QString date) { void Generator::addPhotoBubble(QString image, QString caption, QString date, Status status) { Bubble bubble; bubble.photo.load(image); - bubble.photoWidth = ConvertScale(bubble.photo.width() / 2); - bubble.photoHeight = ConvertScale(bubble.photo.height() / 2); + bubble.photoWidth = style::ConvertScale(bubble.photo.width() / 2); + bubble.photoHeight = style::ConvertScale(bubble.photo.height() / 2); auto skipBlock = computeSkipBlock(status, date); bubble.text.setRichText(st::messageTextStyle, caption + textcmdSkipBlock(skipBlock.width(), skipBlock.height()), Ui::ItemTextDefaultOptions()); diff --git a/Telegram/SourceFiles/window/window_main_menu.cpp b/Telegram/SourceFiles/window/window_main_menu.cpp index 2d534b0ba..03cf569b3 100644 --- a/Telegram/SourceFiles/window/window_main_menu.cpp +++ b/Telegram/SourceFiles/window/window_main_menu.cpp @@ -493,7 +493,7 @@ void MainMenu::initResetScaleButton() { } else { _resetScaleButton.create(this); _resetScaleButton->addClickHandler([] { - cSetConfigScale(kInterfaceScaleDefault); + cSetConfigScale(style::kScaleDefault); Local::writeSettings(); App::restart(); }); diff --git a/Telegram/SourceFiles/window/window_media_preview.cpp b/Telegram/SourceFiles/window/window_media_preview.cpp index fc7f60898..9270d61e0 100644 --- a/Telegram/SourceFiles/window/window_media_preview.cpp +++ b/Telegram/SourceFiles/window/window_media_preview.cpp @@ -203,7 +203,7 @@ QSize MediaPreviewWidget::currentDimensions() const { box = QSize(2 * st::maxStickerSize, 2 * st::maxStickerSize); } } - result = QSize(qMax(ConvertScale(result.width()), 1), qMax(ConvertScale(result.height()), 1)); + result = QSize(qMax(style::ConvertScale(result.width()), 1), qMax(style::ConvertScale(result.height()), 1)); if (result.width() > box.width()) { result.setHeight(qMax((box.width() * result.height()) / result.width(), 1)); result.setWidth(box.width()); diff --git a/Telegram/gyp/Telegram.gyp b/Telegram/gyp/Telegram.gyp index ec2ed28b7..0656dc677 100644 --- a/Telegram/gyp/Telegram.gyp +++ b/Telegram/gyp/Telegram.gyp @@ -22,8 +22,6 @@ 'sp_media_key_tap_loc': '<(submodules_loc)/SPMediaKeyTap', 'emoji_suggestions_loc': '<(submodules_loc)/emoji_suggestions', 'style_files': [ - '<(res_loc)/colors.palette', - '<(res_loc)/basic.style', '<(src_loc)/boxes/boxes.style', '<(src_loc)/calls/calls.style', '<(src_loc)/dialogs/dialogs.style', @@ -38,9 +36,14 @@ '<(src_loc)/profile/profile.style', '<(src_loc)/settings/settings.style', '<(src_loc)/chat_helpers/chat_helpers.style', - '<(src_loc)/ui/widgets/widgets.style', '<(src_loc)/window/window.style', ], + 'dependent_style_files': [ + '<(res_loc)/colors.palette', + '<(res_loc)/basic.style', + '<(src_loc)/ui/widgets/widgets.style', + ], + 'style_timestamp': '<(SHARED_INTERMEDIATE_DIR)/update_dependent_styles.timestamp', 'langpacks': [ 'en', 'de', @@ -84,6 +87,7 @@ 'lib_lottie.gyp:lib_lottie', 'lib_ffmpeg.gyp:lib_ffmpeg', 'lib_mtproto.gyp:lib_mtproto', + 'lib_ui.gyp:lib_ui', ], 'defines': [ diff --git a/Telegram/gyp/codegen_rules.gypi b/Telegram/gyp/codegen_rules.gypi index a901db3bb..d1c92900b 100644 --- a/Telegram/gyp/codegen_rules.gypi +++ b/Telegram/gyp/codegen_rules.gypi @@ -5,23 +5,10 @@ # https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL { + 'includes': [ + 'codegen_styles_rule.gypi', + ], 'actions': [{ - 'action_name': 'update_dependent_styles', - 'inputs': [ - '<(DEPTH)/update_dependent.py', - '<@(style_files)', - ], - 'outputs': [ - '<(SHARED_INTERMEDIATE_DIR)/update_dependent_styles.timestamp', - ], - 'action': [ - 'python', '<(DEPTH)/update_dependent.py', '--styles', - '-I', '<(res_loc)', '-I', '<(src_loc)', - '-o', '<(SHARED_INTERMEDIATE_DIR)/update_dependent_styles.timestamp', - '<@(style_files)', - ], - 'message': 'Updating dependent style files..', - }, { 'action_name': 'update_dependent_qrc', 'inputs': [ '<(DEPTH)/update_dependent.py', @@ -37,33 +24,6 @@ '<@(qrc_files)', ], 'message': 'Updating dependent qrc files..', - }, { - 'action_name': 'codegen_palette', - 'inputs': [ - '<(PRODUCT_DIR)/codegen_style<(exe_ext)', - '<(SHARED_INTERMEDIATE_DIR)/update_dependent_styles.timestamp', - '<(res_loc)/colors.palette', - ], - 'outputs': [ - '<(SHARED_INTERMEDIATE_DIR)/styles/palette.h', - '<(SHARED_INTERMEDIATE_DIR)/styles/palette.cpp', - ], - 'action': [ - '<(PRODUCT_DIR)/codegen_style<(exe_ext)', - '-I', '<(res_loc)', '-I', '<(src_loc)', - '-o', '<(SHARED_INTERMEDIATE_DIR)/styles', - '-w', '<(PRODUCT_DIR)/..', - - # GYP/Ninja bug workaround: if we specify just <(RULE_INPUT_PATH) - # the <(RULE_INPUT_ROOT) variables won't be available in Ninja, - # and the 'message' will be just 'codegen_style-ing .style..' - # Looks like the using the <(RULE_INPUT_ROOT) here "exports" it - # for using in the 'message' field. - - '<(res_loc)/colors.palette', - ], - 'message': 'codegen_palette-ing colors..', - 'process_outputs_as_sources': 1, }, { 'action_name': 'codegen_lang', 'inputs': [ @@ -98,52 +58,5 @@ ], 'message': 'codegen_numbers-ing numbers.txt..', 'process_outputs_as_sources': 1, - }, { - 'action_name': 'codegen_emoji', - 'inputs': [ - '<(PRODUCT_DIR)/codegen_emoji<(exe_ext)', - '<(res_loc)/emoji_autocomplete.json', - ], - 'outputs': [ - '<(SHARED_INTERMEDIATE_DIR)/emoji.cpp', - '<(SHARED_INTERMEDIATE_DIR)/emoji.h', - '<(SHARED_INTERMEDIATE_DIR)/emoji_suggestions_data.cpp', - '<(SHARED_INTERMEDIATE_DIR)/emoji_suggestions_data.h', - ], - 'action': [ - '<(PRODUCT_DIR)/codegen_emoji<(exe_ext)', - '<(res_loc)/emoji_autocomplete.json', - '-o', '<(SHARED_INTERMEDIATE_DIR)', - ], - 'message': 'codegen_emoji-ing..', - 'process_outputs_as_sources': 1, - }], - 'rules': [{ - 'rule_name': 'codegen_style', - 'extension': 'style', - 'inputs': [ - '<(PRODUCT_DIR)/codegen_style<(exe_ext)', - '<(SHARED_INTERMEDIATE_DIR)/update_dependent_styles.timestamp', - ], - 'outputs': [ - '<(SHARED_INTERMEDIATE_DIR)/styles/style_<(RULE_INPUT_ROOT).h', - '<(SHARED_INTERMEDIATE_DIR)/styles/style_<(RULE_INPUT_ROOT).cpp', - ], - 'action': [ - '<(PRODUCT_DIR)/codegen_style<(exe_ext)', - '-I', '<(res_loc)', '-I', '<(src_loc)', - '-o', '<(SHARED_INTERMEDIATE_DIR)/styles', - '-w', '<(PRODUCT_DIR)/..', - - # GYP/Ninja bug workaround: if we specify just <(RULE_INPUT_PATH) - # the <(RULE_INPUT_ROOT) variables won't be available in Ninja, - # and the 'message' will be just 'codegen_style-ing .style..' - # Looks like the using the <(RULE_INPUT_ROOT) here "exports" it - # for using in the 'message' field. - - '<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT)<(RULE_INPUT_EXT)', - ], - 'message': 'codegen_style-ing <(RULE_INPUT_ROOT).style..', - 'process_outputs_as_sources': 1, }], } diff --git a/Telegram/gyp/codegen_rules_ui.gypi b/Telegram/gyp/codegen_rules_ui.gypi new file mode 100644 index 000000000..63cd679cd --- /dev/null +++ b/Telegram/gyp/codegen_rules_ui.gypi @@ -0,0 +1,58 @@ +# 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 + +{ + 'includes': [ + 'codegen_styles_rule.gypi', + ], + 'actions': [{ + 'action_name': 'codegen_palette', + 'inputs': [ + '<(PRODUCT_DIR)/codegen_style<(exe_ext)', + '<(style_timestamp)', + '<(res_loc)/colors.palette', + ], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/styles/palette.h', + '<(SHARED_INTERMEDIATE_DIR)/styles/palette.cpp', + ], + 'action': [ + '<(PRODUCT_DIR)/codegen_style<(exe_ext)', + '-I', '<(res_loc)', '-I', '<(src_loc)', + '-o', '<(SHARED_INTERMEDIATE_DIR)/styles', + '-w', '<(PRODUCT_DIR)/..', + + # GYP/Ninja bug workaround: if we specify just <(RULE_INPUT_PATH) + # the <(RULE_INPUT_ROOT) variables won't be available in Ninja, + # and the 'message' will be just 'codegen_style-ing .style..' + # Looks like the using the <(RULE_INPUT_ROOT) here "exports" it + # for using in the 'message' field. + + '<(res_loc)/colors.palette', + ], + 'message': 'codegen_palette-ing colors..', + 'process_outputs_as_sources': 1, + }, { + 'action_name': 'codegen_emoji', + 'inputs': [ + '<(PRODUCT_DIR)/codegen_emoji<(exe_ext)', + '<(res_loc)/emoji_autocomplete.json', + ], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/emoji.cpp', + '<(SHARED_INTERMEDIATE_DIR)/emoji.h', + '<(SHARED_INTERMEDIATE_DIR)/emoji_suggestions_data.cpp', + '<(SHARED_INTERMEDIATE_DIR)/emoji_suggestions_data.h', + ], + 'action': [ + '<(PRODUCT_DIR)/codegen_emoji<(exe_ext)', + '<(res_loc)/emoji_autocomplete.json', + '-o', '<(SHARED_INTERMEDIATE_DIR)', + ], + 'message': 'codegen_emoji-ing..', + 'process_outputs_as_sources': 1, + }], +} diff --git a/Telegram/gyp/codegen_styles_rule.gypi b/Telegram/gyp/codegen_styles_rule.gypi new file mode 100644 index 000000000..5c47e9260 --- /dev/null +++ b/Telegram/gyp/codegen_styles_rule.gypi @@ -0,0 +1,54 @@ +# 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 + +{ + 'actions': [{ + 'action_name': 'update_dependent_styles', + 'inputs': [ + '<(DEPTH)/update_dependent.py', + '<@(style_files)', + '<@(dependent_style_files)', + ], + 'outputs': [ + '<(style_timestamp)', + ], + 'action': [ + 'python', '<(DEPTH)/update_dependent.py', '--styles', + '-I', '<(res_loc)', '-I', '<(src_loc)', + '-o', '<(style_timestamp)', + '<@(style_files)', + ], + 'message': 'Updating dependent style files..', + }], + 'rules': [{ + 'rule_name': 'codegen_style', + 'extension': 'style', + 'inputs': [ + '<(PRODUCT_DIR)/codegen_style<(exe_ext)', + '<(style_timestamp)', + ], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/styles/style_<(RULE_INPUT_ROOT).h', + '<(SHARED_INTERMEDIATE_DIR)/styles/style_<(RULE_INPUT_ROOT).cpp', + ], + 'action': [ + '<(PRODUCT_DIR)/codegen_style<(exe_ext)', + '-I', '<(res_loc)', '-I', '<(src_loc)', + '-o', '<(SHARED_INTERMEDIATE_DIR)/styles', + '-w', '<(PRODUCT_DIR)/..', + + # GYP/Ninja bug workaround: if we specify just <(RULE_INPUT_PATH) + # the <(RULE_INPUT_ROOT) variables won't be available in Ninja, + # and the 'message' will be just 'codegen_style-ing .style..' + # Looks like the using the <(RULE_INPUT_ROOT) here "exports" it + # for using in the 'message' field. + + '<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT)<(RULE_INPUT_EXT)', + ], + 'message': 'codegen_style-ing <(RULE_INPUT_ROOT).style..', + 'process_outputs_as_sources': 1, + }], +} diff --git a/Telegram/gyp/lib_scheme.gyp b/Telegram/gyp/lib_scheme.gyp index 0c12f240b..dcbab63e9 100644 --- a/Telegram/gyp/lib_scheme.gyp +++ b/Telegram/gyp/lib_scheme.gyp @@ -51,8 +51,8 @@ 'action': [ 'python', '<(src_loc)/codegen/scheme/codegen_scheme.py', '-o', '<(SHARED_INTERMEDIATE_DIR)', - '<(res_loc)/tl/mtproto.tl', - '<(res_loc)/tl/api.tl', + '<(res_loc)/tl/mtproto.tl', + '<(res_loc)/tl/api.tl', ], 'message': 'codegen_scheme-ing *.tl..', 'process_outputs_as_sources': 1, diff --git a/Telegram/gyp/lib_ui.gyp b/Telegram/gyp/lib_ui.gyp new file mode 100644 index 000000000..ef95ddb2d --- /dev/null +++ b/Telegram/gyp/lib_ui.gyp @@ -0,0 +1,78 @@ +# 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 + +{ + 'includes': [ + 'common.gypi', + ], + 'targets': [{ + 'target_name': 'lib_ui', + 'type': 'static_library', + 'hard_dependency': 1, + 'includes': [ + 'common.gypi', + 'qt.gypi', + 'qt_moc.gypi', + 'codegen_rules_ui.gypi', + 'pch.gypi', + ], + 'dependencies': [ + 'codegen.gyp:codegen_emoji', + 'codegen.gyp:codegen_style', + 'crl.gyp:crl', + ], + 'variables': { + 'variables': { + 'libs_loc': '../../../Libraries', + }, + 'libs_loc': '<(libs_loc)', + 'src_loc': '../SourceFiles', + 'res_loc': '../Resources', + 'official_build_target%': '', + 'submodules_loc': '../ThirdParty', + 'emoji_suggestions_loc': '<(submodules_loc)/emoji_suggestions', + 'style_files': [ + '<(res_loc)/colors.palette', + '<(res_loc)/basic.style', + '<(src_loc)/ui/widgets/widgets.style', + ], + 'dependent_style_files': [ + ], + 'style_timestamp': '<(SHARED_INTERMEDIATE_DIR)/update_dependent_styles_ui.timestamp', + 'pch_source': '<(src_loc)/ui/ui_pch.cpp', + 'pch_header': '<(src_loc)/ui/ui_pch.h', + }, + 'defines': [ + ], + 'include_dirs': [ + '<(src_loc)', + '<(SHARED_INTERMEDIATE_DIR)', + '<(libs_loc)/range-v3/include', + '<(submodules_loc)/GSL/include', + '<(submodules_loc)/variant/include', + '<(submodules_loc)/crl/src', + '<(emoji_suggestions_loc)', + ], + 'sources': [ + '<@(style_files)', + '<(src_loc)/ui/style/style_core.cpp', + '<(src_loc)/ui/style/style_core.h', + '<(src_loc)/ui/style/style_core_color.cpp', + '<(src_loc)/ui/style/style_core_color.h', + '<(src_loc)/ui/style/style_core_font.cpp', + '<(src_loc)/ui/style/style_core_font.h', + '<(src_loc)/ui/style/style_core_icon.cpp', + '<(src_loc)/ui/style/style_core_icon.h', + '<(src_loc)/ui/style/style_core_scale.cpp', + '<(src_loc)/ui/style/style_core_scale.h', + '<(src_loc)/ui/style/style_core_types.cpp', + '<(src_loc)/ui/style/style_core_types.h', + '<(src_loc)/ui/painter.h', + '<(emoji_suggestions_loc)/emoji_suggestions.cpp', + '<(emoji_suggestions_loc)/emoji_suggestions.h', + ], + }], +}