lottie_frame_generator.cpp 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. // This file is part of Desktop App Toolkit,
  2. // a set of libraries for developing nice desktop applications.
  3. //
  4. // For license and copyright information please follow this link:
  5. // https://github.com/desktop-app/legal/blob/master/LEGAL
  6. //
  7. #include "lottie/lottie_frame_generator.h"
  8. #include "lottie/lottie_common.h"
  9. #include "ui/image/image_prepare.h"
  10. #include <rlottie.h>
  11. namespace Lottie {
  12. FrameGenerator::FrameGenerator(const QByteArray &bytes)
  13. : _rlottie(
  14. rlottie::Animation::loadFromData(
  15. ReadUtf8(Images::UnpackGzip(bytes)),
  16. std::string(),
  17. std::string(),
  18. false)) {
  19. if (_rlottie) {
  20. const auto rate = _rlottie->frameRate();
  21. _multiplier = (rate == 60) ? 2 : 1;
  22. auto width = size_t();
  23. auto height = size_t();
  24. _rlottie->size(width, height);
  25. _size = QSize(width, height);
  26. _framesCount = (_rlottie->totalFrame() + _multiplier - 1)
  27. / _multiplier;
  28. _frameDuration = (rate > 0) ? (1000 * _multiplier / rate) : 0;
  29. }
  30. if (!_framesCount || !_frameDuration || _size.isEmpty()) {
  31. _rlottie = nullptr;
  32. _framesCount = _frameDuration = 0;
  33. _size = QSize();
  34. }
  35. }
  36. FrameGenerator::~FrameGenerator() = default;
  37. int FrameGenerator::count() {
  38. return _framesCount;
  39. }
  40. double FrameGenerator::rate() {
  41. return _rlottie ? (_rlottie->frameRate() / _multiplier) : 0.;
  42. }
  43. FrameGenerator::Frame FrameGenerator::renderNext(
  44. QImage storage,
  45. QSize size,
  46. Qt::AspectRatioMode mode) {
  47. if (!_framesCount || _frameIndex == _framesCount) {
  48. return {};
  49. }
  50. ++_frameIndex;
  51. return renderCurrent(std::move(storage), size, mode);
  52. }
  53. FrameGenerator::Frame FrameGenerator::renderCurrent(
  54. QImage storage,
  55. QSize size,
  56. Qt::AspectRatioMode mode) {
  57. Expects(_frameIndex > 0);
  58. const auto index = _frameIndex - 1;
  59. if (storage.format() != kImageFormat
  60. || storage.size() != size) {
  61. storage = CreateFrameStorage(size);
  62. }
  63. storage.fill(Qt::transparent);
  64. const auto scaled = _size.scaled(size, mode);
  65. const auto render = QSize(
  66. std::max(scaled.width(), size.width()),
  67. std::max(scaled.height(), size.height()));
  68. const auto xskip = (size.width() - render.width()) / 2;
  69. const auto yskip = (size.height() - render.height());
  70. const auto skip = (yskip * storage.bytesPerLine() / 4) + xskip;
  71. auto surface = rlottie::Surface(
  72. reinterpret_cast<uint32_t*>(storage.bits()) + skip,
  73. render.width(),
  74. render.height(),
  75. storage.bytesPerLine());
  76. _rlottie->renderSync(index * _multiplier, std::move(surface));
  77. return {
  78. .duration = _frameDuration,
  79. .image = std::move(storage),
  80. .last = (_frameIndex == _framesCount),
  81. };
  82. }
  83. void FrameGenerator::jumpToStart() {
  84. _frameIndex = 0;
  85. }
  86. } // namespace Lottie