mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Support custom emoji in IsolatedEmoji.
This commit is contained in:
parent
9b941bae97
commit
edfb7bb65a
10 changed files with 183 additions and 62 deletions
|
@ -150,22 +150,25 @@ auto EmojiPack::stickerForEmoji(EmojiPtr emoji) -> Sticker {
|
||||||
return { i->second.get(), nullptr };
|
return { i->second.get(), nullptr };
|
||||||
}
|
}
|
||||||
if (!emoji->colored()) {
|
if (!emoji->colored()) {
|
||||||
return Sticker();
|
return {};
|
||||||
}
|
}
|
||||||
const auto j = _map.find(emoji->original());
|
const auto j = _map.find(emoji->original());
|
||||||
if (j != end(_map)) {
|
if (j != end(_map)) {
|
||||||
const auto index = emoji->variantIndex(emoji);
|
const auto index = emoji->variantIndex(emoji);
|
||||||
return { j->second.get(), ColorReplacements(index) };
|
return { j->second.get(), ColorReplacements(index) };
|
||||||
}
|
}
|
||||||
return Sticker();
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto EmojiPack::stickerForEmoji(const IsolatedEmoji &emoji) -> Sticker {
|
auto EmojiPack::stickerForEmoji(const IsolatedEmoji &emoji) -> Sticker {
|
||||||
Expects(!emoji.empty());
|
Expects(!emoji.empty());
|
||||||
|
|
||||||
return (emoji.items[1] != nullptr)
|
if (!v::is_null(emoji.items[1])) {
|
||||||
? Sticker()
|
return {};
|
||||||
: stickerForEmoji(emoji.items[0]);
|
} else if (const auto regular = std::get_if<EmojiPtr>(&emoji.items[0])) {
|
||||||
|
return stickerForEmoji(*regular);
|
||||||
|
}
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<LargeEmojiImage> EmojiPack::image(EmojiPtr emoji) {
|
std::shared_ptr<LargeEmojiImage> EmojiPack::image(EmojiPtr emoji) {
|
||||||
|
|
|
@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/text/text_block.h"
|
#include "ui/text/text_block.h"
|
||||||
#include "ui/ui_utility.h"
|
#include "ui/ui_utility.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
|
#include "styles/style_chat.h"
|
||||||
|
|
||||||
#include "data/stickers/data_stickers.h"
|
#include "data/stickers/data_stickers.h"
|
||||||
#include "ui/widgets/input_fields.h"
|
#include "ui/widgets/input_fields.h"
|
||||||
|
@ -36,7 +37,8 @@ using SizeTag = CustomEmojiManager::SizeTag;
|
||||||
using LottieSize = ChatHelpers::StickerLottieSize;
|
using LottieSize = ChatHelpers::StickerLottieSize;
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case SizeTag::Normal: return LottieSize::MessageHistory;
|
case SizeTag::Normal: return LottieSize::MessageHistory;
|
||||||
case SizeTag::Large: return LottieSize::EmojiInteraction;
|
case SizeTag::Large: return LottieSize::StickersPanel;
|
||||||
|
case SizeTag::Isolated: return LottieSize::EmojiInteraction;
|
||||||
}
|
}
|
||||||
Unexpected("SizeTag value in CustomEmojiManager-LottieSizeFromTag.");
|
Unexpected("SizeTag value in CustomEmojiManager-LottieSizeFromTag.");
|
||||||
}
|
}
|
||||||
|
@ -45,6 +47,9 @@ using SizeTag = CustomEmojiManager::SizeTag;
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case SizeTag::Normal: return Ui::Emoji::GetSizeNormal();
|
case SizeTag::Normal: return Ui::Emoji::GetSizeNormal();
|
||||||
case SizeTag::Large: return Ui::Emoji::GetSizeLarge();
|
case SizeTag::Large: return Ui::Emoji::GetSizeLarge();
|
||||||
|
case SizeTag::Isolated:
|
||||||
|
return (st::largeEmojiSize + 2 * st::largeEmojiOutline)
|
||||||
|
* style::DevicePixelRatio();
|
||||||
}
|
}
|
||||||
Unexpected("SizeTag value in CustomEmojiManager-SizeFromTag.");
|
Unexpected("SizeTag value in CustomEmojiManager-SizeFromTag.");
|
||||||
}
|
}
|
||||||
|
@ -396,20 +401,25 @@ std::unique_ptr<Ui::Text::CustomEmoji> CustomEmojiManager::create(
|
||||||
Ui::CustomEmoji::Preview CustomEmojiManager::prepareNonExactPreview(
|
Ui::CustomEmoji::Preview CustomEmojiManager::prepareNonExactPreview(
|
||||||
DocumentId documentId,
|
DocumentId documentId,
|
||||||
SizeTag tag) const {
|
SizeTag tag) const {
|
||||||
const auto &other = _instances[1 - SizeIndex(tag)];
|
for (auto i = _instances.size(); i != 0;) {
|
||||||
const auto j = other.find(documentId);
|
if (SizeIndex(tag) == --i) {
|
||||||
if (j == end(other)) {
|
continue;
|
||||||
return {};
|
}
|
||||||
} else if (const auto nonExact = j->second->imagePreview()) {
|
const auto &other = _instances[i];
|
||||||
const auto size = SizeFromTag(tag);
|
const auto j = other.find(documentId);
|
||||||
return {
|
if (j == end(other)) {
|
||||||
nonExact.image().scaled(
|
continue;
|
||||||
size,
|
} else if (const auto nonExact = j->second->imagePreview()) {
|
||||||
size,
|
const auto size = SizeFromTag(tag);
|
||||||
Qt::IgnoreAspectRatio,
|
return {
|
||||||
Qt::SmoothTransformation),
|
nonExact.image().scaled(
|
||||||
false,
|
size,
|
||||||
};
|
size,
|
||||||
|
Qt::IgnoreAspectRatio,
|
||||||
|
Qt::SmoothTransformation),
|
||||||
|
false,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -535,7 +545,7 @@ void CustomEmojiManager::requestSetFor(not_null<DocumentData*> document) {
|
||||||
int CustomEmojiManager::SizeIndex(SizeTag tag) {
|
int CustomEmojiManager::SizeIndex(SizeTag tag) {
|
||||||
const auto result = static_cast<int>(tag);
|
const auto result = static_cast<int>(tag);
|
||||||
|
|
||||||
Ensures(result >= 0 && result < 2);
|
Ensures(result >= 0 && result < kSizeCount);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,9 @@ public:
|
||||||
enum class SizeTag {
|
enum class SizeTag {
|
||||||
Normal,
|
Normal,
|
||||||
Large,
|
Large,
|
||||||
|
Isolated,
|
||||||
|
|
||||||
|
kCount,
|
||||||
};
|
};
|
||||||
|
|
||||||
CustomEmojiManager(not_null<Session*> owner);
|
CustomEmojiManager(not_null<Session*> owner);
|
||||||
|
@ -64,6 +67,8 @@ public:
|
||||||
[[nodiscard]] Session &owner() const;
|
[[nodiscard]] Session &owner() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static constexpr auto kSizeCount = int(SizeTag::kCount);
|
||||||
|
|
||||||
struct RepaintBunch {
|
struct RepaintBunch {
|
||||||
crl::time when = 0;
|
crl::time when = 0;
|
||||||
std::vector<base::weak_ptr<Ui::CustomEmoji::Instance>> instances;
|
std::vector<base::weak_ptr<Ui::CustomEmoji::Instance>> instances;
|
||||||
|
@ -91,12 +96,16 @@ private:
|
||||||
|
|
||||||
const not_null<Session*> _owner;
|
const not_null<Session*> _owner;
|
||||||
|
|
||||||
base::flat_map<
|
std::array<
|
||||||
uint64,
|
base::flat_map<
|
||||||
std::unique_ptr<Ui::CustomEmoji::Instance>> _instances[2];
|
uint64,
|
||||||
base::flat_map<
|
std::unique_ptr<Ui::CustomEmoji::Instance>>,
|
||||||
uint64,
|
kSizeCount> _instances;
|
||||||
std::vector<base::weak_ptr<CustomEmojiLoader>>> _loaders[2];
|
std::array<
|
||||||
|
base::flat_map<
|
||||||
|
uint64,
|
||||||
|
std::vector<base::weak_ptr<CustomEmojiLoader>>>,
|
||||||
|
kSizeCount> _loaders;
|
||||||
base::flat_set<uint64> _pendingForRequest;
|
base::flat_set<uint64> _pendingForRequest;
|
||||||
mtpRequestId _requestId = 0;
|
mtpRequestId _requestId = 0;
|
||||||
|
|
||||||
|
|
|
@ -1308,7 +1308,7 @@ TextWithEntities HistoryItem::inReplyText() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
Ui::Text::IsolatedEmoji HistoryItem::isolatedEmoji() const {
|
Ui::Text::IsolatedEmoji HistoryItem::isolatedEmoji() const {
|
||||||
return Ui::Text::IsolatedEmoji();
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryItem::~HistoryItem() {
|
HistoryItem::~HistoryItem() {
|
||||||
|
|
|
@ -419,15 +419,18 @@ void Element::customEmojiRepaint() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Element::clearCustomEmojiRepaint() const {
|
||||||
|
_customEmojiRepaintScheduled = false;
|
||||||
|
data()->_customEmojiRepaintScheduled = false;
|
||||||
|
}
|
||||||
|
|
||||||
void Element::prepareCustomEmojiPaint(
|
void Element::prepareCustomEmojiPaint(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
const Ui::Text::String &text) const {
|
const Ui::Text::String &text) const {
|
||||||
const auto item = data();
|
|
||||||
if (!text.hasCustomEmoji()) {
|
if (!text.hasCustomEmoji()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_customEmojiRepaintScheduled = false;
|
clearCustomEmojiRepaint();
|
||||||
item->_customEmojiRepaintScheduled = false;
|
|
||||||
p.setInactive(delegate()->elementIsGifPaused());
|
p.setInactive(delegate()->elementIsGifPaused());
|
||||||
if (!_heavyCustomEmoji) {
|
if (!_heavyCustomEmoji) {
|
||||||
_heavyCustomEmoji = true;
|
_heavyCustomEmoji = true;
|
||||||
|
|
|
@ -431,6 +431,7 @@ public:
|
||||||
void prepareCustomEmojiPaint(
|
void prepareCustomEmojiPaint(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
const Ui::Text::String &text) const;
|
const Ui::Text::String &text) const;
|
||||||
|
void clearCustomEmojiRepaint() const;
|
||||||
|
|
||||||
[[nodiscard]] ClickHandlerPtr fromPhotoLink() const {
|
[[nodiscard]] ClickHandlerPtr fromPhotoLink() const {
|
||||||
return fromLink();
|
return fromLink();
|
||||||
|
|
|
@ -14,20 +14,34 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "ui/image/image.h"
|
#include "ui/image/image.h"
|
||||||
#include "ui/chat/chat_style.h"
|
#include "ui/chat/chat_style.h"
|
||||||
|
#include "data/data_session.h"
|
||||||
#include "data/data_file_origin.h"
|
#include "data/data_file_origin.h"
|
||||||
|
#include "data/stickers/data_custom_emoji.h"
|
||||||
#include "styles/style_chat.h"
|
#include "styles/style_chat.h"
|
||||||
|
|
||||||
namespace HistoryView {
|
namespace HistoryView {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using EmojiImage = Stickers::LargeEmojiImage;
|
using Stickers::LargeEmojiImage;
|
||||||
|
using ImagePtr = std::shared_ptr<Stickers::LargeEmojiImage>;
|
||||||
|
using CustomPtr = std::unique_ptr<Ui::Text::CustomEmoji>;
|
||||||
|
|
||||||
auto ResolveImages(
|
auto ResolveImages(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
|
Fn<void()> customEmojiRepaint,
|
||||||
const Ui::Text::IsolatedEmoji &emoji)
|
const Ui::Text::IsolatedEmoji &emoji)
|
||||||
-> std::array<std::shared_ptr<EmojiImage>, Ui::Text::kIsolatedEmojiLimit> {
|
-> std::array<LargeEmojiMedia, Ui::Text::kIsolatedEmojiLimit> {
|
||||||
const auto single = [&](EmojiPtr emoji) {
|
const auto single = [&](Ui::Text::IsolatedEmoji::Item item)
|
||||||
return emoji ? session->emojiStickersPack().image(emoji) : nullptr;
|
-> LargeEmojiMedia {
|
||||||
|
if (const auto regular = std::get_if<EmojiPtr>(&item)) {
|
||||||
|
return session->emojiStickersPack().image(*regular);
|
||||||
|
} else if (const auto custom = std::get_if<QString>(&item)) {
|
||||||
|
return session->data().customEmojiManager().create(
|
||||||
|
*custom,
|
||||||
|
customEmojiRepaint,
|
||||||
|
Data::CustomEmojiManager::SizeTag::Isolated);
|
||||||
|
}
|
||||||
|
return v::null;
|
||||||
};
|
};
|
||||||
return { {
|
return { {
|
||||||
single(emoji.items[0]),
|
single(emoji.items[0]),
|
||||||
|
@ -35,28 +49,25 @@ auto ResolveImages(
|
||||||
single(emoji.items[2]) } };
|
single(emoji.items[2]) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto NonEmpty(const std::array<std::shared_ptr<EmojiImage>, Ui::Text::kIsolatedEmojiLimit> &images) {
|
|
||||||
using namespace rpl::mappers;
|
|
||||||
|
|
||||||
return images | ranges::views::filter(_1 != nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
LargeEmoji::LargeEmoji(
|
LargeEmoji::LargeEmoji(
|
||||||
not_null<Element*> parent,
|
not_null<Element*> parent,
|
||||||
const Ui::Text::IsolatedEmoji &emoji)
|
const Ui::Text::IsolatedEmoji &emoji)
|
||||||
: _parent(parent)
|
: _parent(parent)
|
||||||
, _images(ResolveImages(&parent->data()->history()->session(), emoji)) {
|
, _images(ResolveImages(
|
||||||
|
&parent->data()->history()->session(),
|
||||||
|
[=] { parent->customEmojiRepaint(); },
|
||||||
|
emoji)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize LargeEmoji::size() {
|
QSize LargeEmoji::size() {
|
||||||
using namespace rpl::mappers;
|
using namespace rpl::mappers;
|
||||||
|
|
||||||
const auto count = ranges::distance(NonEmpty(_images));
|
const auto count = _images.size()
|
||||||
Assert(count > 0);
|
- ranges::count(_images, LargeEmojiMedia());
|
||||||
|
|
||||||
const auto single = EmojiImage::Size() / cIntRetinaFactor();
|
const auto single = LargeEmojiImage::Size() / cIntRetinaFactor();
|
||||||
const auto skip = st::largeEmojiSkip - 2 * st::largeEmojiOutline;
|
const auto skip = st::largeEmojiSkip - 2 * st::largeEmojiOutline;
|
||||||
const auto inner = count * single.width() + (count - 1) * skip;
|
const auto inner = count * single.width() + (count - 1) * skip;
|
||||||
const auto &padding = st::largeEmojiPadding;
|
const auto &padding = st::largeEmojiPadding;
|
||||||
|
@ -70,23 +81,91 @@ void LargeEmoji::draw(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
const PaintContext &context,
|
const PaintContext &context,
|
||||||
const QRect &r) {
|
const QRect &r) {
|
||||||
auto &&images = NonEmpty(_images);
|
_parent->clearCustomEmojiRepaint();
|
||||||
|
|
||||||
const auto &padding = st::largeEmojiPadding;
|
const auto &padding = st::largeEmojiPadding;
|
||||||
auto x = r.x() + (r.width() - _size.width()) / 2 + padding.left();
|
auto x = r.x() + (r.width() - _size.width()) / 2 + padding.left();
|
||||||
const auto y = r.y() + (r.height() - _size.height()) / 2 + padding.top();
|
const auto y = r.y() + (r.height() - _size.height()) / 2 + padding.top();
|
||||||
const auto skip = st::largeEmojiSkip - 2 * st::largeEmojiOutline;
|
const auto skip = st::largeEmojiSkip - 2 * st::largeEmojiOutline;
|
||||||
const auto size = EmojiImage::Size() / cIntRetinaFactor();
|
const auto size = LargeEmojiImage::Size() / cIntRetinaFactor();
|
||||||
for (const auto &image : images) {
|
const auto paused = _parent->delegate()->elementIsGifPaused();
|
||||||
if (const auto &prepared = image->image) {
|
const auto selected = context.selected();
|
||||||
const auto colored = context.selected()
|
if (!selected) {
|
||||||
? &context.st->msgStickerOverlay()
|
_selectedFrame = QImage();
|
||||||
: nullptr;
|
}
|
||||||
p.drawPixmap(x, y, prepared->pix(size, { .colored = colored }));
|
for (const auto &media : _images) {
|
||||||
} else if (image->load) {
|
if (const auto image = std::get_if<ImagePtr>(&media)) {
|
||||||
image->load();
|
if (const auto &prepared = (*image)->image) {
|
||||||
|
const auto colored = selected
|
||||||
|
? &context.st->msgStickerOverlay()
|
||||||
|
: nullptr;
|
||||||
|
p.drawPixmap(
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
prepared->pix(size, { .colored = colored }));
|
||||||
|
} else if ((*image)->load) {
|
||||||
|
(*image)->load();
|
||||||
|
}
|
||||||
|
} else if (const auto custom = std::get_if<CustomPtr>(&media)) {
|
||||||
|
paintCustom(p, x, y, custom->get(), context, paused);
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
x += size.width() + skip;
|
x += size.width() + skip;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LargeEmoji::paintCustom(
|
||||||
|
QPainter &p,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
not_null<Ui::Text::CustomEmoji*> emoji,
|
||||||
|
const PaintContext &context,
|
||||||
|
bool paused) {
|
||||||
|
if (!_hasHeavyPart) {
|
||||||
|
_hasHeavyPart = true;
|
||||||
|
_parent->history()->owner().registerHeavyViewPart(_parent);
|
||||||
|
}
|
||||||
|
const auto inner = st::largeEmojiSize + 2 * st::largeEmojiOutline;
|
||||||
|
const auto outer = Ui::Text::AdjustCustomEmojiSize(inner);
|
||||||
|
const auto skip = (inner - outer) / 2;
|
||||||
|
const auto preview = context.imageStyle()->msgServiceBg->c;
|
||||||
|
if (context.selected()) {
|
||||||
|
const auto factor = style::DevicePixelRatio();
|
||||||
|
const auto size = QSize(outer, outer) * factor;
|
||||||
|
if (_selectedFrame.size() != size) {
|
||||||
|
_selectedFrame = QImage(
|
||||||
|
size,
|
||||||
|
QImage::Format_ARGB32_Premultiplied);
|
||||||
|
_selectedFrame.setDevicePixelRatio(factor);
|
||||||
|
}
|
||||||
|
_selectedFrame.fill(Qt::transparent);
|
||||||
|
auto q = QPainter(&_selectedFrame);
|
||||||
|
emoji->paint(q, 0, 0, context.now, preview, paused);
|
||||||
|
q.end();
|
||||||
|
|
||||||
|
_selectedFrame = Images::Colored(
|
||||||
|
std::move(_selectedFrame),
|
||||||
|
context.st->msgStickerOverlay()->c);
|
||||||
|
p.drawImage(x + skip, y + skip, _selectedFrame);
|
||||||
|
} else {
|
||||||
|
emoji->paint(p, x + skip, y + skip, context.now, preview, paused);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LargeEmoji::hasHeavyPart() const {
|
||||||
|
return _hasHeavyPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LargeEmoji::unloadHeavyPart() {
|
||||||
|
if (_hasHeavyPart) {
|
||||||
|
_hasHeavyPart = false;
|
||||||
|
for (auto &media : _images) {
|
||||||
|
if (const auto custom = std::get_if<CustomPtr>(&media)) {
|
||||||
|
(*custom)->unload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace HistoryView
|
} // namespace HistoryView
|
||||||
|
|
|
@ -20,6 +20,11 @@ struct LargeEmojiImage;
|
||||||
|
|
||||||
namespace HistoryView {
|
namespace HistoryView {
|
||||||
|
|
||||||
|
using LargeEmojiMedia = std::variant<
|
||||||
|
v::null_t,
|
||||||
|
std::shared_ptr<Stickers::LargeEmojiImage>,
|
||||||
|
std::unique_ptr<Ui::Text::CustomEmoji>>;
|
||||||
|
|
||||||
class LargeEmoji final : public UnwrappedMedia::Content {
|
class LargeEmoji final : public UnwrappedMedia::Content {
|
||||||
public:
|
public:
|
||||||
LargeEmoji(
|
LargeEmoji(
|
||||||
|
@ -39,12 +44,23 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hasHeavyPart() const override;
|
||||||
|
void unloadHeavyPart() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void paintCustom(
|
||||||
|
QPainter &p,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
not_null<Ui::Text::CustomEmoji*> emoji,
|
||||||
|
const PaintContext &context,
|
||||||
|
bool paused);
|
||||||
|
|
||||||
const not_null<Element*> _parent;
|
const not_null<Element*> _parent;
|
||||||
const std::array<
|
const std::array<LargeEmojiMedia, Ui::Text::kIsolatedEmojiLimit> _images;
|
||||||
std::shared_ptr<Stickers::LargeEmojiImage>,
|
QImage _selectedFrame;
|
||||||
Ui::Text::kIsolatedEmojiLimit> _images;
|
|
||||||
QSize _size;
|
QSize _size;
|
||||||
|
bool _hasHeavyPart = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace Ui::CustomEmoji {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr auto kMaxSize = 128;
|
constexpr auto kMaxSize = 128;
|
||||||
constexpr auto kMaxFrames = 512;
|
constexpr auto kMaxFrames = 180;
|
||||||
constexpr auto kMaxFrameDuration = 86400 * crl::time(1000);
|
constexpr auto kMaxFrameDuration = 86400 * crl::time(1000);
|
||||||
constexpr auto kCacheVersion = 1;
|
constexpr auto kCacheVersion = 1;
|
||||||
constexpr auto kPreloadFrames = 3;
|
constexpr auto kPreloadFrames = 3;
|
||||||
|
@ -415,7 +415,7 @@ void Renderer::frameReady(
|
||||||
}
|
}
|
||||||
if (const auto count = generator->count()) {
|
if (const auto count = generator->count()) {
|
||||||
if (!_cache.frames()) {
|
if (!_cache.frames()) {
|
||||||
_cache.reserve(count);
|
_cache.reserve(std::max(count, kMaxFrames));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const auto current = _cache.currentFrame();
|
const auto current = _cache.currentFrame();
|
||||||
|
@ -425,7 +425,7 @@ void Renderer::frameReady(
|
||||||
if (explicitRepaint && _repaint) {
|
if (explicitRepaint && _repaint) {
|
||||||
_repaint();
|
_repaint();
|
||||||
}
|
}
|
||||||
if (!duration) {
|
if (!duration || total + 1 >= kMaxFrames) {
|
||||||
finish();
|
finish();
|
||||||
} else if (current + kPreloadFrames > total) {
|
} else if (current + kPreloadFrames > total) {
|
||||||
renderNext(std::move(generator), std::move(frame));
|
renderNext(std::move(generator), std::move(frame));
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit c5b32c53efbc1481f3942d28ef7e4f5eaca5df1f
|
Subproject commit a5d7b23a638e6c2d9bffa97bf40d5d7559a926c8
|
Loading…
Add table
Reference in a new issue