From 10237a2d90c0a0b887e6e3f8cf344f15d69ac434 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 2 Sep 2025 17:28:38 +0400 Subject: [PATCH] Correct gift symbol sizes and rotations. --- Telegram/SourceFiles/ui/chat/chat_theme.cpp | 62 +++++++++++++-------- Telegram/SourceFiles/ui/chat/chat_theme.h | 13 +++-- 2 files changed, 49 insertions(+), 26 deletions(-) diff --git a/Telegram/SourceFiles/ui/chat/chat_theme.cpp b/Telegram/SourceFiles/ui/chat/chat_theme.cpp index 34c7aa367a..be462c8557 100644 --- a/Telegram/SourceFiles/ui/chat/chat_theme.cpp +++ b/Telegram/SourceFiles/ui/chat/chat_theme.cpp @@ -64,7 +64,8 @@ constexpr auto kMinAcceptableContrast = 1.14;// 4.5; return (shuffled % 60) - 30; } -[[nodiscard]] int ChooseGiftSymbolSkip(const std::vector &symbols) { +[[nodiscard]] int ChooseGiftSymbolSkip( + const std::vector &symbols) { if (symbols.empty()) { return -1; } @@ -72,10 +73,10 @@ constexpr auto kMinAcceptableContrast = 1.14;// 4.5; auto maxValue = 0.; for (auto i = 0, count = int(symbols.size()); i != count; ++i) { const auto &symbol = symbols[i]; - const auto center = symbol.center(); + const auto center = symbol.area.center(); const auto value = std::min(center.x(), 1. - center.x()) * std::min(center.y(), 1. - center.y()) - * std::min(symbol.width(), symbol.height()); + * std::min(symbol.area.width(), symbol.area.height()); if (maxIndex < 0 || maxValue < value) { maxIndex = i; maxValue = value; @@ -111,7 +112,7 @@ constexpr auto kMinAcceptableContrast = 1.14;// 4.5; Qt::SmoothTransformation); result.setDevicePixelRatio(ratio); auto giftArea = QRect(); - int giftRotation = 0; + float64 giftRotation = 0.; if (!request.background.prepared.isNull()) { QPainter p(&result); if (!gradient.isNull()) { @@ -148,15 +149,22 @@ constexpr auto kMinAcceptableContrast = 1.14;// 4.5; symbol.width() * w, symbol.height() * h); }; - const auto giftSymbolPaint = [&](QPainter &p, QRectF symbol) { - const auto rect = giftSymbolRect(symbol); + const auto giftSymbolPaint = [&]( + QPainter &p, + ChatThemeGiftSymbol symbol) { + const auto rect = giftSymbolRect(symbol.area); + + const auto esize = Ui::Emoji::GetSizeLarge() / ratio; + const auto custom = Ui::Text::AdjustCustomEmojiSize(esize); + const auto coef = rect.width() / float64(custom); + p.save(); p.translate(rect.center()); - p.scale( - rect.width() / giftSymbolSize.width(), - rect.height() / giftSymbolSize.height()); - p.rotate(RotationForSymbol(symbol)); + p.rotate(symbol.rotation); p.translate(-rect.center()); + p.translate(rect.topLeft()); + p.scale(coef, coef); + p.translate(-rect.topLeft()); p.drawImage(rect.topLeft(), giftSymbolFrame); p.restore(); }; @@ -193,13 +201,13 @@ constexpr auto kMinAcceptableContrast = 1.14;// 4.5; auto hq = PainterHighQualityEnabler(q); q.setOpacity(0.8); giftSymbolPaint(q, gift); - const auto exact = giftSymbolRect(gift); + const auto exact = giftSymbolRect(gift.area); giftArea = QRect( useshift + (cols / 2) * w + exact.x(), exact.y(), exact.width(), exact.height()); - giftRotation = RotationForSymbol(gift); + giftRotation = gift.rotation; } for (auto y = 0; y != rows; ++y) { @@ -1010,7 +1018,7 @@ QImage PrepareImageForTiled(const QImage &prepared) { return result; } -std::vector ParseGiftSymbols( +std::vector ParseGiftSymbols( const QByteArray &rects, QSize size, float64 scale) { @@ -1018,7 +1026,7 @@ std::vector ParseGiftSymbols( return {}; } - auto result = std::vector(); + auto result = std::vector(); auto offset = 0; const auto jumpPast = [&](const QByteArray &what) { const auto pos = rects.indexOf(what, offset); @@ -1028,8 +1036,8 @@ std::vector ParseGiftSymbols( offset = pos + what.size(); return true; }; - const auto takeDouble = [&](float64 &value) { - const auto end = rects.indexOf('"', offset); + const auto takeDouble = [&](float64 &value, char finish = '"') { + const auto end = rects.indexOf(finish, offset); if (end < 0) { return false; } @@ -1037,10 +1045,20 @@ std::vector ParseGiftSymbols( offset = end + 1; return true; }; + const auto maybeTakeRotation = [&](float64 &value) { + const auto end = rects.indexOf("/>"_q, offset); + const auto pos = rects.indexOf("rotate("_q, offset); + if (pos > offset && end > offset && pos < end) { + offset = pos + 7; + return takeDouble(value, ')'); + } + return true; + }; const auto cw = scale / float64(size.width()); const auto ch = scale / float64(size.height()); while (true) { auto x = float64(), y = float64(), w = float64(), h = float64(); + auto rotation = float64(); if (!jumpPast(" ParseGiftSymbols( || !takeDouble(w) || !jumpPast("height=\""_q) || !takeDouble(h) + || !maybeTakeRotation(rotation) || !jumpPast("/>"_q)) { break; } - result.push_back({ + result.push_back({ .area = { x * cw, y * ch, w * cw, h * ch, - }); + }, .rotation = rotation }); } return result; } @@ -1257,17 +1276,16 @@ ChatThemeBackground PrepareBackgroundImage( return QImage(); } const auto ratio = style::DevicePixelRatio(); - const auto size = Ui::Emoji::GetSizeNormal() / ratio; + const auto esize = Ui::Emoji::GetSizeLarge() / ratio; + const auto customSize = Ui::Text::AdjustCustomEmojiSize(esize); auto result = QImage( - 2 * QSize(size, size) * ratio, + QSize(customSize, customSize) * ratio, QImage::Format_ARGB32_Premultiplied); result.setDevicePixelRatio(ratio); result.fill(Qt::transparent); auto p = QPainter(&result); - const auto shift = (2 * size - (Ui::Emoji::GetSizeLarge() / ratio)) / 2; emoji->paint(p, { .textColor = QColor(0, 0, 0), - .position = QPoint(shift, shift), }); return result; } diff --git a/Telegram/SourceFiles/ui/chat/chat_theme.h b/Telegram/SourceFiles/ui/chat/chat_theme.h index 0426455780..5872613edf 100644 --- a/Telegram/SourceFiles/ui/chat/chat_theme.h +++ b/Telegram/SourceFiles/ui/chat/chat_theme.h @@ -26,6 +26,11 @@ class ChatStyle; struct ChatPaintContext; struct BubblePattern; +struct ChatThemeGiftSymbol { + QRectF area; + float64 rotation = 0.; +}; + struct ChatThemeBackground { QString key; QImage prepared; @@ -33,7 +38,7 @@ struct ChatThemeBackground { QImage gradientForFill; std::optional colorForFill; std::vector colors; - std::vector giftSymbols; + std::vector giftSymbols; QImage giftSymbolFrame; uint64_t giftId = 0; float64 patternOpacity = 1.; @@ -97,7 +102,7 @@ struct CacheBackgroundResult { int x = 0; int y = 0; QRect giftArea; - int giftRotation = 0; + float64 giftRotation = 0; bool waitingForNegativePattern = false; }; @@ -113,7 +118,7 @@ struct CachedBackground { int x = 0; int y = 0; QRect giftArea; - int giftRotation = 0; + float64 giftRotation = 0.; mutable std::unique_ptr gift; bool waitingForNegativePattern = false; }; @@ -256,7 +261,7 @@ struct ChatBackgroundRects { struct BackgroundImageFields { QImage image; - std::vector giftSymbols; + std::vector giftSymbols; }; [[nodiscard]] BackgroundImageFields ReadBackgroundImage( const QString &path,