From 58cf0fa2b1fe674d1feed2c18120adbbd83235ef Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 29 Jan 2019 20:03:51 +0300 Subject: [PATCH] Display date in background preview. --- Telegram/SourceFiles/boxes/background_box.cpp | 34 ++++- Telegram/SourceFiles/boxes/background_box.h | 3 + .../SourceFiles/history/history_widget.cpp | 2 +- .../window/themes/window_theme.cpp | 116 +++++++++++++----- .../SourceFiles/window/themes/window_theme.h | 2 + 5 files changed, 121 insertions(+), 36 deletions(-) diff --git a/Telegram/SourceFiles/boxes/background_box.cpp b/Telegram/SourceFiles/boxes/background_box.cpp index ca211aec1..82ee69217 100644 --- a/Telegram/SourceFiles/boxes/background_box.cpp +++ b/Telegram/SourceFiles/boxes/background_box.cpp @@ -154,7 +154,8 @@ QImage PrepareScaledFromFull( std::move(result), Data::PatternColor(*patternBackground)); } - return result; + return std::move(result).convertToFormat( + QImage::Format_ARGB32_Premultiplied); } } // namespace @@ -380,6 +381,7 @@ void BackgroundPreviewBox::prepare() { if (_paper.hasShareUrl()) { addLeftButton(langFactory(lng_background_share), [=] { share(); }); } + updateServiceBg(_paper.backgroundColor()); _paper.loadThumbnail(); _paper.loadDocument(); @@ -493,12 +495,33 @@ void BackgroundPreviewBox::paintTexts(Painter &p, TimeMs ms) { - height2 - st::historyPaddingBottom; p.translate(0, top); + paintDate(p); _text1->draw(p, rect(), TextSelection(), ms); p.translate(0, height1); _text2->draw(p, rect(), TextSelection(), ms); p.translate(0, height2); } +void BackgroundPreviewBox::paintDate(Painter &p) { + const auto date = _text1->Get(); + if (!date || !_serviceBg) { + return; + } + const auto text = date->text; + const auto bubbleHeight = st::msgServicePadding.top() + st::msgServiceFont->height + st::msgServicePadding.bottom(); + const auto bubbleTop = st::msgServiceMargin.top(); + const auto textWidth = st::msgServiceFont->width(text); + const auto bubbleWidth = st::msgServicePadding.left() + textWidth + st::msgServicePadding.right(); + const auto bubbleLeft = (width() - bubbleWidth) / 2; + const auto radius = bubbleHeight / 2; + p.setPen(Qt::NoPen); + p.setBrush(*_serviceBg); + p.drawRoundedRect(bubbleLeft, bubbleTop, bubbleWidth, bubbleHeight, radius, radius); + p.setPen(st::msgServiceFg); + p.setFont(st::msgServiceFont); + p.drawText(bubbleLeft + st::msgServicePadding.left(), bubbleTop + st::msgServicePadding.top() + st::msgServiceFont->ascent, text); +} + void BackgroundPreviewBox::step_radial(TimeMs ms, bool timer) { Expects(_paper.document() != nullptr); @@ -531,9 +554,18 @@ bool BackgroundPreviewBox::setScaledFromThumb() { } void BackgroundPreviewBox::setScaledFromImage(QImage &&image) { + updateServiceBg(Window::Theme::CountAverageColor(image)); _scaled = App::pixmapFromImageInPlace(std::move(image)); } +void BackgroundPreviewBox::updateServiceBg(std::optional background) { + if (background) { + _serviceBg = Window::Theme::AdjustedColor( + st::msgServiceBg->c, + *background); + } +} + std::optional BackgroundPreviewBox::patternBackgroundColor() const { return _paper.isPattern() ? _paper.backgroundColor() : std::nullopt; } diff --git a/Telegram/SourceFiles/boxes/background_box.h b/Telegram/SourceFiles/boxes/background_box.h index 44d7156d0..46ecb45b6 100644 --- a/Telegram/SourceFiles/boxes/background_box.h +++ b/Telegram/SourceFiles/boxes/background_box.h @@ -70,10 +70,12 @@ private: void checkLoadedDocument(); bool setScaledFromThumb(); void setScaledFromImage(QImage &&image); + void updateServiceBg(std::optional background); std::optional patternBackgroundColor() const; void paintImage(Painter &p); void paintRadial(Painter &p, TimeMs ms); void paintTexts(Painter &p, TimeMs ms); + void paintDate(Painter &p); AdminLog::OwnedItem _text1; AdminLog::OwnedItem _text2; @@ -82,5 +84,6 @@ private: QPixmap _scaled; Ui::RadialAnimation _radial; base::binary_guard _generating; + std::optional _serviceBg; }; diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 84ae4c5f2..5f3b9cccd 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -6361,7 +6361,7 @@ void HistoryWidget::drawField(Painter &p, const QRect &rect) { if (drawWebPagePreview) { auto previewLeft = st::historyReplySkip + st::webPageLeft; p.fillRect(st::historyReplySkip, backy + st::msgReplyPadding.top(), st::webPageBar, st::msgReplyBarSize.height(), st::msgInReplyBarColor); - if ((_previewData->photo && !_previewData->photo->isNull()) || (_previewData->document && _previewData->document->hasThumbnail())) { + if ((_previewData->photo && !_previewData->photo->isNull()) || (_previewData->document && _previewData->document->hasThumbnail() && !_previewData->document->isPatternWallPaper())) { const auto preview = _previewData->photo ? _previewData->photo->getReplyPreview(Data::FileOrigin()) : _previewData->document->getReplyPreview(Data::FileOrigin()); diff --git a/Telegram/SourceFiles/window/themes/window_theme.cpp b/Telegram/SourceFiles/window/themes/window_theme.cpp index 4f0b8109d..088ea91d8 100644 --- a/Telegram/SourceFiles/window/themes/window_theme.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme.cpp @@ -104,6 +104,21 @@ std::optional ColorFromString(const QString &string) { 255); } +QString StringFromColor(QColor color) { + const auto component = [](int value) { + const auto hex = [](int value) { + value = std::clamp(value, 0, 15); + return (value > 9) + ? ('a' + (value - 10)) + : ('0' + value); + }; + return QString() + hex(value / 16) + hex(value % 16); + }; + return component(color.red()) + + component(color.green()) + + component(color.blue()); +} + } // namespace WallPaper::WallPaper(WallPaperId id) : _id(id) { @@ -155,9 +170,32 @@ bool WallPaper::hasShareUrl() const { } QString WallPaper::shareUrl() const { - return hasShareUrl() - ? Core::App().createInternalLinkFull("bg/" + _slug) - : QString(); + if (!hasShareUrl()) { + return QString(); + } + const auto base = Core::App().createInternalLinkFull("bg/" + _slug); + auto params = QStringList(); + if (isPattern()) { + if (_backgroundColor) { + params.push_back("bg_color=" + StringFromColor(*_backgroundColor)); + } + if (_intensity) { + params.push_back("intensity=" + QString::number(_intensity)); + } + } + auto mode = QStringList(); + if (_settings & MTPDwallPaperSettings::Flag::f_blur) { + mode.push_back("blur"); + } + if (_settings & MTPDwallPaperSettings::Flag::f_motion) { + mode.push_back("motion"); + } + if (!mode.isEmpty()) { + params.push_back("mode=" + mode.join('+')); + } + return params.isEmpty() + ? base + : base + '?' + params.join('&'); } void WallPaper::loadThumbnail() const { @@ -815,12 +853,6 @@ QImage validateBackgroundImage(QImage image) { return image; } -void adjustColor(style::color color, float64 hue, float64 saturation) { - auto original = color->c; - original.setHslF(hue, saturation, original.lightnessF(), original.alphaF()); - color.set(original.red(), original.green(), original.blue(), original.alpha()); -} - void WriteAppliedTheme() { auto saved = Saved(); saved.pathRelative = GlobalApplying.pathRelative; @@ -1029,34 +1061,18 @@ bool ChatBackground::adjustPaletteRequired() { } void ChatBackground::adjustPaletteUsingBackground(const QImage &image) { - uint64 components[3] = { 0 }; - uint64 componentsScroll[3] = { 0 }; - const auto w = image.width(); - const auto h = image.height(); - const auto size = w * h; - if (const auto pix = image.constBits()) { - for (auto i = 0, l = size * 4; i != l; i += 4) { - components[2] += pix[i + 0]; - components[1] += pix[i + 1]; - components[0] += pix[i + 2]; - } - } - - if (size) { - for (auto i = 0; i != 3; ++i) { - components[i] /= size; - } - } - - adjustPaletteUsingColor( - QColor(components[0], components[1], components[2])); + adjustPaletteUsingColor(CountAverageColor(image)); } void ChatBackground::adjustPaletteUsingColor(QColor color) { - const auto hue = color.hslHueF(); - const auto saturation = color.hslSaturationF(); - for (const auto &color : _adjustableColors) { - adjustColor(color.item, hue, saturation); + const auto prepared = color.toHsl(); + for (const auto &adjustable : _adjustableColors) { + const auto adjusted = AdjustedColor(adjustable.item->c, prepared); + adjustable.item.set( + adjusted.red(), + adjusted.green(), + adjusted.blue(), + adjusted.alpha()); } } @@ -1530,6 +1546,38 @@ bool IsPaletteTestingPath(const QString &path) { return false; } +QColor CountAverageColor(const QImage &image) { + Expects(image.format() == QImage::Format_ARGB32_Premultiplied); + + uint64 components[3] = { 0 }; + uint64 componentsScroll[3] = { 0 }; + const auto w = image.width(); + const auto h = image.height(); + const auto size = w * h; + if (const auto pix = image.constBits()) { + for (auto i = 0, l = size * 4; i != l; i += 4) { + components[2] += pix[i + 0]; + components[1] += pix[i + 1]; + components[0] += pix[i + 2]; + } + } + if (size) { + for (auto i = 0; i != 3; ++i) { + components[i] /= size; + } + } + return QColor(components[0], components[1], components[2]); +} + +QColor AdjustedColor(QColor original, QColor background) { + return QColor::fromHslF( + background.hslHueF(), + background.hslSaturationF(), + original.lightnessF(), + original.alphaF() + ).toRgb(); +} + void ComputeBackgroundRects(QRect wholeFill, QSize imageSize, QRect &to, QRect &from) { if (uint64(imageSize.width()) * wholeFill.height() > uint64(imageSize.height()) * wholeFill.width()) { float64 pxsize = wholeFill.height() / float64(imageSize.height()); diff --git a/Telegram/SourceFiles/window/themes/window_theme.h b/Telegram/SourceFiles/window/themes/window_theme.h index fe3553ef1..e8c555948 100644 --- a/Telegram/SourceFiles/window/themes/window_theme.h +++ b/Telegram/SourceFiles/window/themes/window_theme.h @@ -153,6 +153,8 @@ void Revert(); bool LoadFromFile(const QString &file, Instance *out, QByteArray *outContent); bool IsPaletteTestingPath(const QString &path); +QColor CountAverageColor(const QImage &image); +QColor AdjustedColor(QColor original, QColor background); struct BackgroundUpdate { enum class Type {