mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 02:01:40 -05:00
Ensure contrast in colorized themes.
This commit is contained in:
parent
763bdf8798
commit
117d6192fa
13 changed files with 238 additions and 183 deletions
|
@ -321,12 +321,14 @@ contactsMultiSelect: MultiSelect {
|
||||||
}
|
}
|
||||||
contactsPhotoCheckIcon: icon {{
|
contactsPhotoCheckIcon: icon {{
|
||||||
"default_checkbox_check",
|
"default_checkbox_check",
|
||||||
windowFgActive,
|
overviewCheckFgActive,
|
||||||
point(3px, 6px)
|
point(3px, 6px)
|
||||||
}};
|
}};
|
||||||
contactsPhotoCheck: RoundCheckbox(defaultRoundCheckbox) {
|
contactsPhotoCheck: RoundCheckbox(defaultRoundCheckbox) {
|
||||||
size: 20px;
|
size: 20px;
|
||||||
sizeSmall: 0.3;
|
sizeSmall: 0.3;
|
||||||
|
bgInactive: overviewCheckBg;
|
||||||
|
bgActive: overviewCheckBgActive;
|
||||||
check: contactsPhotoCheckIcon;
|
check: contactsPhotoCheckIcon;
|
||||||
}
|
}
|
||||||
contactsPhotoCheckbox: RoundImageCheckbox {
|
contactsPhotoCheckbox: RoundImageCheckbox {
|
||||||
|
|
|
@ -48,8 +48,6 @@ overviewCheck: RoundCheckbox(defaultRoundCheckbox) {
|
||||||
check: icon {{ "overview_photo_check", overviewCheckFgActive, point(4px, 8px) }};
|
check: icon {{ "overview_photo_check", overviewCheckFgActive, point(4px, 8px) }};
|
||||||
}
|
}
|
||||||
overviewSmallCheck: RoundCheckbox(contactsPhotoCheck) {
|
overviewSmallCheck: RoundCheckbox(contactsPhotoCheck) {
|
||||||
bgInactive: overviewCheckBg;
|
|
||||||
bgActive: overviewCheckBgActive;
|
|
||||||
border: overviewCheckBorder;
|
border: overviewCheckBorder;
|
||||||
}
|
}
|
||||||
overviewCheckSkip: 5px;
|
overviewCheckSkip: 5px;
|
||||||
|
|
|
@ -286,7 +286,7 @@ public:
|
||||||
QImage prepareRippleMask() const override;
|
QImage prepareRippleMask() const override;
|
||||||
bool checkRippleStartPosition(QPoint position) const override;
|
bool checkRippleStartPosition(QPoint position) const override;
|
||||||
|
|
||||||
void setColorizer(const Window::Theme::Colorizer *colorizer);
|
void setColorizer(const Window::Theme::Colorizer &colorizer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void checkedChangedHook(anim::type animated) override;
|
void checkedChangedHook(anim::type animated) override;
|
||||||
|
@ -503,10 +503,10 @@ DefaultTheme::DefaultTheme(Scheme scheme, bool checked)
|
||||||
: AbstractCheckView(st::defaultRadio.duration, checked, nullptr)
|
: AbstractCheckView(st::defaultRadio.duration, checked, nullptr)
|
||||||
, _scheme(scheme)
|
, _scheme(scheme)
|
||||||
, _radio(st::defaultRadio, checked, [=] { update(); }) {
|
, _radio(st::defaultRadio, checked, [=] { update(); }) {
|
||||||
setColorizer(nullptr);
|
setColorizer({});
|
||||||
}
|
}
|
||||||
|
|
||||||
void DefaultTheme::setColorizer(const Window::Theme::Colorizer *colorizer) {
|
void DefaultTheme::setColorizer(const Window::Theme::Colorizer &colorizer) {
|
||||||
_colorized = _scheme;
|
_colorized = _scheme;
|
||||||
if (colorizer) {
|
if (colorizer) {
|
||||||
Window::Theme::Colorize(_colorized, colorizer);
|
Window::Theme::Colorize(_colorized, colorizer);
|
||||||
|
@ -986,43 +986,25 @@ void SetupDefaultThemes(not_null<Ui::VerticalLayout*> container) {
|
||||||
};
|
};
|
||||||
const auto group = std::make_shared<Ui::RadioenumGroup<Type>>(chosen());
|
const auto group = std::make_shared<Ui::RadioenumGroup<Type>>(chosen());
|
||||||
|
|
||||||
const auto apply = [=](
|
const auto apply = [=](const Scheme &scheme) {
|
||||||
const Scheme &scheme,
|
|
||||||
const Window::Theme::Colorizer *colorizer = nullptr) {
|
|
||||||
const auto isNight = [](const Scheme &scheme) {
|
const auto isNight = [](const Scheme &scheme) {
|
||||||
const auto type = scheme.type;
|
const auto type = scheme.type;
|
||||||
return (type != Type::DayBlue) && (type != Type::Default);
|
return (type != Type::DayBlue) && (type != Type::Default);
|
||||||
};
|
};
|
||||||
const auto currentlyIsCustom = (chosen() == Type(-1));
|
const auto currentlyIsCustom = (chosen() == Type(-1));
|
||||||
if (Window::Theme::IsNightMode() == isNight(scheme)) {
|
if (Window::Theme::IsNightMode() == isNight(scheme)) {
|
||||||
Window::Theme::ApplyDefaultWithPath(scheme.path, colorizer);
|
Window::Theme::ApplyDefaultWithPath(scheme.path);
|
||||||
} else {
|
} else {
|
||||||
Window::Theme::ToggleNightMode(scheme.path, colorizer);
|
Window::Theme::ToggleNightMode(scheme.path);
|
||||||
}
|
}
|
||||||
if (!currentlyIsCustom) {
|
if (!currentlyIsCustom) {
|
||||||
Window::Theme::KeepApplied();
|
Window::Theme::KeepApplied();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const auto applyWithColor = [=](
|
|
||||||
const Scheme &scheme,
|
|
||||||
const QColor &color) {
|
|
||||||
auto &colors = Core::App().settings().themesAccentColors();
|
|
||||||
if (colors.get(scheme.type) != color) {
|
|
||||||
colors.set(scheme.type, color);
|
|
||||||
Local::writeSettings();
|
|
||||||
}
|
|
||||||
const auto colorizer = Window::Theme::ColorizerFrom(scheme, color);
|
|
||||||
apply(scheme, &colorizer);
|
|
||||||
};
|
|
||||||
const auto schemeClicked = [=](
|
const auto schemeClicked = [=](
|
||||||
const Scheme &scheme,
|
const Scheme &scheme,
|
||||||
Qt::KeyboardModifiers modifiers) {
|
Qt::KeyboardModifiers modifiers) {
|
||||||
const auto &colors = Core::App().settings().themesAccentColors();
|
apply(scheme);
|
||||||
if (const auto color = colors.get(scheme.type)) {
|
|
||||||
applyWithColor(scheme, *color);
|
|
||||||
} else {
|
|
||||||
apply(scheme);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
auto checks = base::flat_map<Type,not_null<DefaultTheme*>>();
|
auto checks = base::flat_map<Type,not_null<DefaultTheme*>>();
|
||||||
|
@ -1062,9 +1044,9 @@ void SetupDefaultThemes(not_null<Ui::VerticalLayout*> container) {
|
||||||
const auto colorizer = Window::Theme::ColorizerFrom(
|
const auto colorizer = Window::Theme::ColorizerFrom(
|
||||||
*scheme,
|
*scheme,
|
||||||
*color);
|
*color);
|
||||||
i->second->setColorizer(&colorizer);
|
i->second->setColorizer(colorizer);
|
||||||
} else {
|
} else {
|
||||||
i->second->setColorizer(nullptr);
|
i->second->setColorizer({});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1136,7 +1118,12 @@ void SetupDefaultThemes(not_null<Ui::VerticalLayout*> container) {
|
||||||
if (scheme == end(kSchemesList)) {
|
if (scheme == end(kSchemesList)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
applyWithColor(*scheme, color);
|
auto &colors = Core::App().settings().themesAccentColors();
|
||||||
|
if (colors.get(type) != color) {
|
||||||
|
colors.set(type, color);
|
||||||
|
Local::writeSettings();
|
||||||
|
}
|
||||||
|
apply(*scheme);
|
||||||
}, container->lifetime());
|
}, container->lifetime());
|
||||||
|
|
||||||
AddSkip(container);
|
AddSkip(container);
|
||||||
|
|
|
@ -7,6 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "ui/effects/round_checkbox.h"
|
#include "ui/effects/round_checkbox.h"
|
||||||
|
|
||||||
|
#include "window/themes/window_theme.h"
|
||||||
|
#include "ui/rp_widget.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -237,11 +240,18 @@ QPixmap CheckCaches::paintFrame(
|
||||||
CheckCaches *FrameCaches() {
|
CheckCaches *FrameCaches() {
|
||||||
static QPointer<CheckCaches> Instance;
|
static QPointer<CheckCaches> Instance;
|
||||||
|
|
||||||
if (auto instance = Instance.data()) {
|
if (const auto instance = Instance.data()) {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
auto result = new CheckCaches(QGuiApplication::instance());
|
const auto result = new CheckCaches(QGuiApplication::instance());
|
||||||
Instance = result;
|
Instance = result;
|
||||||
|
const auto subscription = Ui::CreateChild<base::Subscription>(result);
|
||||||
|
*subscription = Window::Theme::Background()->add_subscription([=](
|
||||||
|
const Window::Theme::BackgroundUpdate &update) {
|
||||||
|
if (update.paletteChanged()) {
|
||||||
|
FrameCaches()->clear();
|
||||||
|
}
|
||||||
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,7 +340,6 @@ void RoundCheckbox::setChecked(bool newChecked, SetStyle speed) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoundCheckbox::invalidateCache() {
|
void RoundCheckbox::invalidateCache() {
|
||||||
FrameCaches()->clear();
|
|
||||||
if (!_inactiveCacheBg.isNull() || !_inactiveCacheFg.isNull()) {
|
if (!_inactiveCacheBg.isNull() || !_inactiveCacheFg.isNull()) {
|
||||||
prepareInactiveCache();
|
prepareInactiveCache();
|
||||||
}
|
}
|
||||||
|
|
|
@ -700,7 +700,7 @@ defaultInputField: InputField {
|
||||||
heightMax: 148px;
|
heightMax: 148px;
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultCheckboxIcon: icon {{ "default_checkbox_check", windowFgActive, point(4px, 7px) }};
|
defaultCheckboxIcon: icon {{ "default_checkbox_check", overviewCheckFgActive, point(4px, 7px) }};
|
||||||
|
|
||||||
defaultCheck: Check {
|
defaultCheck: Check {
|
||||||
bg: transparent;
|
bg: transparent;
|
||||||
|
|
|
@ -152,8 +152,8 @@ enum class SetResult {
|
||||||
SetResult setColorSchemeValue(
|
SetResult setColorSchemeValue(
|
||||||
QLatin1String name,
|
QLatin1String name,
|
||||||
QLatin1String value,
|
QLatin1String value,
|
||||||
Instance *out,
|
const Colorizer &colorizer,
|
||||||
const Colorizer *colorizer) {
|
Instance *out) {
|
||||||
auto result = style::palette::SetResult::Ok;
|
auto result = style::palette::SetResult::Ok;
|
||||||
auto size = value.size();
|
auto size = value.size();
|
||||||
auto data = value.data();
|
auto data = value.data();
|
||||||
|
@ -163,8 +163,8 @@ SetResult setColorSchemeValue(
|
||||||
auto g = readHexUchar(data[3], data[4], error);
|
auto g = readHexUchar(data[3], data[4], error);
|
||||||
auto b = readHexUchar(data[5], data[6], error);
|
auto b = readHexUchar(data[5], data[6], error);
|
||||||
auto a = (size == 9) ? readHexUchar(data[7], data[8], error) : uchar(255);
|
auto a = (size == 9) ? readHexUchar(data[7], data[8], error) : uchar(255);
|
||||||
if (colorizer && !colorizer->ignoreKeys.contains(name)) {
|
if (colorizer) {
|
||||||
Colorize(r, g, b, colorizer);
|
Colorize(name, r, g, b, colorizer);
|
||||||
}
|
}
|
||||||
if (error) {
|
if (error) {
|
||||||
LOG(("Theme Warning: Skipping value '%1: %2' (expected a color value in #rrggbb or #rrggbbaa or a previously defined key in the color scheme)").arg(name).arg(value));
|
LOG(("Theme Warning: Skipping value '%1: %2' (expected a color value in #rrggbb or #rrggbbaa or a previously defined key in the color scheme)").arg(name).arg(value));
|
||||||
|
@ -199,14 +199,14 @@ SetResult setColorSchemeValue(
|
||||||
|
|
||||||
bool loadColorScheme(
|
bool loadColorScheme(
|
||||||
const QByteArray &content,
|
const QByteArray &content,
|
||||||
Instance *out,
|
const Colorizer &colorizer,
|
||||||
const Colorizer *colorizer = nullptr) {
|
Instance *out) {
|
||||||
auto unsupported = QMap<QLatin1String, QLatin1String>();
|
auto unsupported = QMap<QLatin1String, QLatin1String>();
|
||||||
return ReadPaletteValues(content, [&](QLatin1String name, QLatin1String value) {
|
return ReadPaletteValues(content, [&](QLatin1String name, QLatin1String value) {
|
||||||
// Find the named value in the already read unsupported list.
|
// Find the named value in the already read unsupported list.
|
||||||
value = unsupported.value(value, value);
|
value = unsupported.value(value, value);
|
||||||
|
|
||||||
auto result = setColorSchemeValue(name, value, out, colorizer);
|
auto result = setColorSchemeValue(name, value, colorizer, out);
|
||||||
if (result == SetResult::Bad) {
|
if (result == SetResult::Bad) {
|
||||||
return false;
|
return false;
|
||||||
} else if (result == SetResult::NotFound) {
|
} else if (result == SetResult::NotFound) {
|
||||||
|
@ -293,8 +293,8 @@ bool loadBackground(zlib::FileToRead &file, QByteArray *outBackground, bool *out
|
||||||
bool loadTheme(
|
bool loadTheme(
|
||||||
const QByteArray &content,
|
const QByteArray &content,
|
||||||
Cached &cache,
|
Cached &cache,
|
||||||
Instance *out = nullptr,
|
const Colorizer &colorizer,
|
||||||
const Colorizer *colorizer = nullptr) {
|
Instance *out = nullptr) {
|
||||||
cache = Cached();
|
cache = Cached();
|
||||||
zlib::FileToRead file(content);
|
zlib::FileToRead file(content);
|
||||||
|
|
||||||
|
@ -310,7 +310,7 @@ bool loadTheme(
|
||||||
LOG(("Theme Error: could not read 'colors.tdesktop-theme' or 'colors.tdesktop-palette' in the theme file."));
|
LOG(("Theme Error: could not read 'colors.tdesktop-theme' or 'colors.tdesktop-palette' in the theme file."));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!loadColorScheme(schemeContent, out, colorizer)) {
|
if (!loadColorScheme(schemeContent, colorizer, out)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Background()->saveAdjustableColors();
|
Background()->saveAdjustableColors();
|
||||||
|
@ -349,7 +349,7 @@ bool loadTheme(
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Looks like it is not a .zip theme.
|
// Looks like it is not a .zip theme.
|
||||||
if (!loadColorScheme(content, out, colorizer)) {
|
if (!loadColorScheme(content, colorizer, out)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Background()->saveAdjustableColors();
|
Background()->saveAdjustableColors();
|
||||||
|
@ -911,9 +911,7 @@ bool ChatBackground::nightMode() const {
|
||||||
return _nightMode;
|
return _nightMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatBackground::toggleNightMode(
|
void ChatBackground::toggleNightMode(std::optional<QString> themePath) {
|
||||||
std::optional<QString> themePath,
|
|
||||||
const Colorizer *colorizer) {
|
|
||||||
const auto settingDefault = themePath.has_value();
|
const auto settingDefault = themePath.has_value();
|
||||||
const auto oldNightMode = _nightMode;
|
const auto oldNightMode = _nightMode;
|
||||||
const auto newNightMode = !_nightMode;
|
const auto newNightMode = !_nightMode;
|
||||||
|
@ -935,6 +933,7 @@ void ChatBackground::toggleNightMode(
|
||||||
const auto loaded = loadTheme(
|
const auto loaded = loadTheme(
|
||||||
preview->content,
|
preview->content,
|
||||||
preview->instance.cached,
|
preview->instance.cached,
|
||||||
|
ColorizerForTheme(path),
|
||||||
&preview->instance);
|
&preview->instance);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -946,7 +945,7 @@ void ChatBackground::toggleNightMode(
|
||||||
path = themePath
|
path = themePath
|
||||||
? *themePath
|
? *themePath
|
||||||
: (newNightMode ? NightThemePath() : QString());
|
: (newNightMode ? NightThemePath() : QString());
|
||||||
ApplyDefaultWithPath(path, colorizer);
|
ApplyDefaultWithPath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Theme editor could have already reverted the testing of this toggle.
|
// Theme editor could have already reverted the testing of this toggle.
|
||||||
|
@ -993,7 +992,8 @@ bool Load(Saved &&saved) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!loadTheme(saved.content, saved.cache)) {
|
const auto colorizer = ColorizerForTheme(saved.pathAbsolute);
|
||||||
|
if (!loadTheme(saved.content, saved.cache, colorizer)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Local::writeTheme(saved);
|
Local::writeTheme(saved);
|
||||||
|
@ -1025,11 +1025,9 @@ bool Apply(std::unique_ptr<Preview> preview) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplyDefaultWithPath(
|
void ApplyDefaultWithPath(const QString &themePath) {
|
||||||
const QString &themePath,
|
|
||||||
const Colorizer *colorizer) {
|
|
||||||
if (!themePath.isEmpty()) {
|
if (!themePath.isEmpty()) {
|
||||||
if (auto preview = PreviewFromFile(themePath, colorizer)) {
|
if (auto preview = PreviewFromFile(themePath)) {
|
||||||
Apply(std::move(preview));
|
Apply(std::move(preview));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1046,12 +1044,14 @@ void ApplyDefaultWithPath(
|
||||||
|
|
||||||
bool ApplyEditedPalette(const QString &path, const QByteArray &content) {
|
bool ApplyEditedPalette(const QString &path, const QByteArray &content) {
|
||||||
Instance out;
|
Instance out;
|
||||||
if (!loadColorScheme(content, &out)) {
|
if (!loadColorScheme(content, Colorizer(), &out)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
out.cached.colors = out.palette.save();
|
out.cached.colors = out.palette.save();
|
||||||
out.cached.paletteChecksum = style::palette::Checksum();
|
out.cached.paletteChecksum = style::palette::Checksum();
|
||||||
out.cached.contentChecksum = hashCrc32(content.constData(), content.size());
|
out.cached.contentChecksum = hashCrc32(
|
||||||
|
content.constData(),
|
||||||
|
content.size());
|
||||||
|
|
||||||
GlobalApplying.pathRelative = path.isEmpty()
|
GlobalApplying.pathRelative = path.isEmpty()
|
||||||
? QString()
|
? QString()
|
||||||
|
@ -1116,27 +1116,25 @@ void SetNightModeValue(bool nightMode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToggleNightMode() {
|
void ToggleNightMode() {
|
||||||
Background()->toggleNightMode(std::nullopt, nullptr);
|
Background()->toggleNightMode(std::nullopt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToggleNightMode(
|
void ToggleNightMode(const QString &path) {
|
||||||
const QString &path,
|
Background()->toggleNightMode(path);
|
||||||
const Colorizer *colorizer) {
|
|
||||||
Background()->toggleNightMode(path, colorizer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoadFromFile(
|
bool LoadFromFile(
|
||||||
const QString &path,
|
const QString &path,
|
||||||
Instance *out,
|
Instance *out,
|
||||||
QByteArray *outContent,
|
QByteArray *outContent) {
|
||||||
const Colorizer *colorizer) {
|
|
||||||
*outContent = readThemeContent(path);
|
*outContent = readThemeContent(path);
|
||||||
if (outContent->size() < 4) {
|
if (outContent->size() < 4) {
|
||||||
LOG(("Theme Error: Could not load theme from %1").arg(path));
|
LOG(("Theme Error: Could not load theme from %1").arg(path));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return loadTheme(*outContent, out->cached, out, colorizer);
|
const auto colorizer = ColorizerForTheme(path);
|
||||||
|
return loadTheme(*outContent, out->cached, colorizer, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsPaletteTestingPath(const QString &path) {
|
bool IsPaletteTestingPath(const QString &path) {
|
||||||
|
|
|
@ -18,8 +18,6 @@ namespace Theme {
|
||||||
|
|
||||||
constexpr auto kThemeSchemeSizeLimit = 1024 * 1024;
|
constexpr auto kThemeSchemeSizeLimit = 1024 * 1024;
|
||||||
|
|
||||||
struct Colorizer;
|
|
||||||
|
|
||||||
struct Cached {
|
struct Cached {
|
||||||
QByteArray colors;
|
QByteArray colors;
|
||||||
QByteArray background;
|
QByteArray background;
|
||||||
|
@ -53,26 +51,21 @@ struct Preview {
|
||||||
|
|
||||||
bool Apply(const QString &filepath);
|
bool Apply(const QString &filepath);
|
||||||
bool Apply(std::unique_ptr<Preview> preview);
|
bool Apply(std::unique_ptr<Preview> preview);
|
||||||
void ApplyDefaultWithPath(
|
void ApplyDefaultWithPath(const QString &themePath);
|
||||||
const QString &themePath,
|
|
||||||
const Colorizer *colorizer = nullptr);
|
|
||||||
bool ApplyEditedPalette(const QString &path, const QByteArray &content);
|
bool ApplyEditedPalette(const QString &path, const QByteArray &content);
|
||||||
void KeepApplied();
|
void KeepApplied();
|
||||||
QString NightThemePath();
|
QString NightThemePath();
|
||||||
[[nodiscard]] bool IsNightMode();
|
[[nodiscard]] bool IsNightMode();
|
||||||
void SetNightModeValue(bool nightMode);
|
void SetNightModeValue(bool nightMode);
|
||||||
void ToggleNightMode();
|
void ToggleNightMode();
|
||||||
void ToggleNightMode(
|
void ToggleNightMode(const QString &themePath);
|
||||||
const QString &themePath,
|
|
||||||
const Colorizer *colorizer = nullptr);
|
|
||||||
[[nodiscard]] bool IsNonDefaultBackground();
|
[[nodiscard]] bool IsNonDefaultBackground();
|
||||||
void Revert();
|
void Revert();
|
||||||
|
|
||||||
bool LoadFromFile(
|
bool LoadFromFile(
|
||||||
const QString &file,
|
const QString &file,
|
||||||
Instance *out,
|
Instance *out,
|
||||||
QByteArray *outContent,
|
QByteArray *outContent);
|
||||||
const Colorizer *colorizer = nullptr);
|
|
||||||
bool IsPaletteTestingPath(const QString &path);
|
bool IsPaletteTestingPath(const QString &path);
|
||||||
QColor CountAverageColor(const QImage &image);
|
QColor CountAverageColor(const QImage &image);
|
||||||
QColor AdjustedColor(QColor original, QColor background);
|
QColor AdjustedColor(QColor original, QColor background);
|
||||||
|
@ -162,9 +155,7 @@ private:
|
||||||
|
|
||||||
void setNightModeValue(bool nightMode);
|
void setNightModeValue(bool nightMode);
|
||||||
[[nodiscard]] bool nightMode() const;
|
[[nodiscard]] bool nightMode() const;
|
||||||
void toggleNightMode(
|
void toggleNightMode(std::optional<QString> themePath);
|
||||||
std::optional<QString> themePath,
|
|
||||||
const Colorizer *colorizer);
|
|
||||||
void keepApplied(const QString &path, bool write);
|
void keepApplied(const QString &path, bool write);
|
||||||
[[nodiscard]] bool isNonDefaultThemeOrBackground();
|
[[nodiscard]] bool isNonDefaultThemeOrBackground();
|
||||||
[[nodiscard]] bool isNonDefaultBackground();
|
[[nodiscard]] bool isNonDefaultBackground();
|
||||||
|
@ -174,9 +165,7 @@ private:
|
||||||
friend bool IsNightMode();
|
friend bool IsNightMode();
|
||||||
friend void SetNightModeValue(bool nightMode);
|
friend void SetNightModeValue(bool nightMode);
|
||||||
friend void ToggleNightMode();
|
friend void ToggleNightMode();
|
||||||
friend void ToggleNightMode(
|
friend void ToggleNightMode(const QString &themePath);
|
||||||
const QString &themePath,
|
|
||||||
const Colorizer *colorizer);
|
|
||||||
friend void KeepApplied();
|
friend void KeepApplied();
|
||||||
friend bool IsNonDefaultBackground();
|
friend bool IsNonDefaultBackground();
|
||||||
|
|
||||||
|
|
|
@ -188,7 +188,7 @@ QByteArray replaceValueInContent(const QByteArray &content, const QByteArray &na
|
||||||
|
|
||||||
QByteArray ColorizeInContent(
|
QByteArray ColorizeInContent(
|
||||||
QByteArray content,
|
QByteArray content,
|
||||||
not_null<const Colorizer*> colorizer) {
|
const Colorizer &colorizer) {
|
||||||
auto validNames = OrderedSet<QLatin1String>();
|
auto validNames = OrderedSet<QLatin1String>();
|
||||||
content.detach();
|
content.detach();
|
||||||
auto start = content.constBegin(), data = start, end = data + content.size();
|
auto start = content.constBegin(), data = start, end = data + content.size();
|
||||||
|
@ -349,21 +349,10 @@ bool CopyColorsToPalette(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (themePath.startsWith(qstr(":/gui"))) {
|
if (const auto colorizer = ColorizerForTheme(themePath)) {
|
||||||
const auto schemes = EmbeddedThemes();
|
paletteContent = ColorizeInContent(
|
||||||
const auto i = ranges::find(
|
std::move(paletteContent),
|
||||||
schemes,
|
colorizer);
|
||||||
themePath,
|
|
||||||
&EmbeddedScheme::path);
|
|
||||||
if (i != end(schemes)) {
|
|
||||||
const auto &colors = Core::App().settings().themesAccentColors();
|
|
||||||
if (const auto accent = colors.get(i->type)) {
|
|
||||||
const auto colorizer = ColorizerFrom(*i, *accent);
|
|
||||||
paletteContent = ColorizeInContent(
|
|
||||||
std::move(paletteContent),
|
|
||||||
&colorizer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (f.write(paletteContent) != paletteContent.size()) {
|
if (f.write(paletteContent) != paletteContent.size()) {
|
||||||
LOG(("Theme Error: could not write palette to '%1'").arg(destination));
|
LOG(("Theme Error: could not write palette to '%1'").arg(destination));
|
||||||
|
|
|
@ -404,13 +404,16 @@ void EditorBlock::sortByDistance(const QColor &to) {
|
||||||
auto fromSaturation = int();
|
auto fromSaturation = int();
|
||||||
auto fromLightness = int();
|
auto fromLightness = int();
|
||||||
row.value().getHsl(&fromHue, &fromSaturation, &fromLightness);
|
row.value().getHsl(&fromHue, &fromSaturation, &fromLightness);
|
||||||
if (!row.copyOf().isEmpty() && row.copyOf() != "windowBgActive") {
|
if (!row.copyOf().isEmpty()) {
|
||||||
return 365;
|
return 365;
|
||||||
}
|
}
|
||||||
const auto a = std::abs(fromHue - toHue);
|
const auto a = std::abs(fromHue - toHue);
|
||||||
const auto b = 360 + fromHue - toHue;
|
const auto b = 360 + fromHue - toHue;
|
||||||
const auto c = 360 + toHue - fromHue;
|
const auto c = 360 + toHue - fromHue;
|
||||||
return std::min(a, std::min(b, c));
|
if (std::min(a, std::min(b, c)) > 15) {
|
||||||
|
return 363;
|
||||||
|
}
|
||||||
|
return 255 - fromSaturation;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -908,9 +908,7 @@ void Generator::restoreTextPalette() {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
std::unique_ptr<Preview> PreviewFromFile(
|
std::unique_ptr<Preview> PreviewFromFile(const QString &filepath) {
|
||||||
const QString &filepath,
|
|
||||||
const Colorizer *colorizer) {
|
|
||||||
auto result = std::make_unique<Preview>();
|
auto result = std::make_unique<Preview>();
|
||||||
result->pathRelative = filepath.isEmpty()
|
result->pathRelative = filepath.isEmpty()
|
||||||
? QString()
|
? QString()
|
||||||
|
@ -918,11 +916,7 @@ std::unique_ptr<Preview> PreviewFromFile(
|
||||||
result->pathAbsolute = filepath.isEmpty()
|
result->pathAbsolute = filepath.isEmpty()
|
||||||
? QString()
|
? QString()
|
||||||
: QFileInfo(filepath).absoluteFilePath();
|
: QFileInfo(filepath).absoluteFilePath();
|
||||||
if (!LoadFromFile(
|
if (!LoadFromFile(filepath, &result->instance, &result->content)) {
|
||||||
filepath,
|
|
||||||
&result->instance,
|
|
||||||
&result->content,
|
|
||||||
colorizer)) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -18,9 +18,7 @@ struct CurrentData {
|
||||||
bool backgroundTiled = false;
|
bool backgroundTiled = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<Preview> PreviewFromFile(
|
std::unique_ptr<Preview> PreviewFromFile(const QString &filepath);
|
||||||
const QString &filepath,
|
|
||||||
const Colorizer *colorizer = nullptr);
|
|
||||||
std::unique_ptr<Preview> GeneratePreview(
|
std::unique_ptr<Preview> GeneratePreview(
|
||||||
const QString &filepath,
|
const QString &filepath,
|
||||||
CurrentData &&data);
|
CurrentData &&data);
|
||||||
|
|
|
@ -9,12 +9,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include "window/themes/window_theme.h"
|
#include "window/themes/window_theme.h"
|
||||||
#include "storage/serialize_common.h"
|
#include "storage/serialize_common.h"
|
||||||
|
#include "core/application.h"
|
||||||
|
#include "core/core_settings.h"
|
||||||
|
|
||||||
namespace Window {
|
namespace Window {
|
||||||
namespace Theme {
|
namespace Theme {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr auto kMaxAccentColors = 3;
|
constexpr auto kMaxAccentColors = 3;
|
||||||
|
constexpr auto kEnoughLightnessForContrast = 64;
|
||||||
|
|
||||||
const auto kColorizeIgnoredKeys = base::flat_set<QLatin1String>{ {
|
const auto kColorizeIgnoredKeys = base::flat_set<QLatin1String>{ {
|
||||||
qstr("boxTextFgGood"),
|
qstr("boxTextFgGood"),
|
||||||
|
@ -100,6 +103,7 @@ Colorizer::Color cColor(str_const hex) {
|
||||||
|
|
||||||
Colorizer ColorizerFrom(const EmbeddedScheme &scheme, const QColor &color) {
|
Colorizer ColorizerFrom(const EmbeddedScheme &scheme, const QColor &color) {
|
||||||
using Color = Colorizer::Color;
|
using Color = Colorizer::Color;
|
||||||
|
using Pair = std::pair<Color, Color>;
|
||||||
|
|
||||||
auto result = Colorizer();
|
auto result = Colorizer();
|
||||||
result.ignoreKeys = kColorizeIgnoredKeys;
|
result.ignoreKeys = kColorizeIgnoredKeys;
|
||||||
|
@ -114,26 +118,34 @@ Colorizer ColorizerFrom(const EmbeddedScheme &scheme, const QColor &color) {
|
||||||
&result.now.lightness);
|
&result.now.lightness);
|
||||||
switch (scheme.type) {
|
switch (scheme.type) {
|
||||||
case EmbeddedType::DayBlue:
|
case EmbeddedType::DayBlue:
|
||||||
result.lightnessMax = 191;
|
result.lightnessMax = 160;
|
||||||
break;
|
break;
|
||||||
case EmbeddedType::Night:
|
case EmbeddedType::Night:
|
||||||
result.keepContrast = base::flat_map<QLatin1String, Color>{ {
|
result.keepContrast = base::flat_map<QLatin1String, Pair>{ {
|
||||||
{ qstr("windowFgActive"), cColor("5288c1") }, // windowBgActive
|
//{ qstr("windowFgActive"), Pair{ cColor("5288c1"), cColor("17212b") } }, // windowBgActive
|
||||||
{ qstr("activeButtonFg"), cColor("2f6ea5") }, // activeButtonBg
|
{ qstr("activeButtonFg"), Pair{ cColor("2f6ea5"), cColor("17212b") } }, // activeButtonBg
|
||||||
{ qstr("profileVerifiedCheckFg"), cColor("5288c1") }, // profileVerifiedCheckBg
|
{ qstr("profileVerifiedCheckFg"), Pair{ cColor("5288c1"), cColor("17212b") } }, // profileVerifiedCheckBg
|
||||||
{ qstr("overviewCheckFgActive"), cColor("5288c1") }, // overviewCheckBgActive
|
{ qstr("overviewCheckFgActive"), Pair{ cColor("5288c1"), cColor("17212b") } }, // overviewCheckBgActive
|
||||||
|
{ qstr("historyFileInIconFg"), Pair{ cColor("3f96d0"), cColor("182533") } }, // msgFileInBg, msgInBg
|
||||||
|
{ qstr("historyFileInIconFgSelected"), Pair{ cColor("6ab4f4"), cColor("2e70a5") } }, // msgFileInBgSelected, msgInBgSelected
|
||||||
|
{ qstr("historyFileInRadialFg"), Pair{ cColor("3f96d0"), cColor("182533") } }, // msgFileInBg, msgInBg
|
||||||
|
{ qstr("historyFileInRadialFgSelected"), Pair{ cColor("6ab4f4"), cColor("2e70a5") } }, // msgFileInBgSelected, msgInBgSelected
|
||||||
|
{ qstr("historyFileOutIconFg"), Pair{ cColor("4c9ce2"), cColor("2b5278") } }, // msgFileOutBg, msgOutBg
|
||||||
|
{ qstr("historyFileOutIconFgSelected"), Pair{ cColor("58abf3"), cColor("2e70a5") } }, // msgFileOutBgSelected, msgOutBgSelected
|
||||||
|
{ qstr("historyFileOutRadialFg"), Pair{ cColor("4c9ce2"), cColor("2b5278") } }, // msgFileOutBg, msgOutBg
|
||||||
|
{ qstr("historyFileOutRadialFgSelected"), Pair{ cColor("58abf3"), cColor("2e70a5") } }, // msgFileOutBgSelected, msgOutBgSelected
|
||||||
} };
|
} };
|
||||||
result.lightnessMin = 64;
|
result.lightnessMin = 96;
|
||||||
break;
|
break;
|
||||||
case EmbeddedType::NightGreen:
|
case EmbeddedType::NightGreen:
|
||||||
result.keepContrast = base::flat_map<QLatin1String, Color>{ {
|
result.keepContrast = base::flat_map<QLatin1String, Pair>{ {
|
||||||
{ qstr("windowFgActive"), cColor("3fc1b0") }, // windowBgActive
|
//{ qstr("windowFgActive"), Pair{ cColor("3fc1b0"), cColor("282e33") } }, // windowBgActive, windowBg
|
||||||
{ qstr("activeButtonFg"), cColor("2da192") }, // activeButtonBg
|
{ qstr("activeButtonFg"), Pair{ cColor("2da192"), cColor("282e33") } }, // activeButtonBg, windowBg
|
||||||
{ qstr("profileVerifiedCheckFg"), cColor("3fc1b0") }, // profileVerifiedCheckBg
|
{ qstr("profileVerifiedCheckFg"), Pair{ cColor("3fc1b0"), cColor("282e33") } }, // profileVerifiedCheckBg, windowBg
|
||||||
{ qstr("overviewCheckFgActive"), cColor("3fc1b0") }, // overviewCheckBgActive
|
{ qstr("overviewCheckFgActive"), Pair{ cColor("3fc1b0"), cColor("282e33") } }, // overviewCheckBgActive
|
||||||
{ qstr("callIconFg"), cColor("5ad1c1") }, // callAnswerBg
|
{ qstr("callIconFg"), Pair{ cColor("5ad1c1"), cColor("26282c") } }, // callAnswerBg, callBg
|
||||||
} };
|
} };
|
||||||
result.lightnessMin = 64;
|
result.lightnessMin = 96;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
result.now.lightness = std::clamp(
|
result.now.lightness = std::clamp(
|
||||||
|
@ -143,56 +155,131 @@ Colorizer ColorizerFrom(const EmbeddedScheme &scheme, const QColor &color) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Colorize(
|
Colorizer ColorizerForTheme(const QString &absolutePath) {
|
||||||
uchar &r,
|
if (!absolutePath.startsWith(qstr(":/gui"))) {
|
||||||
uchar &g,
|
return Colorizer();
|
||||||
uchar &b,
|
}
|
||||||
not_null<const Colorizer*> colorizer) {
|
const auto schemes = EmbeddedThemes();
|
||||||
auto color = QColor(int(r), int(g), int(b));
|
const auto i = ranges::find(
|
||||||
|
schemes,
|
||||||
|
absolutePath,
|
||||||
|
&EmbeddedScheme::path);
|
||||||
|
if (i == end(schemes)) {
|
||||||
|
return Colorizer();
|
||||||
|
}
|
||||||
|
const auto &colors = Core::App().settings().themesAccentColors();
|
||||||
|
if (const auto accent = colors.get(i->type)) {
|
||||||
|
return ColorizerFrom(*i, *accent);
|
||||||
|
}
|
||||||
|
return Colorizer();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] std::optional<Colorizer::Color> Colorize(
|
||||||
|
const Colorizer::Color &color,
|
||||||
|
const Colorizer &colorizer) {
|
||||||
|
const auto changeColor = std::abs(color.hue - colorizer.was.hue)
|
||||||
|
< colorizer.hueThreshold;
|
||||||
|
if (!changeColor) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
const auto nowHue = color.hue + (colorizer.now.hue - colorizer.was.hue);
|
||||||
|
const auto nowSaturation = ((color.saturation > colorizer.was.saturation)
|
||||||
|
&& (colorizer.now.saturation > colorizer.was.saturation))
|
||||||
|
? (((colorizer.now.saturation * (255 - colorizer.was.saturation))
|
||||||
|
+ ((color.saturation - colorizer.was.saturation)
|
||||||
|
* (255 - colorizer.now.saturation)))
|
||||||
|
/ (255 - colorizer.was.saturation))
|
||||||
|
: ((color.saturation != colorizer.was.saturation)
|
||||||
|
&& (colorizer.was.saturation != 0))
|
||||||
|
? ((color.saturation * colorizer.now.saturation)
|
||||||
|
/ colorizer.was.saturation)
|
||||||
|
: colorizer.now.saturation;
|
||||||
|
const auto nowLightness = (color.lightness > colorizer.was.lightness)
|
||||||
|
? (((colorizer.now.lightness * (255 - colorizer.was.lightness))
|
||||||
|
+ ((color.lightness - colorizer.was.lightness)
|
||||||
|
* (255 - colorizer.now.lightness)))
|
||||||
|
/ (255 - colorizer.was.lightness))
|
||||||
|
: (color.lightness < colorizer.was.lightness)
|
||||||
|
? ((color.lightness * colorizer.now.lightness)
|
||||||
|
/ colorizer.was.lightness)
|
||||||
|
: colorizer.now.lightness;
|
||||||
|
return Colorizer::Color{
|
||||||
|
((nowHue + 360) % 360),
|
||||||
|
nowSaturation,
|
||||||
|
nowLightness
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] std::optional<QColor> Colorize(
|
||||||
|
const QColor &color,
|
||||||
|
const Colorizer &colorizer) {
|
||||||
auto hue = 0;
|
auto hue = 0;
|
||||||
auto saturation = 0;
|
auto saturation = 0;
|
||||||
auto lightness = 0;
|
auto lightness = 0;
|
||||||
color.getHsl(&hue, &saturation, &lightness);
|
color.getHsl(&hue, &saturation, &lightness);
|
||||||
const auto changeColor = std::abs(hue - colorizer->was.hue)
|
const auto result = Colorize(
|
||||||
<= colorizer->hueThreshold;
|
Colorizer::Color{ hue, saturation, lightness },
|
||||||
if (!changeColor) {
|
colorizer);
|
||||||
return;
|
if (!result) {
|
||||||
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
const auto nowHue = hue + (colorizer->now.hue - colorizer->was.hue);
|
const auto &fields = *result;
|
||||||
const auto nowSaturation = ((saturation > colorizer->was.saturation)
|
return QColor::fromHsl(fields.hue, fields.saturation, fields.lightness);
|
||||||
&& (colorizer->now.saturation > colorizer->was.saturation))
|
}
|
||||||
? (((colorizer->now.saturation * (255 - colorizer->was.saturation))
|
|
||||||
+ ((saturation - colorizer->was.saturation)
|
void FillColorizeResult(uchar &r, uchar &g, uchar &b, const QColor &color) {
|
||||||
* (255 - colorizer->now.saturation)))
|
|
||||||
/ (255 - colorizer->was.saturation))
|
|
||||||
: ((saturation != colorizer->was.saturation)
|
|
||||||
&& (colorizer->was.saturation != 0))
|
|
||||||
? ((saturation * colorizer->now.saturation)
|
|
||||||
/ colorizer->was.saturation)
|
|
||||||
: colorizer->now.saturation;
|
|
||||||
const auto nowLightness = (lightness > colorizer->was.lightness)
|
|
||||||
? (((colorizer->now.lightness * (255 - colorizer->was.lightness))
|
|
||||||
+ ((lightness - colorizer->was.lightness)
|
|
||||||
* (255 - colorizer->now.lightness)))
|
|
||||||
/ (255 - colorizer->was.lightness))
|
|
||||||
: (lightness < colorizer->was.lightness)
|
|
||||||
? ((lightness * colorizer->now.lightness)
|
|
||||||
/ colorizer->was.lightness)
|
|
||||||
: colorizer->now.lightness;
|
|
||||||
auto nowR = 0;
|
auto nowR = 0;
|
||||||
auto nowG = 0;
|
auto nowG = 0;
|
||||||
auto nowB = 0;
|
auto nowB = 0;
|
||||||
QColor::fromHsl(
|
color.getRgb(&nowR, &nowG, &nowB);
|
||||||
((nowHue + 360) % 360),
|
|
||||||
nowSaturation,
|
|
||||||
nowLightness
|
|
||||||
).getRgb(&nowR, &nowG, &nowB);
|
|
||||||
r = uchar(nowR);
|
r = uchar(nowR);
|
||||||
g = uchar(nowG);
|
g = uchar(nowG);
|
||||||
b = uchar(nowB);
|
b = uchar(nowB);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Colorize(uint32 &pixel, not_null<const Colorizer*> colorizer) {
|
void Colorize(uchar &r, uchar &g, uchar &b, const Colorizer &colorizer) {
|
||||||
|
const auto changed = Colorize(QColor(int(r), int(g), int(b)), colorizer);
|
||||||
|
if (changed) {
|
||||||
|
FillColorizeResult(r, g, b, *changed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Colorize(
|
||||||
|
QLatin1String name,
|
||||||
|
uchar &r,
|
||||||
|
uchar &g,
|
||||||
|
uchar &b,
|
||||||
|
const Colorizer &colorizer) {
|
||||||
|
if (colorizer.ignoreKeys.contains(name)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto i = colorizer.keepContrast.find(name);
|
||||||
|
if (i == end(colorizer.keepContrast)) {
|
||||||
|
Colorize(r, g, b, colorizer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto check = i->second.first;
|
||||||
|
const auto rgb = QColor(int(r), int(g), int(b));
|
||||||
|
const auto changed = Colorize(rgb, colorizer);
|
||||||
|
const auto checked = Colorize(check, colorizer).value_or(check);
|
||||||
|
const auto delta = std::abs(changed.value_or(rgb).lightness() - checked.lightness);
|
||||||
|
if (delta >= kEnoughLightnessForContrast) {
|
||||||
|
if (changed) {
|
||||||
|
FillColorizeResult(r, g, b, *changed);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto replace = i->second.second;
|
||||||
|
const auto result = Colorize(replace, colorizer).value_or(replace);
|
||||||
|
FillColorizeResult(
|
||||||
|
r,
|
||||||
|
g,
|
||||||
|
b,
|
||||||
|
QColor::fromHsl(result.hue, result.saturation, result.lightness));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Colorize(uint32 &pixel, const Colorizer &colorizer) {
|
||||||
const auto chars = reinterpret_cast<uchar*>(&pixel);
|
const auto chars = reinterpret_cast<uchar*>(&pixel);
|
||||||
Colorize(
|
Colorize(
|
||||||
chars[2],
|
chars[2],
|
||||||
|
@ -201,15 +288,7 @@ void Colorize(uint32 &pixel, not_null<const Colorizer*> colorizer) {
|
||||||
colorizer);
|
colorizer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Colorize(QColor &color, not_null<const Colorizer*> colorizer) {
|
void Colorize(QImage &image, const Colorizer &colorizer) {
|
||||||
auto r = uchar(color.red());
|
|
||||||
auto g = uchar(color.green());
|
|
||||||
auto b = uchar(color.blue());
|
|
||||||
Colorize(r, g, b, colorizer);
|
|
||||||
color = QColor(r, g, b, color.alpha());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Colorize(QImage &image, not_null<const Colorizer*> colorizer) {
|
|
||||||
image = std::move(image).convertToFormat(QImage::Format_ARGB32);
|
image = std::move(image).convertToFormat(QImage::Format_ARGB32);
|
||||||
const auto bytes = image.bits();
|
const auto bytes = image.bits();
|
||||||
const auto bytesPerLine = image.bytesPerLine();
|
const auto bytesPerLine = image.bytesPerLine();
|
||||||
|
@ -223,7 +302,7 @@ void Colorize(QImage &image, not_null<const Colorizer*> colorizer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Colorize(EmbeddedScheme &scheme, not_null<const Colorizer*> colorizer) {
|
void Colorize(EmbeddedScheme &scheme, const Colorizer &colorizer) {
|
||||||
const auto colors = {
|
const auto colors = {
|
||||||
&EmbeddedScheme::background,
|
&EmbeddedScheme::background,
|
||||||
&EmbeddedScheme::sent,
|
&EmbeddedScheme::sent,
|
||||||
|
@ -232,17 +311,19 @@ void Colorize(EmbeddedScheme &scheme, not_null<const Colorizer*> colorizer) {
|
||||||
&EmbeddedScheme::radiobuttonInactive
|
&EmbeddedScheme::radiobuttonInactive
|
||||||
};
|
};
|
||||||
for (const auto color : colors) {
|
for (const auto color : colors) {
|
||||||
Colorize(scheme.*color, colorizer);
|
if (const auto changed = Colorize(scheme.*color, colorizer)) {
|
||||||
|
scheme.*color = changed->toRgb();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Colorize(
|
QByteArray Colorize(
|
||||||
QLatin1String hexColor,
|
QLatin1String hexColor,
|
||||||
not_null<const Colorizer*> colorizer) {
|
const Colorizer &colorizer) {
|
||||||
Expects(hexColor.size() == 7 || hexColor.size() == 9);
|
Expects(hexColor.size() == 7 || hexColor.size() == 9);
|
||||||
|
|
||||||
auto color = qColor(str_const(hexColor.data() + 1, 6));
|
auto color = qColor(str_const(hexColor.data() + 1, 6));
|
||||||
Colorize(color, colorizer);
|
const auto changed = Colorize(color, colorizer).value_or(color).toRgb();
|
||||||
|
|
||||||
auto result = QByteArray();
|
auto result = QByteArray();
|
||||||
result.reserve(hexColor.size());
|
result.reserve(hexColor.size());
|
||||||
|
@ -258,9 +339,9 @@ QByteArray Colorize(
|
||||||
addHex(code / 16);
|
addHex(code / 16);
|
||||||
addHex(code % 16);
|
addHex(code % 16);
|
||||||
};
|
};
|
||||||
addValue(color.red());
|
addValue(changed.red());
|
||||||
addValue(color.green());
|
addValue(changed.green());
|
||||||
addValue(color.blue());
|
addValue(changed.blue());
|
||||||
if (hexColor.size() == 9) {
|
if (hexColor.size() == 9) {
|
||||||
result.append(hexColor.data()[7]);
|
result.append(hexColor.data()[7]);
|
||||||
result.append(hexColor.data()[8]);
|
result.append(hexColor.data()[8]);
|
||||||
|
@ -311,7 +392,7 @@ std::vector<EmbeddedScheme> EmbeddedThemes() {
|
||||||
qColor("75bfb5"),
|
qColor("75bfb5"),
|
||||||
tr::lng_settings_theme_matrix,
|
tr::lng_settings_theme_matrix,
|
||||||
":/gui/night-green.tdesktop-theme",
|
":/gui/night-green.tdesktop-theme",
|
||||||
qColor("3fc1b0")
|
qColor("01ffdd")
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,23 +59,30 @@ struct Colorizer {
|
||||||
Color was;
|
Color was;
|
||||||
Color now;
|
Color now;
|
||||||
base::flat_set<QLatin1String> ignoreKeys;
|
base::flat_set<QLatin1String> ignoreKeys;
|
||||||
base::flat_map<QLatin1String, Color> keepContrast;
|
base::flat_map<QLatin1String, std::pair<Color, Color>> keepContrast;
|
||||||
|
|
||||||
|
explicit operator bool() const {
|
||||||
|
return (hueThreshold > 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] Colorizer ColorizerFrom(
|
[[nodiscard]] Colorizer ColorizerFrom(
|
||||||
const EmbeddedScheme &scheme,
|
const EmbeddedScheme &scheme,
|
||||||
const QColor &color);
|
const QColor &color);
|
||||||
|
[[nodiscard]] Colorizer ColorizerForTheme(const QString &absolutePath);
|
||||||
|
|
||||||
|
void Colorize(uchar &r, uchar &g, uchar &b, const Colorizer &colorizer);
|
||||||
void Colorize(
|
void Colorize(
|
||||||
|
QLatin1String name,
|
||||||
uchar &r,
|
uchar &r,
|
||||||
uchar &g,
|
uchar &g,
|
||||||
uchar &b,
|
uchar &b,
|
||||||
not_null<const Colorizer*> colorizer);
|
const Colorizer &colorizer);
|
||||||
void Colorize(QImage &image, not_null<const Colorizer*> colorizer);
|
void Colorize(QImage &image, const Colorizer &colorizer);
|
||||||
void Colorize(EmbeddedScheme &scheme, not_null<const Colorizer*> colorizer);
|
void Colorize(EmbeddedScheme &scheme, const Colorizer &colorizer);
|
||||||
[[nodiscard]] QByteArray Colorize(
|
[[nodiscard]] QByteArray Colorize(
|
||||||
QLatin1String hexColor,
|
QLatin1String hexColor,
|
||||||
not_null<const Colorizer*> colorizer);
|
const Colorizer &colorizer);
|
||||||
|
|
||||||
[[nodiscard]] std::vector<EmbeddedScheme> EmbeddedThemes();
|
[[nodiscard]] std::vector<EmbeddedScheme> EmbeddedThemes();
|
||||||
[[nodiscard]] std::vector<QColor> DefaultAccentColors(EmbeddedType type);
|
[[nodiscard]] std::vector<QColor> DefaultAccentColors(EmbeddedType type);
|
||||||
|
|
Loading…
Add table
Reference in a new issue