1 /*
2 This file is part of Telegram Desktop,
3 the official desktop application for the Telegram messaging service.
4
5 For license and copyright information please follow this link:
6 https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
7 */
8 #include "data/data_wall_paper.h"
9
10 #include "data/data_document.h"
11 #include "data/data_file_origin.h"
12 #include "data/data_session.h"
13 #include "storage/serialize_common.h"
14 #include "ui/chat/chat_theme.h"
15 #include "core/application.h"
16 #include "main/main_session.h"
17
18 namespace Data {
19 namespace {
20
FromLegacyBackgroundId(int32 legacyId)21 constexpr auto FromLegacyBackgroundId(int32 legacyId) -> WallPaperId {
22 return uint64(0xFFFFFFFF00000000ULL) | uint64(uint32(legacyId));
23 }
24
25 constexpr auto kUninitializedBackground = FromLegacyBackgroundId(-999);
26 constexpr auto kTestingThemeBackground = FromLegacyBackgroundId(-666);
27 constexpr auto kTestingDefaultBackground = FromLegacyBackgroundId(-665);
28 constexpr auto kTestingEditorBackground = FromLegacyBackgroundId(-664);
29 constexpr auto kThemeBackground = FromLegacyBackgroundId(-2);
30 constexpr auto kCustomBackground = FromLegacyBackgroundId(-1);
31 constexpr auto kLegacy1DefaultBackground = FromLegacyBackgroundId(0);
32 constexpr auto kLegacy2DefaultBackground = 5947530738516623361;
33 constexpr auto kLegacy3DefaultBackground = 5778236420632084488;
34 constexpr auto kLegacy4DefaultBackground = 5945087215657811969;
35 constexpr auto kDefaultBackground = 5933856211186221059;
36 constexpr auto kIncorrectDefaultBackground = FromLegacyBackgroundId(105);
37
38 constexpr auto kVersionTag = qint32(0x7FFFFFFF);
39 constexpr auto kVersion = 1;
40
SerializeColor(const QColor & color)41 [[nodiscard]] quint32 SerializeColor(const QColor &color) {
42 return (quint32(std::clamp(color.red(), 0, 255)) << 16)
43 | (quint32(std::clamp(color.green(), 0, 255)) << 8)
44 | quint32(std::clamp(color.blue(), 0, 255));
45 }
46
SerializeMaybeColor(std::optional<QColor> color)47 [[nodiscard]] quint32 SerializeMaybeColor(std::optional<QColor> color) {
48 return color ? SerializeColor(*color) : quint32(-1);
49 }
50
ColorsFromMTP(const MTPDwallPaperSettings & data)51 [[nodiscard]] std::vector<QColor> ColorsFromMTP(
52 const MTPDwallPaperSettings &data) {
53 auto result = std::vector<QColor>();
54 const auto c1 = MaybeColorFromSerialized(data.vbackground_color());
55 if (!c1) {
56 return result;
57 }
58 result.reserve(4);
59 result.push_back(*c1);
60 const auto c2 = MaybeColorFromSerialized(data.vsecond_background_color());
61 if (!c2) {
62 return result;
63 }
64 result.push_back(*c2);
65 const auto c3 = MaybeColorFromSerialized(data.vthird_background_color());
66 if (!c3) {
67 return result;
68 }
69 result.push_back(*c3);
70 const auto c4 = MaybeColorFromSerialized(data.vfourth_background_color());
71 if (!c4) {
72 return result;
73 }
74 result.push_back(*c4);
75 return result;
76 }
77
ColorFromString(QStringView string)78 [[nodiscard]] std::optional<QColor> ColorFromString(QStringView string) {
79 if (string.size() != 6) {
80 return {};
81 } else if (ranges::any_of(string, [](QChar ch) {
82 return (ch < 'a' || ch > 'f')
83 && (ch < 'A' || ch > 'F')
84 && (ch < '0' || ch > '9');
85 })) {
86 return {};
87 }
88 const auto component = [](QStringView text, int index) {
89 const auto decimal = [](QChar hex) {
90 const auto code = hex.unicode();
91 return (code >= '0' && code <= '9')
92 ? int(code - '0')
93 : (code >= 'a' && code <= 'f')
94 ? int(code - 'a' + 0x0a)
95 : int(code - 'A' + 0x0a);
96 };
97 index *= 2;
98 return decimal(text[index]) * 0x10 + decimal(text[index + 1]);
99 };
100 return QColor(
101 component(string, 0),
102 component(string, 1),
103 component(string, 2),
104 255);
105 }
106
ColorsFromString(const QString & string)107 [[nodiscard]] std::vector<QColor> ColorsFromString(const QString &string) {
108 constexpr auto kMaxColors = 4;
109 const auto view = QStringView(string);
110 const auto count = int(view.size() / 6);
111 if (!count || count > kMaxColors || view.size() != count * 7 - 1) {
112 return {};
113 }
114 auto result = std::vector<QColor>();
115 result.reserve(count);
116 for (auto i = 0; i != count; ++i) {
117 if (i + 1 < count
118 && view[i * 7 + 6] != '~'
119 && (count > 2 || view[i * 7 + 6] != '-')) {
120 return {};
121 } else if (const auto parsed = ColorFromString(view.mid(i * 7, 6))) {
122 result.push_back(*parsed);
123 } else {
124 return {};
125 }
126 }
127 return result;
128 }
129
StringFromColor(QColor color)130 [[nodiscard]] QString StringFromColor(QColor color) {
131 const auto component = [](int value) {
132 const auto hex = [](int value) {
133 value = std::clamp(value, 0, 15);
134 return (value > 9)
135 ? ('a' + (value - 10))
136 : ('0' + value);
137 };
138 return QString() + hex(value / 16) + hex(value % 16);
139 };
140 return component(color.red())
141 + component(color.green())
142 + component(color.blue());
143 }
144
StringFromColors(const std::vector<QColor> & colors)145 [[nodiscard]] QString StringFromColors(const std::vector<QColor> &colors) {
146 Expects(!colors.empty());
147
148 auto strings = QStringList();
149 strings.reserve(colors.size());
150 for (const auto &color : colors) {
151 strings.push_back(StringFromColor(color));
152 }
153 const auto separator = (colors.size() > 2) ? '~' : '-';
154 return strings.join(separator);
155 }
156
RawFromLegacyFlags(qint32 legacyFlags)157 [[nodiscard]] qint32 RawFromLegacyFlags(qint32 legacyFlags) {
158 using Flag = WallPaperFlag;
159 return ((legacyFlags & (1 << 0)) ? qint32(Flag::Creator) : 0)
160 | ((legacyFlags & (1 << 1)) ? qint32(Flag::Default) : 0)
161 | ((legacyFlags & (1 << 3)) ? qint32(Flag::Pattern) : 0)
162 | ((legacyFlags & (1 << 4)) ? qint32(Flag::Dark) : 0);
163 }
164
165 } // namespace
166
WallPaper(WallPaperId id)167 WallPaper::WallPaper(WallPaperId id) : _id(id) {
168 }
169
setLocalImageAsThumbnail(std::shared_ptr<Image> image)170 void WallPaper::setLocalImageAsThumbnail(std::shared_ptr<Image> image) {
171 Expects(IsDefaultWallPaper(*this)
172 || IsLegacy1DefaultWallPaper(*this)
173 || IsCustomWallPaper(*this));
174 Expects(_thumbnail == nullptr);
175
176 _thumbnail = std::move(image);
177 }
178
id() const179 WallPaperId WallPaper::id() const {
180 return _id;
181 }
182
backgroundColors() const183 const std::vector<QColor> WallPaper::backgroundColors() const {
184 return _backgroundColors;
185 }
186
document() const187 DocumentData *WallPaper::document() const {
188 return _document;
189 }
190
localThumbnail() const191 Image *WallPaper::localThumbnail() const {
192 return _thumbnail.get();
193 }
194
isPattern() const195 bool WallPaper::isPattern() const {
196 return _flags & WallPaperFlag::Pattern;
197 }
198
isDefault() const199 bool WallPaper::isDefault() const {
200 return _flags & WallPaperFlag::Default;
201 }
202
isCreator() const203 bool WallPaper::isCreator() const {
204 return _flags & WallPaperFlag::Creator;
205 }
206
isDark() const207 bool WallPaper::isDark() const {
208 return _flags & WallPaperFlag::Dark;
209 }
210
isLocal() const211 bool WallPaper::isLocal() const {
212 return !document() && _thumbnail;
213 }
214
isBlurred() const215 bool WallPaper::isBlurred() const {
216 return _blurred;
217 }
218
patternIntensity() const219 int WallPaper::patternIntensity() const {
220 return _intensity;
221 }
222
patternOpacity() const223 float64 WallPaper::patternOpacity() const {
224 return _intensity / 100.;
225 }
226
gradientRotation() const227 int WallPaper::gradientRotation() const {
228 // In case of complex gradients rotation value is dynamic.
229 return (_backgroundColors.size() < 3) ? _rotation : 0;
230 }
231
hasShareUrl() const232 bool WallPaper::hasShareUrl() const {
233 return !_slug.isEmpty();
234 }
235
shareUrl(not_null<Main::Session * > session) const236 QString WallPaper::shareUrl(not_null<Main::Session*> session) const {
237 if (!hasShareUrl()) {
238 return QString();
239 }
240 const auto base = session->createInternalLinkFull("bg/" + _slug);
241 auto params = QStringList();
242 if (isPattern()) {
243 if (!backgroundColors().empty()) {
244 params.push_back(
245 "bg_color=" + StringFromColors(backgroundColors()));
246 }
247 if (_intensity) {
248 params.push_back("intensity=" + QString::number(_intensity));
249 }
250 }
251 if (_rotation && backgroundColors().size() == 2) {
252 params.push_back("rotation=" + QString::number(_rotation));
253 }
254 auto mode = QStringList();
255 if (_blurred) {
256 mode.push_back("blur");
257 }
258 if (!mode.isEmpty()) {
259 params.push_back("mode=" + mode.join('+'));
260 }
261 return params.isEmpty()
262 ? base
263 : base + '?' + params.join('&');
264 }
265
loadDocumentThumbnail() const266 void WallPaper::loadDocumentThumbnail() const {
267 if (_document) {
268 _document->loadThumbnail(fileOrigin());
269 }
270 }
271
loadDocument() const272 void WallPaper::loadDocument() const {
273 if (_document) {
274 _document->save(fileOrigin(), QString());
275 }
276 }
277
fileOrigin() const278 FileOrigin WallPaper::fileOrigin() const {
279 return FileOriginWallpaper(_id, _accessHash, _ownerId, _slug);
280 }
281
ownerId() const282 UserId WallPaper::ownerId() const {
283 return _ownerId;
284 }
285
mtpInput(not_null<Main::Session * > session) const286 MTPInputWallPaper WallPaper::mtpInput(not_null<Main::Session*> session) const {
287 return (_ownerId && _ownerId != session->userId() && !_slug.isEmpty())
288 ? MTP_inputWallPaperSlug(MTP_string(_slug))
289 : MTP_inputWallPaper(MTP_long(_id), MTP_long(_accessHash));
290 }
291
mtpSettings() const292 MTPWallPaperSettings WallPaper::mtpSettings() const {
293 const auto serializeForIndex = [&](int index) {
294 return (_backgroundColors.size() > index)
295 ? MTP_int(SerializeColor(_backgroundColors[index]))
296 : MTP_int(0);
297 };
298 using Flag = MTPDwallPaperSettings::Flag;
299 const auto flagForIndex = [&](int index) {
300 return (_backgroundColors.size() <= index)
301 ? Flag(0)
302 : (index == 0)
303 ? Flag::f_background_color
304 : (index == 1)
305 ? Flag::f_second_background_color
306 : (index == 2)
307 ? Flag::f_third_background_color
308 : Flag::f_fourth_background_color;
309 };
310 return MTP_wallPaperSettings(
311 MTP_flags((_blurred ? Flag::f_blur : Flag(0))
312 | flagForIndex(0)
313 | flagForIndex(1)
314 | flagForIndex(2)
315 | flagForIndex(3)),
316 serializeForIndex(0),
317 serializeForIndex(1),
318 serializeForIndex(2),
319 serializeForIndex(3),
320 MTP_int(_intensity),
321 MTP_int(_rotation));
322 }
323
withUrlParams(const QMap<QString,QString> & params) const324 WallPaper WallPaper::withUrlParams(
325 const QMap<QString, QString> ¶ms) const {
326 auto result = *this;
327 result._blurred = false;
328 result._backgroundColors = ColorsFromString(_slug);
329 result._intensity = kDefaultIntensity;
330 if (auto mode = params.value("mode"); !mode.isEmpty()) {
331 const auto list = mode.replace('+', ' ').split(' ');
332 for (const auto &change : list) {
333 if (change == qstr("blur")) {
334 result._blurred = true;
335 }
336 }
337 }
338 if (result._backgroundColors.empty()) {
339 result._backgroundColors = ColorsFromString(params.value("bg_color"));
340 }
341 if (result._backgroundColors.empty()) {
342 result._backgroundColors = ColorsFromString(params.value("gradient"));
343 }
344 if (result._backgroundColors.empty()) {
345 result._backgroundColors = ColorsFromString(params.value("color"));
346 }
347 if (result._backgroundColors.empty()) {
348 result._backgroundColors = ColorsFromString(params.value("slug"));
349 }
350 if (const auto string = params.value("intensity"); !string.isEmpty()) {
351 auto ok = false;
352 const auto intensity = string.toInt(&ok);
353 if (ok && base::in_range(intensity, -100, 101)) {
354 result._intensity = intensity;
355 }
356 }
357 result._rotation = params.value("rotation").toInt();
358 result._rotation = (std::clamp(result._rotation, 0, 315) / 45) * 45;
359
360 return result;
361 }
362
withBlurred(bool blurred) const363 WallPaper WallPaper::withBlurred(bool blurred) const {
364 auto result = *this;
365 result._blurred = blurred;
366 return result;
367 }
368
withPatternIntensity(int intensity) const369 WallPaper WallPaper::withPatternIntensity(int intensity) const {
370 auto result = *this;
371 result._intensity = intensity;
372 return result;
373 }
374
withGradientRotation(int rotation) const375 WallPaper WallPaper::withGradientRotation(int rotation) const {
376 auto result = *this;
377 result._rotation = rotation;
378 return result;
379 }
380
withBackgroundColors(std::vector<QColor> colors) const381 WallPaper WallPaper::withBackgroundColors(std::vector<QColor> colors) const {
382 auto result = *this;
383 result._backgroundColors = std::move(colors);
384 if (!ColorsFromString(_slug).empty()) {
385 result._slug = StringFromColors(result._backgroundColors);
386 }
387 return result;
388 }
389
withParamsFrom(const WallPaper & other) const390 WallPaper WallPaper::withParamsFrom(const WallPaper &other) const {
391 auto result = *this;
392 result._blurred = other._blurred;
393 if (!other._backgroundColors.empty()) {
394 result._backgroundColors = other._backgroundColors;
395 if (!ColorsFromString(_slug).empty()) {
396 result._slug = StringFromColors(result._backgroundColors);
397 }
398 }
399 result._intensity = other._intensity;
400 if (other.isPattern()) {
401 result._flags |= WallPaperFlag::Pattern;
402 }
403 return result;
404 }
405
withoutImageData() const406 WallPaper WallPaper::withoutImageData() const {
407 auto result = *this;
408 result._thumbnail = nullptr;
409 return result;
410 }
411
Create(not_null<Main::Session * > session,const MTPWallPaper & data)412 std::optional<WallPaper> WallPaper::Create(
413 not_null<Main::Session*> session,
414 const MTPWallPaper &data) {
415 return data.match([&](const MTPDwallPaper &data) {
416 return Create(session, data);
417 }, [](const MTPDwallPaperNoFile &data) {
418 return Create(data);
419 });
420 }
421
Create(not_null<Main::Session * > session,const MTPDwallPaper & data)422 std::optional<WallPaper> WallPaper::Create(
423 not_null<Main::Session*> session,
424 const MTPDwallPaper &data) {
425 const auto document = session->data().processDocument(
426 data.vdocument());
427 if (!document->checkWallPaperProperties()) {
428 return std::nullopt;
429 }
430 auto result = WallPaper(data.vid().v);
431 result._accessHash = data.vaccess_hash().v;
432 result._ownerId = session->userId();
433 result._flags = (data.is_dark() ? WallPaperFlag::Dark : WallPaperFlag(0))
434 | (data.is_pattern() ? WallPaperFlag::Pattern : WallPaperFlag(0))
435 | (data.is_default() ? WallPaperFlag::Default : WallPaperFlag(0))
436 | (data.is_creator() ? WallPaperFlag::Creator : WallPaperFlag(0));
437 result._slug = qs(data.vslug());
438 result._document = document;
439 if (const auto settings = data.vsettings()) {
440 settings->match([&](const MTPDwallPaperSettings &data) {
441 result._blurred = data.is_blur();
442 if (result.isPattern()) {
443 result._backgroundColors = ColorsFromMTP(data);
444 if (const auto intensity = data.vintensity()) {
445 result._intensity = intensity->v;
446 }
447 if (const auto rotation = data.vrotation()) {
448 result._rotation = rotation->v;
449 }
450 }
451 });
452 }
453 return result;
454 }
455
Create(const MTPDwallPaperNoFile & data)456 std::optional<WallPaper> WallPaper::Create(const MTPDwallPaperNoFile &data) {
457 auto result = WallPaper(data.vid().v);
458 result._flags = (data.is_dark() ? WallPaperFlag::Dark : WallPaperFlag(0))
459 | (data.is_default() ? WallPaperFlag::Default : WallPaperFlag(0));
460 result._blurred = false;
461 result._backgroundColors.clear();
462 if (const auto settings = data.vsettings()) {
463 settings->match([&](const MTPDwallPaperSettings &data) {
464 result._blurred = data.is_blur();
465 result._backgroundColors = ColorsFromMTP(data);
466 if (const auto rotation = data.vrotation()) {
467 result._rotation = rotation->v;
468 }
469 });
470 }
471 return result;
472 }
473
serialize() const474 QByteArray WallPaper::serialize() const {
475 auto size = sizeof(quint64) // _id
476 + sizeof(quint64) // _accessHash
477 + sizeof(qint32) // version tag
478 + sizeof(qint32) // version
479 + sizeof(qint32) // _flags
480 + Serialize::stringSize(_slug)
481 + sizeof(qint32) // _settings
482 + sizeof(qint32) // _backgroundColors.size()
483 + (_backgroundColors.size() * sizeof(quint32)) // _backgroundColors
484 + sizeof(qint32) // _intensity
485 + sizeof(qint32) // _rotation
486 + sizeof(quint64); // ownerId
487
488 auto result = QByteArray();
489 result.reserve(size);
490 {
491 auto stream = QDataStream(&result, QIODevice::WriteOnly);
492 stream.setVersion(QDataStream::Qt_5_1);
493 stream
494 << quint64(_id)
495 << quint64(_accessHash)
496 << qint32(kVersionTag)
497 << qint32(kVersion)
498 << qint32(_flags)
499 << _slug
500 << qint32(_blurred ? 1 : 0)
501 << qint32(_backgroundColors.size());
502 for (const auto &color : _backgroundColors) {
503 stream << SerializeMaybeColor(color);
504 }
505 stream
506 << qint32(_intensity)
507 << qint32(_rotation)
508 << quint64(_ownerId.bare);
509 }
510 return result;
511 }
512
FromSerialized(const QByteArray & serialized)513 std::optional<WallPaper> WallPaper::FromSerialized(
514 const QByteArray &serialized) {
515 if (serialized.isEmpty()) {
516 return std::nullopt;
517 }
518
519 auto id = quint64();
520 auto accessHash = quint64();
521 auto versionTag = qint32();
522 auto version = qint32(0);
523
524 auto stream = QDataStream(serialized);
525 stream.setVersion(QDataStream::Qt_5_1);
526 stream
527 >> id
528 >> accessHash
529 >> versionTag;
530
531 auto flags = qint32();
532 auto ownerId = UserId();
533 auto slug = QString();
534 auto blurred = qint32();
535 auto backgroundColors = std::vector<QColor>();
536 auto intensity = qint32();
537 auto rotation = qint32();
538 if (versionTag == kVersionTag) {
539 auto bareOwnerId = quint64();
540 auto backgroundColorsCount = qint32();
541 stream
542 >> version
543 >> flags
544 >> slug
545 >> blurred
546 >> backgroundColorsCount;
547 if (backgroundColorsCount < 0 || backgroundColorsCount > 4) {
548 return std::nullopt;
549 }
550 backgroundColors.reserve(backgroundColorsCount);
551 for (auto i = 0; i != backgroundColorsCount; ++i) {
552 auto serialized = quint32();
553 stream >> serialized;
554 const auto color = MaybeColorFromSerialized(serialized);
555 if (!color) {
556 return std::nullopt;
557 }
558 backgroundColors.push_back(*color);
559 }
560 stream
561 >> intensity
562 >> rotation
563 >> bareOwnerId;
564 ownerId = UserId(BareId(bareOwnerId));
565 } else {
566 auto settings = qint32();
567 auto backgroundColor = quint32();
568 stream
569 >> slug
570 >> settings
571 >> backgroundColor
572 >> intensity;
573 if (!stream.atEnd()) {
574 auto field1 = qint32();
575 auto field2 = qint32();
576 stream >> field1;
577 if (!stream.atEnd()) {
578 stream >> field2;
579 }
580 ownerId = UserId(
581 BareId(uint32(field1)) | (BareId(uint32(field2)) << 32));
582 }
583 flags = RawFromLegacyFlags(versionTag);
584 blurred = (settings & qint32(1U << 1)) ? 1 : 0;
585 if (const auto color = MaybeColorFromSerialized(backgroundColor)) {
586 backgroundColors.push_back(*color);
587 }
588 }
589 if (stream.status() != QDataStream::Ok) {
590 return std::nullopt;
591 } else if (intensity < -100 || intensity > 100) {
592 return std::nullopt;
593 }
594 auto result = WallPaper(id);
595 result._accessHash = accessHash;
596 result._ownerId = ownerId;
597 result._flags = WallPaperFlags::from_raw(flags);
598 result._slug = slug;
599 result._blurred = (blurred == 1);
600 result._backgroundColors = std::move(backgroundColors);
601 result._intensity = intensity;
602 result._rotation = rotation;
603 return result;
604 }
605
FromLegacySerialized(quint64 id,quint64 accessHash,quint32 flags,QString slug)606 std::optional<WallPaper> WallPaper::FromLegacySerialized(
607 quint64 id,
608 quint64 accessHash,
609 quint32 flags,
610 QString slug) {
611 auto result = WallPaper(id);
612 result._accessHash = accessHash;
613 result._flags = WallPaperFlags::from_raw(RawFromLegacyFlags(flags));
614 result._slug = slug;
615 if (const auto color = ColorFromString(slug)) {
616 result._backgroundColors.push_back(*color);
617 }
618 return result;
619 }
620
FromLegacyId(qint32 legacyId)621 std::optional<WallPaper> WallPaper::FromLegacyId(qint32 legacyId) {
622 auto result = WallPaper(FromLegacyBackgroundId(legacyId));
623 if (!IsCustomWallPaper(result)) {
624 result._flags = WallPaperFlag::Default;
625 }
626 return result;
627 }
628
FromColorsSlug(const QString & slug)629 std::optional<WallPaper> WallPaper::FromColorsSlug(const QString &slug) {
630 auto colors = ColorsFromString(slug);
631 if (colors.empty()) {
632 return std::nullopt;
633 }
634 auto result = CustomWallPaper();
635 result._slug = slug;
636 result._backgroundColors = std::move(colors);
637 return result;
638 }
639
ConstructDefault()640 WallPaper WallPaper::ConstructDefault() {
641 auto result = WallPaper(
642 kDefaultBackground
643 ).withPatternIntensity(50).withBackgroundColors({
644 QColor(219, 221, 187),
645 QColor(107, 165, 135),
646 QColor(213, 216, 141),
647 QColor(136, 184, 132),
648 });
649 result._flags |= WallPaperFlag::Default | WallPaperFlag::Pattern;
650 return result;
651 }
652
ThemeWallPaper()653 WallPaper ThemeWallPaper() {
654 return WallPaper(kThemeBackground);
655 }
656
IsThemeWallPaper(const WallPaper & paper)657 bool IsThemeWallPaper(const WallPaper &paper) {
658 return (paper.id() == kThemeBackground);
659 }
660
CustomWallPaper()661 WallPaper CustomWallPaper() {
662 return WallPaper(kCustomBackground);
663 }
664
IsCustomWallPaper(const WallPaper & paper)665 bool IsCustomWallPaper(const WallPaper &paper) {
666 return (paper.id() == kCustomBackground);
667 }
668
Legacy1DefaultWallPaper()669 WallPaper Legacy1DefaultWallPaper() {
670 return WallPaper(kLegacy1DefaultBackground);
671 }
672
IsLegacy1DefaultWallPaper(const WallPaper & paper)673 bool IsLegacy1DefaultWallPaper(const WallPaper &paper) {
674 return (paper.id() == kLegacy1DefaultBackground);
675 }
676
IsLegacy2DefaultWallPaper(const WallPaper & paper)677 bool IsLegacy2DefaultWallPaper(const WallPaper &paper) {
678 return (paper.id() == kLegacy2DefaultBackground)
679 || (paper.id() == kIncorrectDefaultBackground);
680 }
681
IsLegacy3DefaultWallPaper(const WallPaper & paper)682 bool IsLegacy3DefaultWallPaper(const WallPaper &paper) {
683 return (paper.id() == kLegacy3DefaultBackground);
684 }
685
IsLegacy4DefaultWallPaper(const WallPaper & paper)686 bool IsLegacy4DefaultWallPaper(const WallPaper &paper) {
687 return (paper.id() == kLegacy4DefaultBackground);
688 }
689
DefaultWallPaper()690 WallPaper DefaultWallPaper() {
691 return WallPaper::ConstructDefault();
692 }
693
IsDefaultWallPaper(const WallPaper & paper)694 bool IsDefaultWallPaper(const WallPaper &paper) {
695 return (paper.id() == kDefaultBackground);
696 }
697
IsCloudWallPaper(const WallPaper & paper)698 bool IsCloudWallPaper(const WallPaper &paper) {
699 return (paper.id() != kIncorrectDefaultBackground)
700 && !IsThemeWallPaper(paper)
701 && !IsCustomWallPaper(paper)
702 && !IsLegacy1DefaultWallPaper(paper)
703 && !details::IsUninitializedWallPaper(paper)
704 && !details::IsTestingThemeWallPaper(paper)
705 && !details::IsTestingDefaultWallPaper(paper)
706 && !details::IsTestingEditorWallPaper(paper);
707 }
708
GenerateDitheredGradient(const Data::WallPaper & paper)709 QImage GenerateDitheredGradient(const Data::WallPaper &paper) {
710 return Ui::GenerateDitheredGradient(
711 paper.backgroundColors(),
712 paper.gradientRotation());
713 }
714
ColorFromSerialized(quint32 serialized)715 QColor ColorFromSerialized(quint32 serialized) {
716 return QColor(
717 int((serialized >> 16) & 0xFFU),
718 int((serialized >> 8) & 0xFFU),
719 int(serialized & 0xFFU));
720 }
721
ColorFromSerialized(MTPint serialized)722 QColor ColorFromSerialized(MTPint serialized) {
723 return ColorFromSerialized(serialized.v);
724 }
725
MaybeColorFromSerialized(quint32 serialized)726 std::optional<QColor> MaybeColorFromSerialized(
727 quint32 serialized) {
728 return (serialized == quint32(-1))
729 ? std::nullopt
730 : std::make_optional(ColorFromSerialized(serialized));
731 }
732
MaybeColorFromSerialized(const tl::conditional<MTPint> & mtp)733 std::optional<QColor> MaybeColorFromSerialized(
734 const tl::conditional<MTPint> &mtp) {
735 return mtp ? std::make_optional(ColorFromSerialized(*mtp)) : std::nullopt;
736 }
737
738 namespace details {
739
UninitializedWallPaper()740 WallPaper UninitializedWallPaper() {
741 return WallPaper(kUninitializedBackground);
742 }
743
IsUninitializedWallPaper(const WallPaper & paper)744 bool IsUninitializedWallPaper(const WallPaper &paper) {
745 return (paper.id() == kUninitializedBackground);
746 }
747
TestingThemeWallPaper()748 WallPaper TestingThemeWallPaper() {
749 return WallPaper(kTestingThemeBackground);
750 }
751
IsTestingThemeWallPaper(const WallPaper & paper)752 bool IsTestingThemeWallPaper(const WallPaper &paper) {
753 return (paper.id() == kTestingThemeBackground);
754 }
755
TestingDefaultWallPaper()756 WallPaper TestingDefaultWallPaper() {
757 return WallPaper(
758 kTestingDefaultBackground
759 ).withParamsFrom(DefaultWallPaper());
760 }
761
IsTestingDefaultWallPaper(const WallPaper & paper)762 bool IsTestingDefaultWallPaper(const WallPaper &paper) {
763 return (paper.id() == kTestingDefaultBackground);
764 }
765
TestingEditorWallPaper()766 WallPaper TestingEditorWallPaper() {
767 return WallPaper(kTestingEditorBackground);
768 }
769
IsTestingEditorWallPaper(const WallPaper & paper)770 bool IsTestingEditorWallPaper(const WallPaper &paper) {
771 return (paper.id() == kTestingEditorBackground);
772 }
773
774 } // namespace details
775 } // namespace Data
776