Unpack lottie gzip to std::string for rlottie.

This commit is contained in:
John Preston 2019-06-26 10:55:08 +02:00
parent aa3a079853
commit f20d9395d1
4 changed files with 16 additions and 26 deletions

View File

@ -21,7 +21,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Lottie { namespace Lottie {
namespace { namespace {
QByteArray UnpackGzip(const QByteArray &bytes) { std::string UnpackGzip(const QByteArray &bytes) {
const auto original = [&] {
return std::string(bytes.constData(), bytes.size());
};
z_stream stream; z_stream stream;
stream.zalloc = nullptr; stream.zalloc = nullptr;
stream.zfree = nullptr; stream.zfree = nullptr;
@ -30,11 +33,11 @@ QByteArray UnpackGzip(const QByteArray &bytes) {
stream.next_in = nullptr; stream.next_in = nullptr;
int res = inflateInit2(&stream, 16 + MAX_WBITS); int res = inflateInit2(&stream, 16 + MAX_WBITS);
if (res != Z_OK) { if (res != Z_OK) {
return bytes; return original();
} }
const auto guard = gsl::finally([&] { inflateEnd(&stream); }); const auto guard = gsl::finally([&] { inflateEnd(&stream); });
auto result = QByteArray(kMaxFileSize + 1, Qt::Uninitialized); auto result = std::string(kMaxFileSize + 1, char(0));
stream.avail_in = bytes.size(); stream.avail_in = bytes.size();
stream.next_in = reinterpret_cast<Bytef*>(const_cast<char*>(bytes.data())); stream.next_in = reinterpret_cast<Bytef*>(const_cast<char*>(bytes.data()));
stream.avail_out = 0; stream.avail_out = 0;
@ -43,9 +46,9 @@ QByteArray UnpackGzip(const QByteArray &bytes) {
stream.next_out = reinterpret_cast<Bytef*>(result.data()); stream.next_out = reinterpret_cast<Bytef*>(result.data());
int res = inflate(&stream, Z_NO_FLUSH); int res = inflate(&stream, Z_NO_FLUSH);
if (res != Z_OK && res != Z_STREAM_END) { if (res != Z_OK && res != Z_STREAM_END) {
return bytes; return original();
} else if (!stream.avail_out) { } else if (!stream.avail_out) {
return bytes; return original();
} }
} }
result.resize(result.size() - stream.avail_out); result.resize(result.size() - stream.avail_out);
@ -75,21 +78,16 @@ auto Init(QByteArray &&content)
<< content.size(); << content.size();
return Error::ParseFailed; return Error::ParseFailed;
} }
content = UnpackGzip(content); const auto string = UnpackGzip(content);
if (content.size() > kMaxFileSize) { Assert(string.size() <= kMaxFileSize);
qWarning()
<< "Lottie Error: Too large file: " auto animation = rlottie::Animation::loadFromData(string, std::string());
<< content.size();
return Error::ParseFailed;
}
auto animation = rlottie::Animation::loadFromData(
std::string(content.constData(), content.size()),
std::string());
if (!animation) { if (!animation) {
qWarning() qWarning()
<< "Lottie Error: Parse failed."; << "Lottie Error: Parse failed.";
return Error::ParseFailed; return Error::ParseFailed;
} }
auto result = std::make_unique<SharedState>(std::move(animation)); auto result = std::make_unique<SharedState>(std::move(animation));
auto information = result->information(); auto information = result->information();
if (!information.frameRate if (!information.frameRate
@ -154,8 +152,7 @@ QImage Animation::frame(const FrameRequest &request) const {
Expects(_renderer != nullptr); Expects(_renderer != nullptr);
const auto frame = _state->frameForPaint(); const auto frame = _state->frameForPaint();
const auto changed = (frame->request != request) const auto changed = (frame->request != request);
&& (request.strict || !frame->request.strict);
if (changed) { if (changed) {
frame->request = request; frame->request = request;
_renderer->updateFrameRequest(_state, request); _renderer->updateFrameRequest(_state, request);

View File

@ -49,13 +49,6 @@ enum class Error {
struct FrameRequest { struct FrameRequest {
QSize resize; QSize resize;
std::optional<QColor> colored; std::optional<QColor> colored;
bool strict = true;
static FrameRequest NonStrict() {
auto result = FrameRequest();
result.strict = false;
return result;
}
bool empty() const { bool empty() const {
return resize.isEmpty(); return resize.isEmpty();

View File

@ -180,7 +180,7 @@ SharedState::SharedState(std::unique_ptr<rlottie::Animation> animation)
calculateProperties(); calculateProperties();
if (isValid()) { if (isValid()) {
auto cover = QImage(); auto cover = QImage();
renderFrame(cover, FrameRequest::NonStrict(), 0); renderFrame(cover, FrameRequest(), 0);
init(std::move(cover)); init(std::move(cover));
} }
} }

View File

@ -32,7 +32,7 @@ struct Frame {
crl::time displayed = kTimeUnknown; crl::time displayed = kTimeUnknown;
crl::time display = kTimeUnknown; crl::time display = kTimeUnknown;
FrameRequest request = FrameRequest::NonStrict(); FrameRequest request;
QImage prepared; QImage prepared;
}; };