Files
utun2/tools/chatgui/src/lottieicon.cpp
T
evgeny 38c9f229bc stcp: ed25519 pubkey exchange in handshake, fix instance destroy segfault, fix chat_tcp_test
- u_async.c: process immediate_queue BEFORE epoll_wait in uasync_poll
- stcp_link.c: defensive NULL etcp_conn/etcp_link in stcp_link_close
- utun_instance.c: move stcp_server_list_destroy_all to Phase J (before ETCP),
  add deferred drain in both Phase J and L
- stcp.h/c: STCP_HS_ENC_CLIENT 6→38, STCP_HS_ENC_SERVER 7→39,
  exchange ed25519_pubkey in both handshake directions
- etcp_connections.c: copy peer_ed25519 from STCP to ETCP_CONN in
  etcp_link_enter_ready_tcp; guard link->etcp in tcp_link_close_cb
- chat_sync.c: fix lk->conn NULL dereference for TCP links
- test_stcp.c: update stcp_server_create/stcp_client_connect callsites
- tools/chat_tcp_test: change transport udp→tcp
2026-08-07 00:48:27 +03:00

75 lines
2.4 KiB
C++

#include "lottieicon.h"
#include <rlottie_capi.h>
#include <zlib.h>
#include <cstring>
static QByteArray unpackGzip(const QByteArray &data) {
if (data.isEmpty()) return {};
z_stream strm = {};
int ret = inflateInit2(&strm, 16 + MAX_WBITS);
if (ret != Z_OK) return {};
strm.avail_in = (uInt)data.size();
strm.next_in = (Bytef *)data.constData();
QByteArray result;
result.resize(data.size() * 3);
size_t total = 0;
do {
size_t remain = (size_t)result.size() - total;
if (remain < 4096) {
result.resize(result.size() * 2);
remain = (size_t)result.size() - total;
}
strm.avail_out = (uInt)remain;
strm.next_out = (Bytef *)result.data() + total;
ret = inflate(&strm, Z_NO_FLUSH);
if (ret == Z_STREAM_ERROR || ret == Z_DATA_ERROR) {
inflateEnd(&strm);
return {};
}
total += remain - strm.avail_out;
} while (ret != Z_STREAM_END);
inflateEnd(&strm);
result.resize((int)total);
return result;
}
LottieIcon::LottieIcon(const QByteArray &tgsData, const QString &key) {
m_tgsSize = (int)tgsData.size();
QByteArray json = unpackGzip(tgsData);
if (json.isEmpty()) return;
m_jsonData = json;
QByteArray keyUtf8 = key.toUtf8();
m_anim = lottie_animation_from_data(m_jsonData.constData(), keyUtf8.constData(), "");
if (!m_anim) return;
lottie_animation_get_size(m_anim, &m_w, &m_h);
m_totalFrames = (int)lottie_animation_get_totalframe(m_anim);
m_frameRate = lottie_animation_get_framerate(m_anim);
if (m_totalFrames <= 0) m_totalFrames = 1;
m_valid = true;
}
LottieIcon::~LottieIcon() {
if (m_anim) lottie_animation_destroy(m_anim);
}
QImage LottieIcon::renderFrame(int frameNum, QSize targetSize) const {
if (!m_valid || targetSize.width() <= 0 || targetSize.height() <= 0)
return QImage();
int w = targetSize.width();
int h = targetSize.height();
size_t stride = (size_t)w * 4;
std::vector<uint32_t> buffer((size_t)w * (size_t)h);
int frame = frameNum % m_totalFrames;
lottie_animation_render(m_anim, (size_t)frame, buffer.data(),
(size_t)w, (size_t)h, stride);
QImage img(w, h, QImage::Format_ARGB32_Premultiplied);
for (int y = 0; y < h; y++)
std::memcpy(img.scanLine(y), &buffer[(size_t)y * (size_t)w], stride);
return img;
}