@@ -7,12 +7,15 @@ For license and copyright information please follow this link:
77*/
88#include " ui/chat/chat_theme.h"
99
10- #include " ui/image/image_prepare.h"
10+ #include " ui/color_contrast.h"
11+ #include " ui/emoji_config.h"
12+ #include " ui/painter.h"
1113#include " ui/power_saving.h"
1214#include " ui/ui_utility.h"
1315#include " ui/chat/message_bubble.h"
1416#include " ui/chat/chat_style.h"
15- #include " ui/color_contrast.h"
17+ #include " ui/image/image_prepare.h"
18+ #include " ui/text/text_custom_emoji.h"
1619#include " ui/style/style_core_palette.h"
1720#include " ui/style/style_palette_colorizer.h"
1821
@@ -53,6 +56,14 @@ constexpr auto kMinAcceptableContrast = 1.14;// 4.5;
5356 return (doubled % 2 ) ? 0.5 : 1 .;
5457}
5558
59+ [[nodiscard]] int RotationForSymbol (const QRectF &symbol) {
60+ const auto a = int (base::SafeRound (symbol.x () * 255 ));
61+ const auto b = int (base::SafeRound (symbol.y () * 255 ));
62+ const auto value = uint16 ((uint16 (a) << 8 ) | uint16 (b));
63+ const auto shuffled = uint16 (value << 5 ) | uint16 (value >> 3 );
64+ return (shuffled % 90 ) - 45 ;
65+ }
66+
5667[[nodiscard]] CacheBackgroundResult CacheBackgroundByRequest (
5768 const CacheBackgroundRequest &request) {
5869 Expects (!request.area .isEmpty ());
@@ -83,14 +94,17 @@ constexpr auto kMinAcceptableContrast = 1.14;// 4.5;
8394 QPainter p (&result);
8495 if (!gradient.isNull ()) {
8596 if (request.background .patternOpacity >= 0 .) {
86- p.setCompositionMode (QPainter::CompositionMode_SoftLight);
97+ p.setCompositionMode (
98+ QPainter::CompositionMode_SoftLight);
8799 p.setOpacity (request.background .patternOpacity );
88100 } else {
89101 p.setCompositionMode (
90102 QPainter::CompositionMode_DestinationIn);
91103 }
92104 }
93- const auto tiled = request.background .isPattern
105+ const auto hasGiftSymbols = request.background .isPattern
106+ && !request.background .giftSymbols .empty ();
107+ auto tiled = request.background .isPattern
94108 ? request.background .prepared .scaled (
95109 request.area .height () * ratio,
96110 request.area .height () * ratio,
@@ -99,6 +113,31 @@ constexpr auto kMinAcceptableContrast = 1.14;// 4.5;
99113 : request.background .preparedForTiled ;
100114 const auto w = tiled.width () / float (ratio);
101115 const auto h = tiled.height () / float (ratio);
116+
117+ const auto &giftSymbols = request.background .giftSymbols ;
118+ const auto &giftSymbolFrame = request.background .giftSymbolFrame ;
119+ const auto giftSymbolSize = giftSymbolFrame.size () / ratio;
120+ if (hasGiftSymbols) {
121+ auto q = QPainter (&tiled);
122+ auto hq = PainterHighQualityEnabler (q);
123+ q.setOpacity (0.8 );
124+ for (const auto &symbol : giftSymbols) {
125+ const auto rect = QRectF (
126+ symbol.x () * w,
127+ symbol.y () * h,
128+ symbol.width () * w,
129+ symbol.height () * h);
130+ q.save ();
131+ q.translate (rect.center ());
132+ q.scale (
133+ rect.width () / giftSymbolSize.width (),
134+ rect.height () / giftSymbolSize.height ());
135+ q.rotate (RotationForSymbol (symbol));
136+ q.translate (-rect.center ());
137+ q.drawImage (rect.topLeft (), giftSymbolFrame);
138+ q.restore ();
139+ }
140+ }
102141 const auto cx = int (std::ceil (request.area .width () / w));
103142 const auto cy = int (std::ceil (request.area .height () / h));
104143 const auto rows = cy;
@@ -111,7 +150,8 @@ constexpr auto kMinAcceptableContrast = 1.14;// 4.5;
111150 const auto useshift = xshift / float (ratio);
112151 for (auto y = 0 ; y != rows; ++y) {
113152 for (auto x = 0 ; x != cols; ++x) {
114- p.drawImage (QPointF (useshift + x * w, y * h), tiled);
153+ const auto position = QPointF (useshift + x * w, y * h);
154+ p.drawImage (position, tiled);
115155 }
116156 }
117157 if (!gradient.isNull ()
@@ -1093,7 +1133,7 @@ ChatThemeBackground PrepareBackgroundImage(
10931133 data.path ,
10941134 data.bytes ,
10951135 data.gzipSvg ,
1096- data.findGiftSymbols )
1136+ ! data.giftSymbolFrame . isNull () )
10971137 : BackgroundImageFields ();
10981138 auto prepared = needBackground
10991139 ? PreprocessBackgroundImage (std::move (read.image ))
@@ -1143,10 +1183,32 @@ ChatThemeBackground PrepareBackgroundImage(
11431183 : std::make_optional (data.colors .front ())),
11441184 .colors = data.colors ,
11451185 .giftSymbols = std::move (read.giftSymbols ),
1186+ .giftSymbolFrame = data.giftSymbolFrame ,
11461187 .patternOpacity = data.patternOpacity ,
11471188 .gradientRotation = data.generateGradient ? data.gradientRotation : 0 ,
11481189 .isPattern = data.isPattern ,
11491190 };
11501191}
11511192
1193+ [[nodiscard]] QImage PrepareGiftSymbol (
1194+ const std::unique_ptr<Text::CustomEmoji> &emoji) {
1195+ if (!emoji || !emoji->ready ()) {
1196+ return QImage ();
1197+ }
1198+ const auto ratio = style::DevicePixelRatio ();
1199+ const auto size = Ui::Emoji::GetSizeNormal () / ratio;
1200+ auto result = QImage (
1201+ 2 * QSize (size, size) * ratio,
1202+ QImage::Format_ARGB32_Premultiplied);
1203+ result.setDevicePixelRatio (ratio);
1204+ result.fill (Qt::transparent);
1205+ auto p = QPainter (&result);
1206+ const auto shift = (2 * size - (Ui::Emoji::GetSizeLarge () / ratio)) / 2 ;
1207+ emoji->paint (p, {
1208+ .textColor = QColor (0 , 0 , 0 ),
1209+ .position = QPoint (shift, shift),
1210+ });
1211+ return result;
1212+ }
1213+
11521214} // namespace Window::Theme
0 commit comments