data_wall_paper.cpp 22 KB

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