mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-04-01 23:00:58 +00:00
Apply lightness limits in accent colors.
This commit is contained in:
parent
56a82600f8
commit
763bdf8798
Telegram/SourceFiles
@ -296,6 +296,8 @@ public:
|
|||||||
void setRGB(int red, int green, int blue);
|
void setRGB(int red, int green, int blue);
|
||||||
void setAlpha(int alpha);
|
void setAlpha(int alpha);
|
||||||
|
|
||||||
|
void setLightnessLimits(int min, int max);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
void resizeEvent(QResizeEvent *e) override;
|
void resizeEvent(QResizeEvent *e) override;
|
||||||
@ -315,10 +317,14 @@ private:
|
|||||||
void generatePixmap();
|
void generatePixmap();
|
||||||
void updatePixmapFromMask();
|
void updatePixmapFromMask();
|
||||||
void updateCurrentPoint(QPoint localPosition);
|
void updateCurrentPoint(QPoint localPosition);
|
||||||
|
[[nodiscard]] QColor applyLimits(QColor color) const;
|
||||||
|
|
||||||
Direction _direction = Direction::Horizontal;
|
Direction _direction = Direction::Horizontal;
|
||||||
Type _type = Type::Hue;
|
Type _type = Type::Hue;
|
||||||
|
|
||||||
|
int _lightnessMin = 0;
|
||||||
|
int _lightnessMax = 255;
|
||||||
|
|
||||||
QColor _color;
|
QColor _color;
|
||||||
float64 _value = 0;
|
float64 _value = 0;
|
||||||
|
|
||||||
@ -331,7 +337,12 @@ private:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
EditColorBox::Slider::Slider(QWidget *parent, Direction direction, Type type, QColor color) : TWidget(parent)
|
EditColorBox::Slider::Slider(
|
||||||
|
QWidget *parent,
|
||||||
|
Direction direction,
|
||||||
|
Type type,
|
||||||
|
QColor color)
|
||||||
|
: TWidget(parent)
|
||||||
, _direction(direction)
|
, _direction(direction)
|
||||||
, _type(type)
|
, _type(type)
|
||||||
, _color(color.red(), color.green(), color.blue())
|
, _color(color.red(), color.green(), color.blue())
|
||||||
@ -429,10 +440,13 @@ void EditColorBox::Slider::generatePixmap() {
|
|||||||
_mask = std::move(image);
|
_mask = std::move(image);
|
||||||
updatePixmapFromMask();
|
updatePixmapFromMask();
|
||||||
} else {
|
} else {
|
||||||
QColor color;
|
const auto range = _lightnessMax - _lightnessMin;
|
||||||
for (auto x = 0; x != size; ++x) {
|
for (auto x = 0; x != size; ++x) {
|
||||||
color.setHsl(_color.hslHue(), _color.hslSaturation(), x * 255 / size);
|
const auto color = QColor::fromHsl(
|
||||||
auto value = anim::getPremultiplied(color.toRgb());
|
_color.hslHue(),
|
||||||
|
_color.hslSaturation(),
|
||||||
|
_lightnessMin + x * range / size);
|
||||||
|
const auto value = anim::getPremultiplied(color.toRgb());
|
||||||
for (auto y = 0; y != cIntRetinaFactor(); ++y) {
|
for (auto y = 0; y != cIntRetinaFactor(); ++y) {
|
||||||
ints[y * intsPerLine] = value;
|
ints[y * intsPerLine] = value;
|
||||||
}
|
}
|
||||||
@ -454,13 +468,16 @@ void EditColorBox::Slider::setHSB(HSB hsb) {
|
|||||||
_color.setHsv(hsb.hue, hsb.saturation, hsb.brightness);
|
_color.setHsv(hsb.hue, hsb.saturation, hsb.brightness);
|
||||||
colorUpdated();
|
colorUpdated();
|
||||||
} else {
|
} else {
|
||||||
_color.setHsl(hsb.hue, hsb.saturation, hsb.brightness);
|
_color.setHsl(
|
||||||
|
hsb.hue,
|
||||||
|
hsb.saturation,
|
||||||
|
std::clamp(hsb.brightness, _lightnessMin, _lightnessMax));
|
||||||
colorUpdated();
|
colorUpdated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditColorBox::Slider::setRGB(int red, int green, int blue) {
|
void EditColorBox::Slider::setRGB(int red, int green, int blue) {
|
||||||
_color.setRgb(red, green, blue);
|
_color = applyLimits(QColor(red, green, blue));
|
||||||
colorUpdated();
|
colorUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -470,6 +487,7 @@ void EditColorBox::Slider::colorUpdated() {
|
|||||||
} else if (!_mask.isNull()) {
|
} else if (!_mask.isNull()) {
|
||||||
updatePixmapFromMask();
|
updatePixmapFromMask();
|
||||||
} else {
|
} else {
|
||||||
|
_value = valueFromColor(_color);
|
||||||
generatePixmap();
|
generatePixmap();
|
||||||
}
|
}
|
||||||
update();
|
update();
|
||||||
@ -480,7 +498,11 @@ float64 EditColorBox::Slider::valueFromColor(QColor color) const {
|
|||||||
? valueFromHue(color.hsvHue())
|
? valueFromHue(color.hsvHue())
|
||||||
: (_type == Type::Opacity)
|
: (_type == Type::Opacity)
|
||||||
? color.alphaF()
|
? color.alphaF()
|
||||||
: color.lightnessF();
|
: std::clamp(
|
||||||
|
((color.lightness() - _lightnessMin)
|
||||||
|
/ float64(_lightnessMax - _lightnessMin)),
|
||||||
|
0.,
|
||||||
|
1.);
|
||||||
}
|
}
|
||||||
|
|
||||||
float64 EditColorBox::Slider::valueFromHue(int hue) const {
|
float64 EditColorBox::Slider::valueFromHue(int hue) const {
|
||||||
@ -494,6 +516,15 @@ void EditColorBox::Slider::setAlpha(int alpha) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditColorBox::Slider::setLightnessLimits(int min, int max) {
|
||||||
|
Expects(max > min);
|
||||||
|
|
||||||
|
_lightnessMin = min;
|
||||||
|
_lightnessMax = max;
|
||||||
|
_color = applyLimits(_color);
|
||||||
|
colorUpdated();
|
||||||
|
}
|
||||||
|
|
||||||
void EditColorBox::Slider::updatePixmapFromMask() {
|
void EditColorBox::Slider::updatePixmapFromMask() {
|
||||||
_pixmap = App::pixmapFromImageInPlace(style::colorizeImage(_mask, _color));
|
_pixmap = App::pixmapFromImageInPlace(style::colorizeImage(_mask, _color));
|
||||||
}
|
}
|
||||||
@ -509,6 +540,19 @@ void EditColorBox::Slider::updateCurrentPoint(QPoint localPosition) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QColor EditColorBox::Slider::applyLimits(QColor color) const {
|
||||||
|
if (_type != Type::Lightness) {
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto lightness = color.lightness();
|
||||||
|
const auto clamped = std::clamp(lightness, _lightnessMin, _lightnessMax);
|
||||||
|
if (clamped == lightness) {
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
return QColor::fromHsl(color.hslHue(), color.hslSaturation(), clamped);
|
||||||
|
}
|
||||||
|
|
||||||
class EditColorBox::Field : public Ui::MaskedInputField {
|
class EditColorBox::Field : public Ui::MaskedInputField {
|
||||||
public:
|
public:
|
||||||
Field(QWidget *parent, const style::InputField &st, const QString &placeholder, int limit, const QString &units = QString());
|
Field(QWidget *parent, const style::InputField &st, const QString &placeholder, int limit, const QString &units = QString());
|
||||||
@ -736,7 +780,16 @@ EditColorBox::EditColorBox(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EditColorBox::setLightnessLimits(int min, int max) {
|
void EditColorBox::setLightnessLimits(int min, int max) {
|
||||||
|
Expects(_mode == Mode::HSL);
|
||||||
|
|
||||||
|
_lightnessMin = min;
|
||||||
|
_lightnessMax = max;
|
||||||
|
_lightnessSlider->setLightnessLimits(min, max);
|
||||||
|
|
||||||
|
const auto adjusted = applyLimits(_new);
|
||||||
|
if (_new != adjusted) {
|
||||||
|
updateFromColor(adjusted);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditColorBox::prepare() {
|
void EditColorBox::prepare() {
|
||||||
@ -937,12 +990,27 @@ EditColorBox::HSB EditColorBox::hsbFromControls() const {
|
|||||||
: qRound((1. - _picker->valueY()) * 255);
|
: qRound((1. - _picker->valueY()) * 255);
|
||||||
const auto brightness = (_mode == Mode::RGBA)
|
const auto brightness = (_mode == Mode::RGBA)
|
||||||
? qRound((1. - _picker->valueY()) * 255)
|
? qRound((1. - _picker->valueY()) * 255)
|
||||||
: qRound(_lightnessSlider->value() * 255);
|
: (_lightnessMin
|
||||||
|
+ qRound(_lightnessSlider->value()
|
||||||
|
* (_lightnessMax - _lightnessMin)));
|
||||||
return { hue, saturation, brightness };
|
return { hue, saturation, brightness };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QColor EditColorBox::applyLimits(QColor color) const {
|
||||||
|
if (_mode != Mode::HSL) {
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto lightness = color.lightness();
|
||||||
|
const auto clamped = std::clamp(lightness, _lightnessMin, _lightnessMax);
|
||||||
|
if (clamped == lightness) {
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
return QColor::fromHsl(color.hslHue(), color.hslSaturation(), clamped);
|
||||||
|
}
|
||||||
|
|
||||||
void EditColorBox::updateFromColor(QColor color) {
|
void EditColorBox::updateFromColor(QColor color) {
|
||||||
_new = color;
|
_new = applyLimits(color);
|
||||||
updateControlsFromColor();
|
updateControlsFromColor();
|
||||||
updateRGBFields();
|
updateRGBFields();
|
||||||
updateHSBFields();
|
updateHSBFields();
|
||||||
@ -961,10 +1029,13 @@ void EditColorBox::updateFromControls() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EditColorBox::updateFromHSBFields() {
|
void EditColorBox::updateFromHSBFields() {
|
||||||
auto hue = _hueField->value();
|
const auto hue = _hueField->value();
|
||||||
auto saturation = percentToByte(_saturationField->value());
|
const auto saturation = percentToByte(_saturationField->value());
|
||||||
auto brightness = percentToByte(_brightnessField->value());
|
const auto brightness = std::clamp(
|
||||||
auto alpha = _opacitySlider
|
percentToByte(_brightnessField->value()),
|
||||||
|
_lightnessMin,
|
||||||
|
_lightnessMax);
|
||||||
|
const auto alpha = _opacitySlider
|
||||||
? qRound(_opacitySlider->value() * 255)
|
? qRound(_opacitySlider->value() * 255)
|
||||||
: 255;
|
: 255;
|
||||||
setHSB({ hue, saturation, brightness }, alpha);
|
setHSB({ hue, saturation, brightness }, alpha);
|
||||||
@ -972,10 +1043,10 @@ void EditColorBox::updateFromHSBFields() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EditColorBox::updateFromRGBFields() {
|
void EditColorBox::updateFromRGBFields() {
|
||||||
auto red = _redField->value();
|
const auto red = _redField->value();
|
||||||
auto blue = _blueField->value();
|
const auto blue = _blueField->value();
|
||||||
auto green = _greenField->value();
|
const auto green = _greenField->value();
|
||||||
auto alpha = _opacitySlider
|
const auto alpha = _opacitySlider
|
||||||
? qRound(_opacitySlider->value() * 255)
|
? qRound(_opacitySlider->value() * 255)
|
||||||
: 255;
|
: 255;
|
||||||
setRGB(red, green, blue, alpha);
|
setRGB(red, green, blue, alpha);
|
||||||
@ -1051,7 +1122,7 @@ void EditColorBox::setHSB(HSB hsb, int alpha) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EditColorBox::setRGB(int red, int green, int blue, int alpha) {
|
void EditColorBox::setRGB(int red, int green, int blue, int alpha) {
|
||||||
_new.setRgb(red, green, blue, alpha);
|
_new = applyLimits(QColor(red, green, blue, alpha));
|
||||||
updateControlsFromColor();
|
updateControlsFromColor();
|
||||||
updateHSBFields();
|
updateHSBFields();
|
||||||
update();
|
update();
|
||||||
|
@ -63,6 +63,7 @@ private:
|
|||||||
void updateFromResultField();
|
void updateFromResultField();
|
||||||
void setHSB(HSB hsb, int alpha);
|
void setHSB(HSB hsb, int alpha);
|
||||||
void setRGB(int red, int green, int blue, int alpha);
|
void setRGB(int red, int green, int blue, int alpha);
|
||||||
|
[[nodiscard]] QColor applyLimits(QColor color) const;
|
||||||
|
|
||||||
int percentFromByte(int byte) {
|
int percentFromByte(int byte) {
|
||||||
return snap(qRound(byte * 100 / 255.), 0, 100);
|
return snap(qRound(byte * 100 / 255.), 0, 100);
|
||||||
@ -99,6 +100,9 @@ private:
|
|||||||
QRect _currentRect;
|
QRect _currentRect;
|
||||||
QRect _newRect;
|
QRect _newRect;
|
||||||
|
|
||||||
|
int _lightnessMin = 0;
|
||||||
|
int _lightnessMax = 255;
|
||||||
|
|
||||||
Fn<void(QColor)> _saveCallback;
|
Fn<void(QColor)> _saveCallback;
|
||||||
Fn<void()> _cancelCallback;
|
Fn<void()> _cancelCallback;
|
||||||
|
|
||||||
|
@ -199,16 +199,17 @@ void ColorsPalette::show(Type type) {
|
|||||||
const auto colorizer = Window::Theme::ColorizerFrom(
|
const auto colorizer = Window::Theme::ColorizerFrom(
|
||||||
*scheme,
|
*scheme,
|
||||||
scheme->accentColor);
|
scheme->accentColor);
|
||||||
const auto box = Ui::show(Box<EditColorBox>(
|
auto box = Box<EditColorBox>(
|
||||||
tr::lng_settings_theme_accent_title(tr::now),
|
tr::lng_settings_theme_accent_title(tr::now),
|
||||||
EditColorBox::Mode::HSL,
|
EditColorBox::Mode::HSL,
|
||||||
current));
|
current);
|
||||||
box->setLightnessLimits(
|
box->setLightnessLimits(
|
||||||
colorizer.lightnessMin,
|
colorizer.lightnessMin,
|
||||||
colorizer.lightnessMax);
|
colorizer.lightnessMax);
|
||||||
box->setSaveCallback(crl::guard(custom, [=](QColor result) {
|
box->setSaveCallback(crl::guard(custom, [=](QColor result) {
|
||||||
_selected.fire_copy(result);
|
_selected.fire_copy(result);
|
||||||
}));
|
}));
|
||||||
|
Ui::show(std::move(box));
|
||||||
}, custom->lifetime());
|
}, custom->lifetime());
|
||||||
pushButton(custom);
|
pushButton(custom);
|
||||||
inner->resize(_outer->width(), inner->height());
|
inner->resize(_outer->width(), inner->height());
|
||||||
|
Loading…
Reference in New Issue
Block a user