stickers_emoji_image_loader.cpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  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 "chat_helpers/stickers_emoji_image_loader.h"
  8. #include "styles/style_chat.h"
  9. #include <QtCore/QtMath>
  10. namespace Stickers {
  11. EmojiImageLoader::EmojiImageLoader(crl::weak_on_queue<EmojiImageLoader> weak)
  12. : _weak(std::move(weak)) {
  13. }
  14. void EmojiImageLoader::init(
  15. std::shared_ptr<UniversalImages> images,
  16. bool largeEnabled) {
  17. Expects(images != nullptr);
  18. _images = std::move(images);
  19. if (largeEnabled) {
  20. _images->ensureLoaded();
  21. }
  22. }
  23. QImage EmojiImageLoader::prepare(EmojiPtr emoji) const {
  24. const auto loaded = _images->ensureLoaded();
  25. const auto factor = style::DevicePixelRatio();
  26. const auto side = st::largeEmojiSize + 2 * st::largeEmojiOutline;
  27. auto tinted = QImage(
  28. QSize(st::largeEmojiSize, st::largeEmojiSize) * factor,
  29. QImage::Format_ARGB32_Premultiplied);
  30. tinted.fill(Qt::white);
  31. if (loaded) {
  32. QPainter p(&tinted);
  33. p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
  34. _images->draw(
  35. p,
  36. emoji,
  37. st::largeEmojiSize * factor,
  38. 0,
  39. 0);
  40. }
  41. auto result = QImage(
  42. QSize(side, side) * factor,
  43. QImage::Format_ARGB32_Premultiplied);
  44. result.fill(Qt::transparent);
  45. if (loaded) {
  46. QPainter p(&result);
  47. const auto delta = st::largeEmojiOutline * factor;
  48. const auto planar = std::array<QPoint, 4>{ {
  49. { 0, -1 },
  50. { -1, 0 },
  51. { 1, 0 },
  52. { 0, 1 },
  53. } };
  54. for (const auto &shift : planar) {
  55. for (auto i = 0; i != delta; ++i) {
  56. p.drawImage(QPoint(delta, delta) + shift * (i + 1), tinted);
  57. }
  58. }
  59. const auto diagonal = std::array<QPoint, 4>{ {
  60. { -1, -1 },
  61. { 1, -1 },
  62. { -1, 1 },
  63. { 1, 1 },
  64. } };
  65. const auto corrected = int(base::SafeRound(delta / M_SQRT2));
  66. for (const auto &shift : diagonal) {
  67. for (auto i = 0; i != corrected; ++i) {
  68. p.drawImage(QPoint(delta, delta) + shift * (i + 1), tinted);
  69. }
  70. }
  71. _images->draw(
  72. p,
  73. emoji,
  74. st::largeEmojiSize * factor,
  75. delta,
  76. delta);
  77. }
  78. return result;
  79. }
  80. void EmojiImageLoader::switchTo(std::shared_ptr<UniversalImages> images) {
  81. _images = std::move(images);
  82. }
  83. auto EmojiImageLoader::releaseImages() -> std::shared_ptr<UniversalImages> {
  84. return std::exchange(
  85. _images,
  86. std::make_shared<UniversalImages>(_images->id()));
  87. }
  88. } // namespace Stickers