1
0
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:
John Preston 2019-08-27 12:44:54 +03:00
parent 56a82600f8
commit 763bdf8798
3 changed files with 96 additions and 20 deletions

View File

@ -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();

View File

@ -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;

View File

@ -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());