Browse Source

chatgui: fix all animations showing the same TGS (rlottie model cache key collision)

lottie_animation_from_data uses 'key' as a cache key for parsed models.
All LottieIcon instances were created with key="", causing rlottie's
model cache to return the first loaded animation for all subsequent
requests. Only visible on Windows where rlottie cache is enabled by
default.

Fix: pass unique animPath as key to each LottieIcon constructor.
Also replaced fprintf(stderr) diag with GUI_INFO logging via
AnimTimer::logRegisteredIcons() in debug_ui.h.
topo_upd
Evgeny 2 months ago
parent
commit
0e11d858e8
  1. 12
      tools/chatgui/src/animtimer.cpp
  2. 1
      tools/chatgui/src/animtimer.h
  3. 3
      tools/chatgui/src/emojipanel.cpp
  4. 13
      tools/chatgui/src/lottieicon.cpp
  5. 5
      tools/chatgui/src/lottieicon.h
  6. 2
      tools/chatgui/src/mainwindow.cpp
  7. 9
      tools/chatgui/src/messagelist.cpp

12
tools/chatgui/src/animtimer.cpp

@ -1,6 +1,6 @@
#include "animtimer.h"
#include "lottieicon.h"
#include "../../lib/debug_config.h"
#include "debug_ui.h"
AnimTimer::AnimTimer() {
m_timer.setInterval(33);
@ -49,3 +49,13 @@ void AnimTimer::onTimer() {
icon->advanceFrame();
emit ticked();
}
void AnimTimer::logRegisteredIcons() const {
for (auto it = m_icons.constBegin(); it != m_icons.constEnd(); ++it) {
LottieIcon *icon = it.value();
GUI_INFO("LottieIcon: path=%s frames=%d size=%dx%d tgsSize=%d valid=%d",
qPrintable(it.key()), icon->frameCount(),
icon->originalSize().width(), icon->originalSize().height(),
icon->tgsSize(), (int)icon->isValid());
}
}

1
tools/chatgui/src/animtimer.h

@ -14,6 +14,7 @@ public:
void registerIcon(const QString &key, LottieIcon *icon);
void unregisterIcon(const QString &key);
LottieIcon *icon(const QString &key) const;
void logRegisteredIcons() const;
void activate();
void deactivate();

3
tools/chatgui/src/emojipanel.cpp

@ -3,7 +3,6 @@
#include "emojitabbar.h"
#include "animtimer.h"
#include "lottieicon.h"
#include <cstdio>
#include <QPushButton>
#include <QScrollArea>
#include <QTabWidget>
@ -35,8 +34,6 @@ public:
if (data.type == EmojiType::Animation) {
setMouseTracking(true);
m_icon = AnimTimer::instance()->icon(data.animPath);
fprintf(stderr, "[DIAG EmojiBtn] btn=%p path=%s m_icon=%p\n",
(void*)this, qPrintable(data.animPath), (void*)m_icon);
m_timer.setInterval(33);
connect(&m_timer, &QTimer::timeout, this, [this]() {
if (m_icon && m_icon->isValid()) {

13
tools/chatgui/src/lottieicon.cpp

@ -2,7 +2,6 @@
#include <rlottie_capi.h>
#include <zlib.h>
#include <cstring>
#include <cstdio>
static QByteArray unpackGzip(const QByteArray &data) {
if (data.isEmpty()) return {};
@ -34,23 +33,19 @@ static QByteArray unpackGzip(const QByteArray &data) {
return result;
}
LottieIcon::LottieIcon(const QByteArray &tgsData) {
LottieIcon::LottieIcon(const QByteArray &tgsData, const QString &key) {
m_tgsSize = (int)tgsData.size();
QByteArray json = unpackGzip(tgsData);
fprintf(stderr, "[DIAG LottieIcon] this=%p tgsSize=%d jsonSize=%d jsonEmpty=%d\n",
(void*)this, (int)tgsData.size(), (int)json.size(), (int)json.isEmpty());
if (json.isEmpty()) return;
m_jsonData = json;
m_anim = lottie_animation_from_data(m_jsonData.constData(), "", "");
fprintf(stderr, "[DIAG LottieIcon] this=%p m_anim=%p jsonHead=%.60s\n",
(void*)this, (void*)m_anim, m_jsonData.constData());
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);
fprintf(stderr, "[DIAG LottieIcon] this=%p frames=%d size=%zux%zu\n",
(void*)this, m_totalFrames, m_w, m_h);
if (m_totalFrames <= 0) m_totalFrames = 1;
m_valid = true;
}

5
tools/chatgui/src/lottieicon.h

@ -7,7 +7,7 @@
class LottieIcon {
public:
explicit LottieIcon(const QByteArray &tgsData);
explicit LottieIcon(const QByteArray &tgsData, const QString &key);
~LottieIcon();
bool isValid() const { return m_valid; }
@ -15,6 +15,8 @@ public:
int frameCount() const { return m_totalFrames; }
double frameRate() const { return m_frameRate; }
int currentFrame() const { return m_currentFrame; }
int tgsSize() const { return m_tgsSize; }
void setTgsSize(int sz) { m_tgsSize = sz; }
QImage renderFrame(int frameNum, QSize targetSize) const;
void advanceFrame() { m_currentFrame = (m_currentFrame + 1) % m_totalFrames; }
@ -24,6 +26,7 @@ private:
struct Lottie_Animation_S *m_anim = nullptr;
int m_currentFrame = 0;
int m_totalFrames = 0;
int m_tgsSize = 0;
double m_frameRate = 60.0;
size_t m_w = 0, m_h = 0;
QByteArray m_jsonData;

2
tools/chatgui/src/mainwindow.cpp

@ -143,6 +143,8 @@ void MainWindow::setupNode() {
if (!m_node->start(m_cfgPath))
qWarning("Failed to start UtunNode");
else
AnimTimer::instance()->logRegisteredIcons();
}
void MainWindow::setupMessaging() {

9
tools/chatgui/src/messagelist.cpp

@ -16,7 +16,6 @@
#include <QScrollBar>
#include <QApplication>
#include <QDebug>
#include <cstdio>
#include <vector>
#include <memory>
@ -106,17 +105,11 @@ MessageList::MessageList(DbManager* db, QWidget *parent)
QFile f(e.animPath);
if (f.open(QIODevice::ReadOnly)) {
QByteArray raw = f.readAll();
auto icon = std::make_unique<LottieIcon>(raw);
fprintf(stderr, "[DIAG register] path=%s fileOpen=1 rawSize=%d iconPtr=%p iconValid=%d\n",
qPrintable(e.animPath), (int)raw.size(),
(void*)icon.get(), (int)icon->isValid());
auto icon = std::make_unique<LottieIcon>(raw, e.animPath);
if (icon->isValid()) {
AnimTimer::instance()->registerIcon(e.animPath, icon.get());
s_icons.push_back(std::move(icon));
}
} else {
fprintf(stderr, "[DIAG register] path=%s fileOpen=0\n",
qPrintable(e.animPath));
}
}
}

Loading…
Cancel
Save