mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-22 09:07:05 +02:00
Move some style code to lib_ui.
This commit is contained in:
parent
5a1c8e6a0a
commit
e2f54eb3e9
69 changed files with 1119 additions and 856 deletions
|
@ -9,6 +9,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include <cstdlib>
|
||||
|
||||
// Ensures/Expects.
|
||||
#include <gsl/gsl_assert>
|
||||
|
||||
namespace base {
|
||||
namespace assertion {
|
||||
|
||||
|
|
|
@ -7,3 +7,4 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "base/base_pch.h"
|
||||
|
||||
// Precompiled header helper.
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -393,7 +393,10 @@ EmojiListWidget::EmojiListWidget(
|
|||
_esize = Ui::Emoji::GetSizeLarge();
|
||||
|
||||
for (auto i = 0; i != kEmojiSectionCount; ++i) {
|
||||
_counts[i] = Ui::Emoji::GetSectionCount(static_cast<Section>(i));
|
||||
const auto section = static_cast<Section>(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>(section));
|
||||
_emoji[section] = (static_cast<Section>(section) == Section::Recent)
|
||||
? GetRecentEmojiSection()
|
||||
: Ui::Emoji::GetSection(static_cast<Section>(section));
|
||||
_counts[section] = _emoji[section].size();
|
||||
if (static_cast<Section>(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
|
||||
|
|
|
@ -11,6 +11,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/widgets/tooltip.h"
|
||||
#include "base/timer.h"
|
||||
|
||||
namespace tr {
|
||||
template <typename ...Tags>
|
||||
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
|
||||
|
|
|
@ -114,7 +114,7 @@ auto SuggestionsWidget::getRowsByQuery() const -> std::vector<Row> {
|
|||
}) | 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()
|
||||
|
|
|
@ -384,7 +384,7 @@ void InitMessageField(
|
|||
field->setTagMimeProcessor(std::make_unique<FieldTagMimeProcessor>());
|
||||
|
||||
field->document()->setDocumentMargin(4.);
|
||||
field->setAdditionalMargin(ConvertScale(4) - 4);
|
||||
field->setAdditionalMargin(style::ConvertScale(4) - 4);
|
||||
|
||||
field->customTab(true);
|
||||
field->setInstantReplaces(Ui::InstantReplaces::Default());
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -396,6 +396,22 @@ void Init() {\n\
|
|||
|
||||
bool Generator::writeHeader() {
|
||||
auto header = std::make_unique<common::CppFile>(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<EmojiPtr>;\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<std::pair<QString, int>> 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<const One*> 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<std::pair<QString, int>> 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());
|
||||
|
|
|
@ -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<QString(const Module&, structure::FullName)> 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";
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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<Lang::Translator>();
|
||||
QCoreApplication::instance()->installTranslator(_translator.get());
|
||||
|
||||
style::startManager();
|
||||
style::startManager(cScale());
|
||||
Ui::InitTextOptions();
|
||||
Ui::Emoji::Init();
|
||||
Media::Player::start(_audio.get());
|
||||
|
|
|
@ -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<PreLaunchWindow*>(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<PreLaunchWindow*>(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<PreLaunchWindow*>(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<PreLaunchWindow*>(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<PreLaunchWindow*>(parent)->basicSize());
|
||||
setFont(closeFont);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -7,3 +7,4 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "export/export_pch.h"
|
||||
|
||||
// Precompiled header helper.
|
||||
|
|
|
@ -124,8 +124,8 @@ QSize Document::countOptimalSize() {
|
|||
auto thumbed = Get<HistoryDocumentThumbed>();
|
||||
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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 });
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 });
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -1800,8 +1800,8 @@ void OverlayWidget::displayPhoto(not_null<PhotoData*> 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();
|
||||
|
|
|
@ -7,3 +7,4 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "mtproto/mtp_pch.h"
|
||||
|
||||
// Precompiled header helper.
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -376,13 +376,15 @@ void AppendFavedStickers(std::vector<PickerScrubberItem> &to) {
|
|||
|
||||
void AppendEmojiPacks(std::vector<PickerScrubberItem> &to) {
|
||||
for (auto i = 0; i != ChatHelpers::kEmojiSectionCount; ++i) {
|
||||
const auto section = Ui::Emoji::GetSection(
|
||||
static_cast<Ui::Emoji::Section>(i));
|
||||
const auto title = i
|
||||
? Ui::Emoji::CategoryTitle(i)(tr::now)
|
||||
: TitleRecentlyUsed();
|
||||
const auto section = static_cast<Ui::Emoji::Section>(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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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<EmojiPtr>;
|
||||
using RecentEmojiPreloadOldOld = QVector<QPair<uint32, ushort>>;
|
||||
using RecentEmojiPreloadOld = QVector<QPair<uint64, ushort>>;
|
||||
using RecentEmojiPreload = QVector<QPair<QString, ushort>>;
|
||||
|
@ -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<EmojiPtr> 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 <typename T>
|
||||
inline T ConvertScale(T value, int scale) {
|
||||
return (value < 0.)
|
||||
? (-ConvertScale(-value, scale))
|
||||
: T(std::round((float64(value) * scale / 100.) - 0.01));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
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()));
|
||||
}
|
||||
|
|
|
@ -124,7 +124,7 @@ void SetupInterfaceScale(
|
|||
const auto toggled = Ui::CreateChild<rpl::event_stream<bool>>(
|
||||
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<int>{ 100, 110, 120, 130, 140, 150 }
|
||||
: std::vector<int>{ 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());
|
||||
|
|
|
@ -99,9 +99,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include <range/v3/all.hpp>
|
||||
|
||||
// Ensures/Expects.
|
||||
#include <gsl/gsl_assert>
|
||||
|
||||
// Redefine Ensures/Expects by our own assertions.
|
||||
#include "base/assertion.h"
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -7,3 +7,4 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "storage/storage_pch.h"
|
||||
|
||||
// Precompiled header helper.
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<Instance>();
|
|||
auto Universal = std::shared_ptr<UniversalImages>();
|
||||
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<QImage> 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<UniversalImages>(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<Instance>(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<Set> Sets() {
|
||||
return kSets | ranges::to_vector;
|
||||
}
|
||||
|
@ -714,83 +658,8 @@ 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;
|
||||
}
|
||||
}
|
||||
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 = {
|
||||
QVector<EmojiPtr> GetDefaultRecent() {
|
||||
const auto defaultRecent = {
|
||||
0xD83DDE02LLU,
|
||||
0xD83DDE18LLU,
|
||||
0x2764LLU,
|
||||
|
@ -826,61 +695,13 @@ RecentEmojiPack &GetRecent() {
|
|||
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));
|
||||
auto result = QVector<EmojiPtr>();
|
||||
for (const auto oldKey : defaultRecent) {
|
||||
if (const auto emoji = Ui::Emoji::FromOldKey(oldKey)) {
|
||||
result.push_back(emoji);
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
|
|
|
@ -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 <QtGui/QPainter>
|
||||
#include <QtGui/QPixmap>
|
||||
|
||||
#include <rpl/producer.h>
|
||||
|
||||
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<void(bool)> callback);
|
||||
|
||||
tr::phrase<> CategoryTitle(int index);
|
||||
|
||||
std::vector<Set> 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<EmojiPtr> GetDefaultRecent();
|
||||
|
||||
const QPixmap &SinglePixmap(EmojiPtr emoji, int fontHeight);
|
||||
void Draw(QPainter &p, EmojiPtr emoji, int size, int x, int y);
|
||||
|
|
118
Telegram/SourceFiles/ui/painter.h
Normal file
118
Telegram/SourceFiles/ui/painter.h
Normal file
|
@ -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 <QtCore/QPoint>
|
||||
#include <QtGui/QPainter>
|
||||
|
||||
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;
|
||||
|
||||
};
|
|
@ -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 <QtGui/QPainter>
|
||||
|
||||
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<internal::ModuleBase*>;
|
||||
NeverFreedPointer<ModulesList> styleModules;
|
||||
int DevicePixelRatioValue = 1;
|
||||
bool RightToLeftValue = false;
|
||||
|
||||
void startModules() {
|
||||
if (!styleModules) return;
|
||||
|
||||
for_const (auto module, *styleModules) {
|
||||
module->start();
|
||||
}
|
||||
std::vector<internal::ModuleBase*> &StyleModules() {
|
||||
static auto result = std::vector<internal::ModuleBase*>();
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -7,6 +7,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QtGui/QColor>
|
||||
#include <QtGui/QPen>
|
||||
#include <QtGui/QBrush>
|
||||
|
||||
namespace style {
|
||||
|
||||
class palette;
|
||||
|
|
|
@ -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 <QtCore/QMap>
|
||||
#include <QtCore/QVector>
|
||||
#include <QtGui/QFontInfo>
|
||||
#include <QtGui/QFontDatabase>
|
||||
|
||||
namespace style {
|
||||
namespace internal {
|
||||
namespace {
|
||||
|
||||
typedef QMap<QString, int> FontFamilyMap;
|
||||
FontFamilyMap fontFamilyMap;
|
||||
|
||||
typedef QVector<QString> FontFamilies;
|
||||
FontFamilies fontFamilies;
|
||||
|
||||
typedef QMap<uint32, FontData*> FontDatas;
|
||||
FontDatas fontsMap;
|
||||
QMap<QString, int> fontFamilyMap;
|
||||
QVector<QString> fontFamilies;
|
||||
QMap<uint32, FontData*> fontsMap;
|
||||
|
||||
uint32 fontKey(int size, uint32 flags, int family) {
|
||||
return (((uint32(family) << 10) | uint32(size)) << 4) | flags;
|
||||
}
|
||||
|
||||
bool ValidateFont(const QString &familyName, int flags = 0) {
|
||||
QFont checkFont(familyName);
|
||||
checkFont.setPixelSize(13);
|
||||
checkFont.setBold(flags & style::internal::FontBold);
|
||||
checkFont.setItalic(flags & style::internal::FontItalic);
|
||||
checkFont.setUnderline(flags & style::internal::FontUnderline);
|
||||
checkFont.setStyleStrategy(QFont::PreferQuality);
|
||||
auto realFamily = QFontInfo(checkFont).family();
|
||||
if (realFamily.trimmed().compare(familyName, Qt::CaseInsensitive)) {
|
||||
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 {
|
||||
|
|
|
@ -7,9 +7,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "base/basic_types.h"
|
||||
|
||||
#include <QtGui/QFont>
|
||||
#include <QtGui/QFontMetrics>
|
||||
|
||||
namespace style {
|
||||
namespace internal {
|
||||
|
||||
void StartFonts();
|
||||
[[nodiscard]] QString GetFontOverride(const QString &familyName);
|
||||
|
||||
void destroyFonts();
|
||||
int registerFontFamily(const QString &family);
|
||||
|
||||
|
|
|
@ -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 <QtGui/QPainter>
|
||||
|
||||
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<const IconMask*, QImage>;
|
||||
using IconPixmaps = QMap<QPair<const IconMask*, uint32>, QPixmap>;
|
||||
using IconDatas = OrderedSet<IconData*>;
|
||||
NeverFreedPointer<IconMasks> iconMasks;
|
||||
NeverFreedPointer<IconPixmaps> iconPixmaps;
|
||||
NeverFreedPointer<IconDatas> iconData;
|
||||
QMap<const IconMask*, QImage> iconMasks;
|
||||
QMap<QPair<const IconMask*, uint32>, QPixmap> iconPixmaps;
|
||||
OrderedSet<IconData*> 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,11 +333,9 @@ int IconData::height() const {
|
|||
|
||||
void resetIcons() {
|
||||
iconPixmaps.clear();
|
||||
if (iconData) {
|
||||
for (auto data : *iconData) {
|
||||
for (const auto data : iconData) {
|
||||
data->reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void destroyIcons() {
|
||||
|
|
|
@ -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 <vector>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
38
Telegram/SourceFiles/ui/style/style_core_scale.cpp
Normal file
38
Telegram/SourceFiles/ui/style/style_core_scale.cpp
Normal file
|
@ -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
|
50
Telegram/SourceFiles/ui/style/style_core_scale.h
Normal file
50
Telegram/SourceFiles/ui/style/style_core_scale.h
Normal file
|
@ -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 <QtCore/QSize>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
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 <typename T>
|
||||
[[nodiscard]] inline T ConvertScale(T value, int scale) {
|
||||
return (value < 0.)
|
||||
? (-ConvertScale(-value, scale))
|
||||
: T(std::round((double(value) * scale / 100.) - 0.01));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
[[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
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -7,6 +7,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "base/basic_types.h"
|
||||
|
||||
#include <QtCore/QList>
|
||||
|
||||
enum class EntityType {
|
||||
Invalid = 0,
|
||||
|
||||
|
|
|
@ -13,114 +13,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include <QtGui/QWindow>
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtGui/QFontDatabase>
|
||||
|
||||
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 {
|
||||
|
|
|
@ -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 <typename Object>
|
||||
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<const QWidget*> 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 <typename Base>
|
||||
class TWidgetHelper : public Base {
|
||||
public:
|
||||
|
|
10
Telegram/SourceFiles/ui/ui_pch.cpp
Normal file
10
Telegram/SourceFiles/ui/ui_pch.cpp
Normal file
|
@ -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.
|
21
Telegram/SourceFiles/ui/ui_pch.h
Normal file
21
Telegram/SourceFiles/ui/ui_pch.h
Normal file
|
@ -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 <QtCore/QString>
|
||||
#include <QtCore/QPoint>
|
||||
#include <QtCore/QRect>
|
||||
#include <QtCore/QSize>
|
||||
|
||||
#include <QtGui/QColor>
|
||||
#include <QtGui/QPen>
|
||||
#include <QtGui/QBrush>
|
||||
#include <QtGui/QCursor>
|
||||
#include <QtGui/QFont>
|
||||
#include <QtGui/QFontMetrics>
|
||||
|
||||
#include <QtWidgets/QWidget>
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -493,7 +493,7 @@ void MainMenu::initResetScaleButton() {
|
|||
} else {
|
||||
_resetScaleButton.create(this);
|
||||
_resetScaleButton->addClickHandler([] {
|
||||
cSetConfigScale(kInterfaceScaleDefault);
|
||||
cSetConfigScale(style::kScaleDefault);
|
||||
Local::writeSettings();
|
||||
App::restart();
|
||||
});
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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': [
|
||||
|
|
|
@ -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,
|
||||
}],
|
||||
}
|
||||
|
|
58
Telegram/gyp/codegen_rules_ui.gypi
Normal file
58
Telegram/gyp/codegen_rules_ui.gypi
Normal file
|
@ -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,
|
||||
}],
|
||||
}
|
54
Telegram/gyp/codegen_styles_rule.gypi
Normal file
54
Telegram/gyp/codegen_styles_rule.gypi
Normal file
|
@ -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,
|
||||
}],
|
||||
}
|
78
Telegram/gyp/lib_ui.gyp
Normal file
78
Telegram/gyp/lib_ui.gyp
Normal file
|
@ -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',
|
||||
],
|
||||
}],
|
||||
}
|
Loading…
Add table
Reference in a new issue