Moved out pattern points draw for unique gifts to separated class.

This commit is contained in:
23rd
2025-10-09 14:44:58 +03:00
parent 0a114bbe4a
commit eeb0b62bfa
8 changed files with 215 additions and 172 deletions
@@ -12,7 +12,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/event_filter.h"
#include "base/unixtime.h"
#include "boxes/peer_list_box.h"
#include "boxes/star_gift_box.h"
#include "data/stickers/data_custom_emoji.h"
#include "data/data_premium_limits.h"
#include "data/data_channel.h"
@@ -36,6 +35,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/empty_userpic.h"
#include "ui/dynamic_image.h"
#include "ui/painter.h"
#include "ui/top_background_gradient.h"
#include "styles/style_boxes.h"
#include "styles/style_credits.h"
#include "styles/style_premium.h"
@@ -895,9 +895,9 @@ public:
auto p = QPainter(&_backgroundCache);
p.setClipRect(inner);
const auto skip = inner.width() / 3;
Ui::PaintPoints(
Ui::PaintBgPoints(
p,
Ui::PatternPointsSmall(),
Ui::PatternBgPointsSmall(),
_patternCache,
_patternEmoji.get(),
*_unique,
+4 -144
View File
@@ -572,38 +572,6 @@ auto GenerateGiftMedia(
};
}
void PrepareImage(
QImage &image,
not_null<Text::CustomEmoji*> emoji,
const PatternPoint &point,
const Data::UniqueGift &gift) {
if (!image.isNull() || !emoji->ready()) {
return;
}
const auto ratio = style::DevicePixelRatio();
const auto size = Emoji::GetSizeNormal() / ratio;
image = QImage(
2 * QSize(size, size) * ratio,
QImage::Format_ARGB32_Premultiplied);
image.setDevicePixelRatio(ratio);
image.fill(Qt::transparent);
auto p = QPainter(&image);
auto hq = PainterHighQualityEnabler(p);
p.setOpacity(point.opacity);
if (point.scale < 1.) {
p.translate(size, size);
p.scale(point.scale, point.scale);
p.translate(-size, -size);
}
const auto shift = (2 * size - (Emoji::GetSizeLarge() / ratio)) / 2;
emoji->paint(p, {
.textColor = gift.backdrop.patternColor,
.position = QPoint(shift, shift),
});
}
PreviewWrap::PreviewWrap(
not_null<QWidget*> parent,
not_null<PeerData*> recipient,
@@ -3894,9 +3862,9 @@ void AddUniqueGiftCover(
}
p.drawImage(0, 0, gift.gradient);
PaintPoints(
Ui::PaintBgPoints(
p,
PatternPoints(),
Ui::PatternBgPoints(),
gift.emojis,
gift.emoji.get(),
*gift.gift,
@@ -4007,9 +3975,9 @@ void AddWearGiftCover(
}
p.drawImage(0, 0, state->gradient);
PaintPoints(
Ui::PaintBgPoints(
p,
PatternPoints(),
Ui::PatternBgPoints(),
state->emojis,
state->emoji.get(),
state->gift,
@@ -5042,119 +5010,11 @@ void UpgradeBox(
AddUniqueCloseButton(box, {});
}
const std::vector<PatternPoint> &PatternPoints() {
static const auto kSmall = 0.7;
static const auto kFaded = 0.2;
static const auto kLarge = 0.85;
static const auto kOpaque = 0.3;
static const auto result = std::vector<PatternPoint>{
{ { 0.5, 0.066 }, kSmall, kFaded },
{ { 0.177, 0.168 }, kSmall, kFaded },
{ { 0.822, 0.168 }, kSmall, kFaded },
{ { 0.37, 0.168 }, kLarge, kOpaque },
{ { 0.63, 0.168 }, kLarge, kOpaque },
{ { 0.277, 0.308 }, kSmall, kOpaque },
{ { 0.723, 0.308 }, kSmall, kOpaque },
{ { 0.13, 0.42 }, kSmall, kFaded },
{ { 0.87, 0.42 }, kSmall, kFaded },
{ { 0.27, 0.533 }, kLarge, kOpaque },
{ { 0.73, 0.533 }, kLarge, kOpaque },
{ { 0.2, 0.73 }, kSmall, kFaded },
{ { 0.8, 0.73 }, kSmall, kFaded },
{ { 0.302, 0.825 }, kLarge, kOpaque },
{ { 0.698, 0.825 }, kLarge, kOpaque },
{ { 0.5, 0.876 }, kLarge, kFaded },
{ { 0.144, 0.936 }, kSmall, kFaded },
{ { 0.856, 0.936 }, kSmall, kFaded },
};
return result;
}
const std::vector<PatternPoint> &PatternPointsSmall() {
static const auto kSmall = 0.45;
static const auto kFaded = 0.2;
static const auto kLarge = 0.55;
static const auto kOpaque = 0.3;
static const auto result = std::vector<PatternPoint>{
{ { 0.5, 0.066 }, kSmall, kFaded },
{ { 0.177, 0.168 }, kSmall, kFaded },
{ { 0.822, 0.168 }, kSmall, kFaded },
{ { 0.37, 0.168 }, kLarge, kOpaque },
{ { 0.63, 0.168 }, kLarge, kOpaque },
{ { 0.277, 0.308 }, kSmall, kOpaque },
{ { 0.723, 0.308 }, kSmall, kOpaque },
{ { 0.13, 0.42 }, kSmall, kFaded },
{ { 0.87, 0.42 }, kSmall, kFaded },
{ { 0.27, 0.533 }, kLarge, kOpaque },
{ { 0.73, 0.533 }, kLarge, kOpaque },
{ { 0.2, 0.73 }, kSmall, kFaded },
{ { 0.8, 0.73 }, kSmall, kFaded },
{ { 0.302, 0.825 }, kLarge, kOpaque },
{ { 0.698, 0.825 }, kLarge, kOpaque },
{ { 0.5, 0.876 }, kLarge, kFaded },
{ { 0.144, 0.936 }, kSmall, kFaded },
{ { 0.856, 0.936 }, kSmall, kFaded },
};
return result;
}
void PaintPoints(
QPainter &p,
const std::vector<PatternPoint> &points,
base::flat_map<float64, QImage> &cache,
not_null<Text::CustomEmoji*> emoji,
const Data::UniqueGift &gift,
const QRect &rect,
float64 shown) {
const auto origin = rect.topLeft();
const auto width = rect.width();
const auto height = rect.height();
const auto ratio = style::DevicePixelRatio();
const auto paintPoint = [&](const PatternPoint &point) {
const auto key = (1. + point.opacity) * 10. + point.scale;
auto &image = cache[key];
PrepareImage(image, emoji, point, gift);
if (!image.isNull()) {
const auto position = origin + QPoint(
int(point.position.x() * width),
int(point.position.y() * height));
if (shown < 1.) {
p.save();
p.translate(position);
p.scale(shown, shown);
p.translate(-position);
}
const auto size = image.size() / ratio;
p.drawImage(
position - QPoint(size.width() / 2, size.height() / 2),
image);
if (shown < 1.) {
p.restore();
}
}
};
for (const auto &point : points) {
paintPoint(point);
}
}
void ShowStarGiftUpgradeBox(StarGiftUpgradeArgs &&args) {
const auto weak = base::make_weak(args.controller);
@@ -87,23 +87,6 @@ void ShowUniqueGiftSellBox(
void GiftReleasedByHandler(not_null<PeerData*> peer);
struct PatternPoint {
QPointF position;
float64 scale = 1.;
float64 opacity = 1.;
};
[[nodiscard]] const std::vector<PatternPoint> &PatternPoints();
[[nodiscard]] const std::vector<PatternPoint> &PatternPointsSmall();
void PaintPoints(
QPainter &p,
const std::vector<PatternPoint> &points,
base::flat_map<float64, QImage> &cache,
not_null<Text::CustomEmoji*> emoji,
const Data::UniqueGift &gift,
const QRect &rect,
float64 shown = 1.);
struct StarGiftUpgradeArgs {
not_null<Window::SessionController*> controller;
base::required<uint64> stargiftId;
@@ -9,7 +9,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h"
#include "boxes/background_preview_box.h"
#include "boxes/star_gift_box.h"
#include "history/history.h"
#include "history/history_item.h"
#include "history/view/history_view_element.h"
@@ -35,6 +34,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/chat/chat_theme.h"
#include "ui/cached_round_corners.h"
#include "ui/painter.h"
#include "ui/top_background_gradient.h"
#include "ui/ui_utility.h"
#include "window/section_widget.h"
#include "window/window_session_controller.h"
@@ -707,9 +707,9 @@ void GiftThemeBox::cacheUniqueBackground(int width, int height) {
auto p = QPainter(&_backgroundCache);
p.setClipRect(inner);
const auto skip = inner.width() / 3;
Ui::PaintPoints(
Ui::PaintBgPoints(
p,
Ui::PatternPointsSmall(),
Ui::PatternBgPointsSmall(),
_patternCache,
_patternEmoji.get(),
*_data.unique,
@@ -33,6 +33,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/painter.h"
#include "ui/power_saving.h"
#include "ui/rect.h"
#include "ui/top_background_gradient.h"
#include "window/window_session_controller.h"
#include "styles/style_chat.h"
#include "styles/style_credits.h"
@@ -476,9 +477,9 @@ auto UniqueGiftBg(
const auto top = (webpreview ? 2 : 1) * (-shift);
const auto outer = QRect(-shift, top, doubled, doubled);
p.setClipRect(inner);
Ui::PaintPoints(
Ui::PaintBgPoints(
p,
Ui::PatternPoints(),
Ui::PatternBgPoints(),
state->cache,
state->pattern.get(),
*gift,
@@ -11,7 +11,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_premium.h"
#include "base/unixtime.h"
#include "boxes/send_credits_box.h" // SetButtonMarkedLabel
#include "boxes/star_gift_box.h"
#include "boxes/sticker_set_box.h"
#include "chat_helpers/stickers_gift_box_pack.h"
#include "chat_helpers/stickers_lottie.h"
@@ -36,6 +35,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/dynamic_thumbnails.h"
#include "ui/effects/premium_graphics.h"
#include "ui/painter.h"
#include "ui/top_background_gradient.h"
#include "window/window_session_controller.h"
#include "styles/style_chat.h"
#include "styles/style_credits.h"
@@ -620,9 +620,9 @@ void GiftButton::cacheUniqueBackground(
auto p = QPainter(&_uniqueBackgroundCache);
p.setClipRect(inner);
const auto skip = inner.width() / 3;
Ui::PaintPoints(
Ui::PaintBgPoints(
p,
Ui::PatternPointsSmall(),
Ui::PatternBgPointsSmall(),
_uniquePatternCache,
_uniquePatternEmoji.get(),
*unique,
@@ -11,11 +11,47 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_credits.h"
#include "data/data_peer.h"
#include "data/data_star_gift.h"
#include "data/stickers/data_custom_emoji.h"
#include "ui/image/image_prepare.h"
#include "ui/painter.h"
#include "ui/text/custom_emoji_helper.h"
#include "styles/style_layers.h"
#include "styles/style_chat_helpers.h"
namespace Ui {
namespace {
void PrepareImage(
QImage &image,
not_null<Ui::Text::CustomEmoji*> emoji,
const PatternPoint &point,
const QColor &patternColor) {
if (!image.isNull() || !emoji->ready()) {
return;
}
const auto ratio = style::DevicePixelRatio();
const auto size = Emoji::GetSizeNormal() / ratio;
image = QImage(
2 * QSize(size, size) * ratio,
QImage::Format_ARGB32_Premultiplied);
image.setDevicePixelRatio(ratio);
image.fill(Qt::transparent);
auto p = QPainter(&image);
auto hq = PainterHighQualityEnabler(p);
p.setOpacity(point.opacity);
if (point.scale < 1.) {
p.translate(size, size);
p.scale(point.scale, point.scale);
p.translate(-size, -size);
}
const auto shift = (2 * size - (Emoji::GetSizeLarge() / ratio)) / 2;
emoji->paint(p, {
.textColor = patternColor,
.position = QPoint(shift, shift),
});
}
} // namespace
QImage CreateTopBgGradient(
QSize size,
@@ -66,4 +102,136 @@ QImage CreateTopBgGradient(QSize size, not_null<PeerData*> peer) {
}
}
const std::vector<PatternPoint> &PatternBgPoints() {
static const auto kSmall = 0.7;
static const auto kFaded = 0.2;
static const auto kLarge = 0.85;
static const auto kOpaque = 0.3;
static const auto result = std::vector<PatternPoint>{
{ { 0.5, 0.066 }, kSmall, kFaded },
{ { 0.177, 0.168 }, kSmall, kFaded },
{ { 0.822, 0.168 }, kSmall, kFaded },
{ { 0.37, 0.168 }, kLarge, kOpaque },
{ { 0.63, 0.168 }, kLarge, kOpaque },
{ { 0.277, 0.308 }, kSmall, kOpaque },
{ { 0.723, 0.308 }, kSmall, kOpaque },
{ { 0.13, 0.42 }, kSmall, kFaded },
{ { 0.87, 0.42 }, kSmall, kFaded },
{ { 0.27, 0.533 }, kLarge, kOpaque },
{ { 0.73, 0.533 }, kLarge, kOpaque },
{ { 0.2, 0.73 }, kSmall, kFaded },
{ { 0.8, 0.73 }, kSmall, kFaded },
{ { 0.302, 0.825 }, kLarge, kOpaque },
{ { 0.698, 0.825 }, kLarge, kOpaque },
{ { 0.5, 0.876 }, kLarge, kFaded },
{ { 0.144, 0.936 }, kSmall, kFaded },
{ { 0.856, 0.936 }, kSmall, kFaded },
};
return result;
}
const std::vector<PatternPoint> &PatternBgPointsSmall() {
static const auto kSmall = 0.45;
static const auto kFaded = 0.2;
static const auto kLarge = 0.55;
static const auto kOpaque = 0.3;
static const auto result = std::vector<PatternPoint>{
{ { 0.5, 0.066 }, kSmall, kFaded },
{ { 0.177, 0.168 }, kSmall, kFaded },
{ { 0.822, 0.168 }, kSmall, kFaded },
{ { 0.37, 0.168 }, kLarge, kOpaque },
{ { 0.63, 0.168 }, kLarge, kOpaque },
{ { 0.277, 0.308 }, kSmall, kOpaque },
{ { 0.723, 0.308 }, kSmall, kOpaque },
{ { 0.13, 0.42 }, kSmall, kFaded },
{ { 0.87, 0.42 }, kSmall, kFaded },
{ { 0.27, 0.533 }, kLarge, kOpaque },
{ { 0.73, 0.533 }, kLarge, kOpaque },
{ { 0.2, 0.73 }, kSmall, kFaded },
{ { 0.8, 0.73 }, kSmall, kFaded },
{ { 0.302, 0.825 }, kLarge, kOpaque },
{ { 0.698, 0.825 }, kLarge, kOpaque },
{ { 0.5, 0.876 }, kLarge, kFaded },
{ { 0.144, 0.936 }, kSmall, kFaded },
{ { 0.856, 0.936 }, kSmall, kFaded },
};
return result;
}
void PaintBgPoints(
QPainter &p,
const std::vector<PatternPoint> &points,
base::flat_map<float64, QImage> &cache,
not_null<Ui::Text::CustomEmoji*> emoji,
const Data::UniqueGift &gift,
const QRect &rect,
float64 shown) {
PaintBgPoints(
p,
points,
cache,
emoji,
gift.backdrop.patternColor,
rect,
shown);
}
void PaintBgPoints(
QPainter &p,
const std::vector<PatternPoint> &points,
base::flat_map<float64, QImage> &cache,
not_null<Ui::Text::CustomEmoji*> emoji,
const QColor &patternColor,
const QRect &rect,
float64 shown) {
const auto origin = rect.topLeft();
const auto width = rect.width();
const auto height = rect.height();
const auto ratio = style::DevicePixelRatio();
const auto paintPoint = [&](const PatternPoint &point) {
const auto key = (1. + point.opacity) * 10. + point.scale;
auto &image = cache[key];
PrepareImage(image, emoji, point, patternColor);
if (!image.isNull()) {
const auto position = origin + QPoint(
int(point.position.x() * width),
int(point.position.y() * height));
if (shown < 1.) {
p.save();
p.translate(position);
p.scale(shown, shown);
p.translate(-position);
}
const auto size = image.size() / ratio;
p.drawImage(
position - QPoint(size.width() / 2, size.height() / 2),
image);
if (shown < 1.) {
p.restore();
}
}
};
for (const auto &point : points) {
paintPoint(point);
}
}
} // namespace Ui
@@ -11,10 +11,20 @@ namespace Data {
struct UniqueGift;
} // namespace Data
namespace Ui::Text {
class CustomEmoji;
} // namespace Ui::Text
class PeerData;
namespace Ui {
struct PatternPoint {
QPointF position;
float64 scale = 1.;
float64 opacity = 1.;
};
[[nodiscard]] QImage CreateTopBgGradient(
QSize size,
const Data::UniqueGift &gift);
@@ -29,4 +39,25 @@ namespace Ui {
QSize size,
not_null<PeerData*> peer);
[[nodiscard]] const std::vector<PatternPoint> &PatternBgPoints();
[[nodiscard]] const std::vector<PatternPoint> &PatternBgPointsSmall();
void PaintBgPoints(
QPainter &p,
const std::vector<PatternPoint> &points,
base::flat_map<float64, QImage> &cache,
not_null<Ui::Text::CustomEmoji*> emoji,
const Data::UniqueGift &gift,
const QRect &rect,
float64 shown = 1.);
void PaintBgPoints(
QPainter &p,
const std::vector<PatternPoint> &points,
base::flat_map<float64, QImage> &cache,
not_null<Ui::Text::CustomEmoji*> emoji,
const QColor &patternColor,
const QRect &rect,
float64 shown);
} // namespace Ui