// This file is part of Desktop App Toolkit, // a set of libraries for developing nice desktop applications. // // For license and copyright information please follow this link: // https://github.com/desktop-app/legal/blob/master/LEGAL // #pragma once #include "base/basic_types.h" #include "base/weak_ptr.h" #include "lottie/lottie_common.h" #include #include #include #include #include namespace Lottie { // Frame rate can be 1, 2, ... , 29, 30 or 60. inline constexpr auto kNormalFrameRate = 30; inline constexpr auto kMaxFrameRate = 60; inline constexpr auto kMaxSize = 4096; inline constexpr auto kMaxFramesCount = 210; inline constexpr auto kFrameDisplayTimeAlreadyDone = std::numeric_limits::max(); inline constexpr auto kDisplayedInitial = crl::time(-1); class Player; class FrameProvider; struct FrameProviderToken; struct Frame { QImage original; crl::time displayed = kDisplayedInitial; crl::time display = kTimeUnknown; int index = 0; int sizeRounding = 0; FrameRequest request; QImage prepared; }; QImage PrepareFrameByRequest( not_null frame, bool useExistingPrepared); class SharedState { public: SharedState( std::shared_ptr provider, const FrameRequest &request); void start( not_null owner, crl::time now, crl::time delay = 0, int skippedFrames = 0); [[nodiscard]] Information information() const; [[nodiscard]] bool initialized() const; [[nodiscard]] not_null frameForPaint(); [[nodiscard]] int framesCount() const; [[nodiscard]] crl::time nextFrameDisplayTime() const; void addTimelineDelay(crl::time delayed, int skippedFrames = 0); void markFrameDisplayed(crl::time now); bool markFrameShown(); struct RenderResult { bool rendered = false; base::weak_ptr notify; }; [[nodiscard]] RenderResult renderNextFrame(const FrameRequest &request); ~SharedState(); private: void init(QImage cover, const FrameRequest &request); void renderNextFrame( not_null frame, const FrameRequest &request); [[nodiscard]] int sizeRounding() const; [[nodiscard]] crl::time countFrameDisplayTime(int index) const; [[nodiscard]] not_null getFrame(int index); [[nodiscard]] not_null getFrame(int index) const; [[nodiscard]] int counter() const; // crl::queue changes 0,2,4,6 to 1,3,5,7. // main thread changes 1,3,5,7 to 2,4,6,0. static constexpr auto kCounterUninitialized = -1; std::atomic _counter = kCounterUninitialized; static constexpr auto kFramesCount = 4; std::array _frames; base::weak_ptr _owner; crl::time _started = kTimeUnknown; // (_counter % 2) == 1 main thread can write _delay. // (_counter % 2) == 0 crl::queue can read _delay. crl::time _delay = kTimeUnknown; int _frameIndex = 0; int _framesCount = 0; int _skippedFrames = 0; const std::shared_ptr _provider; std::unique_ptr _token; }; class FrameRendererObject; class FrameRenderer final { public: static std::shared_ptr CreateIndependent(); static std::shared_ptr Instance(); void append( std::unique_ptr entry, const FrameRequest &request); void updateFrameRequest( not_null entry, const FrameRequest &request); void frameShown(); void remove(not_null state); private: using Implementation = FrameRendererObject; crl::object_on_queue _wrapped; }; } // namespace Lottie