diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/kvilib/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/kvilib/ext/kvi_animatedpixmap.cpp | 17 | ||||
| -rw-r--r-- | src/kvilib/ext/kvi_animatedpixmap.h | 19 | ||||
| -rw-r--r-- | src/kvilib/ext/kvi_animatedpixmapcache.cpp | 137 | ||||
| -rw-r--r-- | src/kvilib/ext/kvi_animatedpixmapcache.h | 24 | ||||
| -rw-r--r-- | src/kvilib/irc/kvi_avatar.h | 9 | ||||
| -rw-r--r-- | src/kvilib/system/kvi_time.cpp | 8 | ||||
| -rw-r--r-- | src/kvilib/system/kvi_time.h | 1 | ||||
| -rw-r--r-- | src/kvirc/kernel/kvi_iconmanager.cpp | 15 | ||||
| -rw-r--r-- | src/kvirc/ui/kvi_console.cpp | 9 | ||||
| -rw-r--r-- | src/kvirc/ui/kvi_ircview.cpp | 2 |
11 files changed, 210 insertions, 32 deletions
diff --git a/src/kvilib/CMakeLists.txt b/src/kvilib/CMakeLists.txt index 09aaa9476..80e6eee8b 100644 --- a/src/kvilib/CMakeLists.txt +++ b/src/kvilib/CMakeLists.txt @@ -40,6 +40,7 @@ SET(kvilib_MOC_HDRS tal/kvi_tal_vbox.h tal/kvi_tal_widgetstack.h tal/kvi_tal_wizard.h + ext/kvi_animatedpixmapcache.h ) IF(COMPILE_KDE_SUPPORT) diff --git a/src/kvilib/ext/kvi_animatedpixmap.cpp b/src/kvilib/ext/kvi_animatedpixmap.cpp index 33c079bce..bd2631fe1 100644 --- a/src/kvilib/ext/kvi_animatedpixmap.cpp +++ b/src/kvilib/ext/kvi_animatedpixmap.cpp @@ -8,6 +8,7 @@ #include "kvi_animatedpixmap.h" #include "kvi_settings.h" #include <QImageReader> +#include <QTime> #include <QHash> #include <QMutexLocker> @@ -17,8 +18,6 @@ KviAnimatedPixmap::KviAnimatedPixmap(QString fileName) m_bStarted = 0; m_uCurrentFrameNumber = 0; - connect(&m_timer,SIGNAL(timeout()),this,SLOT(animationTimerShot())); - m_lFrames=KviAnimatedPixmapCache::load(fileName); start(); } @@ -30,20 +29,17 @@ KviAnimatedPixmap::KviAnimatedPixmap(KviAnimatedPixmap* source) m_lFrames(source->m_lFrames) { m_lFrames->refs++; - connect(&m_timer,SIGNAL(timeout()),this,SLOT(animationTimerShot())); //restore started state if(isStarted() && (framesCount()>1)) { - m_timer.start(m_lFrames->at(m_uCurrentFrameNumber).delay); + KviAnimatedPixmapCache::sceduleFrameChange(m_lFrames->at(m_uCurrentFrameNumber).delay,this); } } KviAnimatedPixmap::~KviAnimatedPixmap() { - // all pixmaps will be automagically deleted at - // FrameInfo::~FrameInfo destructor:)) - + KviAnimatedPixmapCache::notifyDelete(this); KviAnimatedPixmapCache::free(m_lFrames); } @@ -51,7 +47,7 @@ void KviAnimatedPixmap::start() { if(!isStarted() && (framesCount()>1)) { - m_timer.start(m_lFrames->at(m_uCurrentFrameNumber).delay); + KviAnimatedPixmapCache::sceduleFrameChange(m_lFrames->at(m_uCurrentFrameNumber).delay,this); m_bStarted = true; } } @@ -60,12 +56,11 @@ void KviAnimatedPixmap::stop() { if(isStarted()) { - m_timer.stop(); m_bStarted = false; } } -void KviAnimatedPixmap::animationTimerShot() +void KviAnimatedPixmap::nextFrame() { m_uCurrentFrameNumber++; //Ensure, that we are not out of bounds @@ -74,7 +69,7 @@ void KviAnimatedPixmap::animationTimerShot() emit(frameChanged()); //run timer again - m_timer.start(m_lFrames->at(m_uCurrentFrameNumber).delay); + KviAnimatedPixmapCache::sceduleFrameChange(m_lFrames->at(m_uCurrentFrameNumber).delay,this); } void KviAnimatedPixmap::resize(QSize newSize,Qt::AspectRatioMode ratioMode) diff --git a/src/kvilib/ext/kvi_animatedpixmap.h b/src/kvilib/ext/kvi_animatedpixmap.h index 5a54f9dc5..e9c2c2e49 100644 --- a/src/kvilib/ext/kvi_animatedpixmap.h +++ b/src/kvilib/ext/kvi_animatedpixmap.h @@ -48,13 +48,12 @@ * This class owns all pixmaps. Do not store links to them. */ -class KVILIB_API KviAnimatedPixmap : public QObject{ +class KVILIB_API KviAnimatedPixmap : public QObject , public KviAnimatedPixmapInterface{ Q_OBJECT protected: QString m_szFileName; KviAnimatedPixmapCache::Data* m_lFrames; - QTimer m_timer; uint m_uCurrentFrameNumber; bool m_bStarted; @@ -100,14 +99,15 @@ public: } /* - * Returns active frame's pixmap + * Returns active frame's pixmap. + * Never fails. */ inline QPixmap* pixmap() { if(m_lFrames->count()>0) return m_lFrames->at(m_uCurrentFrameNumber).pixmap; else - return 0; + return KviAnimatedPixmapCache::dummyPixmap(); } /* @@ -140,17 +140,16 @@ public: */ void resize(QSize newSize,Qt::AspectRatioMode ratioMode); -protected slots: - /* - * Slot, to be connected to m_animationTimer, to receive animation - * frame changes. + * Called when the frame changes */ - void animationTimerShot(); + void nextFrame(); signals: + /* - * This signal emitted when active frame changes + * Slot, to be connected to m_animationTimer, to receive animation + * frame changes. */ void frameChanged(); }; diff --git a/src/kvilib/ext/kvi_animatedpixmapcache.cpp b/src/kvilib/ext/kvi_animatedpixmapcache.cpp index 4e997ad39..38d3ec18b 100644 --- a/src/kvilib/ext/kvi_animatedpixmapcache.cpp +++ b/src/kvilib/ext/kvi_animatedpixmapcache.cpp @@ -8,15 +8,23 @@ #include <kvi_animatedpixmapcache.h> #include <QImageReader> #include <QImage> +#include "kvi_time.h" static KviAnimatedPixmapCache* g_pAnimatedCache = 0; +static QPixmap* g_pDummyPixmap = 0; -KviAnimatedPixmapCache::KviAnimatedPixmapCache() { +KviAnimatedPixmapCache::KviAnimatedPixmapCache() +{ g_pAnimatedCache = this; + m_animationTimer.setSingleShot(true); + connect(&m_animationTimer,SIGNAL(timeout()),this,SLOT(timerEvent())); } KviAnimatedPixmapCache::~KviAnimatedPixmapCache() { - // TODO Auto-generated destructor stub + if(g_pDummyPixmap) { + delete g_pDummyPixmap; + } + g_pAnimatedCache = 0; } KviAnimatedPixmapCache::Data* KviAnimatedPixmapCache::internalLoad(QString szFile) { @@ -135,3 +143,128 @@ void KviAnimatedPixmapCache::free(KviAnimatedPixmapCache::Data* data) { } g_pAnimatedCache->internalFree(data); } + +void KviAnimatedPixmapCache::internalSceduleFrameChange(uint delay,KviAnimatedPixmapInterface* receiver) +{ + debug("Adding %i - %i",(uint)KviTimeUtils::getCurrentTimeMills()+delay,receiver); + m_timerMutex.lock(); + bool needTimerChange = false; + long long when = KviTimeUtils::getCurrentTimeMills()+delay; + + if(m_timerData.isEmpty()) + { + + m_timerData.insert(when,receiver); + needTimerChange = true; + + } else { + long long currentNext = m_timerData.begin().key(); + + if(when<currentNext){ + needTimerChange = true; + } + + m_timerData.insert(when,receiver); + } + + if(needTimerChange) + { + m_animationTimer.start(delay); + } + + m_timerMutex.unlock(); +} + +void KviAnimatedPixmapCache::timerEvent() +{ + /* + * We are adding 15msecs to the current time. This MAY lead to the situation, + * when the current frame will be painted a bit earlier, then i should. + * But we are just playing animated gifs, not a HDTV video. So it should be ok. + * + * But it makes good speedup if there will be event, sceduled in such order: + * 1 event at time X + * 3 events at time X+2msec + * 2 events at time X+6msec + * 1 event at time X+8msec + * 1 event at time X+9msec + * 1 event at time X+12msec + * ... + * + * Such situation is possible if we will have lots of smiles with almost the same + * frame delays. + * + * So it will not emit additional 5 events. + */ + long long now = KviTimeUtils::getCurrentTimeMills() + 15; + +// m_timerMutex.lock(); + + QMultiMap<long long, KviAnimatedPixmapInterface*>::iterator i = + m_timerData.begin(); + + while (i != m_timerData.end() && i.key() <= now) + { + i.value()->nextFrame(); + debug("Calling %i - %i",(uint)KviTimeUtils::getCurrentTimeMills(),i.value()); + i = m_timerData.erase(i); + } + + if (i != m_timerData.end()) + { + long long nextDelay = i.key(); + uint delay = (uint) (nextDelay - KviTimeUtils::getCurrentTimeMills()); + if (delay < 0) + { + delay = 0; + } + m_animationTimer.start(delay); + } +// m_timerMutex.unlock(); +} + +void KviAnimatedPixmapCache::sceduleFrameChange(uint when,KviAnimatedPixmapInterface* receiver) +{ + if (g_pAnimatedCache) + { + g_pAnimatedCache->internalSceduleFrameChange(when,receiver); + } +} + +QPixmap* KviAnimatedPixmapCache::dummyPixmap() +{ + if(!g_pDummyPixmap) + { + g_pDummyPixmap = new QPixmap(); + } + return g_pDummyPixmap; +} + +void KviAnimatedPixmapCache::internalNotifyDelete( + KviAnimatedPixmapInterface* receiver) +{ + m_timerMutex.lock(); + + QMultiMap<long long, KviAnimatedPixmapInterface*>::iterator i = + m_timerData.begin(); + + while (i != m_timerData.end()) + { + if (i.value() == receiver) + { + i = m_timerData.erase(i); + } else { + i++; + } + } + + m_timerMutex.unlock(); +} + +void KviAnimatedPixmapCache::notifyDelete(KviAnimatedPixmapInterface* receiver) +{ + if (g_pAnimatedCache) + { + g_pAnimatedCache->internalNotifyDelete(receiver); + } +} diff --git a/src/kvilib/ext/kvi_animatedpixmapcache.h b/src/kvilib/ext/kvi_animatedpixmapcache.h index 9fe558688..76c8037d4 100644 --- a/src/kvilib/ext/kvi_animatedpixmapcache.h +++ b/src/kvilib/ext/kvi_animatedpixmapcache.h @@ -11,9 +11,16 @@ #include <QMutex> #include <QPixmap> #include <QMultiHash> +#include <QMultiMap> +#include <QTimer> -class KviAnimatedPixmapCache { +class KviAnimatedPixmapInterface { + public: + virtual void nextFrame() = 0; +}; +class KviAnimatedPixmapCache : public QObject { + Q_OBJECT public: /* * This subclass represents simple structure @@ -72,8 +79,12 @@ public: }; protected: - mutable QMutex m_cacheMutex; - QMultiHash<QString,Data*> m_hCache; + mutable QMutex m_cacheMutex; + mutable QMutex m_timerMutex; + + QMultiHash<QString,Data*> m_hCache; + QMultiMap<long long,KviAnimatedPixmapInterface*> m_timerData; + QTimer m_animationTimer; /* * This class is a singletone. @@ -85,12 +96,19 @@ protected: Data* internalResize(Data* data,QSize size); void internalFree(Data* data); + void internalSceduleFrameChange(uint delay,KviAnimatedPixmapInterface* receiver); + void internalNotifyDelete(KviAnimatedPixmapInterface* receiver); +protected slots: + void timerEvent(); public: virtual ~KviAnimatedPixmapCache(); + static void sceduleFrameChange(uint delay,KviAnimatedPixmapInterface* receiver); static Data* load(QString szFileName); static Data* resize(Data* data,QSize size); static void free(Data* data); + static QPixmap* dummyPixmap(); + static void notifyDelete(KviAnimatedPixmapInterface* receiver); }; #endif /* KVI_ANIMATEDPIXMAPCACHE_H_ */ diff --git a/src/kvilib/irc/kvi_avatar.h b/src/kvilib/irc/kvi_avatar.h index 46c47d237..595859add 100644 --- a/src/kvilib/irc/kvi_avatar.h +++ b/src/kvilib/irc/kvi_avatar.h @@ -96,6 +96,15 @@ public: } /* + * Returns true if pixmap has at least one loaded frame. + * Returns false otherways. + */ + inline bool isValid() + { + return m_pPixmap->isValid(); + } + + /* * Returns original animated pixmap. */ inline KviAnimatedPixmap * animatedPixmap() { diff --git a/src/kvilib/system/kvi_time.cpp b/src/kvilib/system/kvi_time.cpp index 4c6af9f69..d3deb3f77 100644 --- a/src/kvilib/system/kvi_time.cpp +++ b/src/kvilib/system/kvi_time.cpp @@ -81,6 +81,14 @@ unsigned long KviMSecTimeInterval::mark() namespace KviTimeUtils { + long long getCurrentTimeMills() + { + struct timeval tmv; + kvi_gettimeofday(&tmv,0); + long long result = tmv.tv_sec * 1000 + tmv.tv_usec / 1000; + return result; + } + void secondsToDaysHoursMinsSecs(unsigned int uSecs, unsigned int * uD,unsigned int * uH,unsigned int * uM,unsigned int * uS) { diff --git a/src/kvilib/system/kvi_time.h b/src/kvilib/system/kvi_time.h index ff4042ccf..b0dd475dd 100644 --- a/src/kvilib/system/kvi_time.h +++ b/src/kvilib/system/kvi_time.h @@ -77,6 +77,7 @@ namespace KviTimeUtils { + long long getCurrentTimeMills(); // splits the time span uSecs in days, hours, minutes and seconds KVILIB_API void secondsToDaysHoursMinsSecs(unsigned int uSecs, unsigned int * uD,unsigned int * uH,unsigned int * uM,unsigned int * uS); diff --git a/src/kvirc/kernel/kvi_iconmanager.cpp b/src/kvirc/kernel/kvi_iconmanager.cpp index ece07194b..5460ee616 100644 --- a/src/kvirc/kernel/kvi_iconmanager.cpp +++ b/src/kvirc/kernel/kvi_iconmanager.cpp @@ -793,24 +793,31 @@ KviAvatar * KviIconManager::getAvatar(const QString &szLocalPath,const QString & //if(!p)return 0; + KviAvatar* result = 0; if(KviFileUtils::fileExists(szP)) { if(KVI_OPTION_BOOL(KviOption_boolScaleAvatarsOnLoad)) { - return new KviAvatar(szP,szN, + result = new KviAvatar(szP,szN, QSize( KVI_OPTION_UINT(KviOption_uintScaleAvatarsOnLoadWidth), KVI_OPTION_UINT(KviOption_uintScaleAvatarsOnLoadHeight) ) ); } else { - return new KviAvatar(szP,szN); + result = new KviAvatar(szP,szN); } - } else { - return 0; } + //Can't load it + if(result && !result->isValid()) + { + delete result; + result = 0; + } + + return result; } void KviIconManager::clearCache() diff --git a/src/kvirc/ui/kvi_console.cpp b/src/kvirc/ui/kvi_console.cpp index b86253114..a2a2ea597 100644 --- a/src/kvirc/ui/kvi_console.cpp +++ b/src/kvirc/ui/kvi_console.cpp @@ -997,7 +997,14 @@ KviAvatar * KviConsole::defaultAvatarFromOptions() if(!avatar)return 0; if(avatar->isNull())return 0; if(KVI_OPTION_STRING(KviOption_stringMyAvatar).isEmpty())return 0; - return new KviAvatar(KVI_OPTION_PIXMAP(KviOption_pixmapMyAvatar).path(),KVI_OPTION_STRING(KviOption_stringMyAvatar)); + KviAvatar * loadedAvatar = new KviAvatar(KVI_OPTION_PIXMAP(KviOption_pixmapMyAvatar).path(),KVI_OPTION_STRING(KviOption_stringMyAvatar)); + if(loadedAvatar->isValid()) + { + return loadedAvatar; + } else { + delete loadedAvatar; + return 0; + } } KviAvatar * KviConsole::currentAvatar() diff --git a/src/kvirc/ui/kvi_ircview.cpp b/src/kvirc/ui/kvi_ircview.cpp index d4c4d450a..cde6897c9 100644 --- a/src/kvirc/ui/kvi_ircview.cpp +++ b/src/kvirc/ui/kvi_ircview.cpp @@ -2042,7 +2042,7 @@ const kvi_wchar_t * KviIrcView::getTextLine(int iMsgType, static void * char_to_check_jump_table[256]= { - &&found_end_of_buffer ,0 ,&&found_mirc_escape ,&&found_color_escape , + &(&found_end_of_buffer),0 ,&&found_mirc_escape ,&&found_color_escape , 0 ,0 ,0 ,0 , 0 ,0 ,&&found_end_of_line ,0 , 0 ,&&found_command_escape ,0 ,&&found_mirc_escape , |
