aboutsummaryrefslogtreecommitdiffstats
#ifndef KVI_ANIMATEDPIXMAP_H_
#define KVI_ANIMATEDPIXMAP_H_
//=============================================================================
//
//   File : KviAnimatedPixmap.h
//   Creation date : Wed Jul 30 2008 01:45:21 CEST by Alexey Uzhva
//
//   This file is part of the KVIrc IRC client distribution
//   Copyright (C) 2008 Alexey Uzhva (wizard at opendoor dot ru)
//
//   This program is FREE software. You can redistribute it and/or
//   modify it under the terms of the GNU General Public License
//   as published by the Free Software Foundation; either version 2
//   of the License, or (at your option) any later version.
//
//   This program is distributed in the HOPE that it will be USEFUL,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//   See the GNU General Public License for more details.
//
//   You should have received a copy of the GNU General Public License
//   along with this program. If not, write to the Free Software Foundation,
//   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
//=============================================================================

#include "kvi_settings.h"
#include "KviAnimatedPixmapCache.h"

#include <QObject>
#include <QString>
#include <QTimer>

class QPixmap;

/**
 * This class should not be here, because we already have QMovie
 * with the same functionality.
 *
 * But QMovie is really stupid, bacause:
 * 	1) It does not support infinitive animation.
 *     It relies on image metadata to determine loop count. So most of pics will
 *     be played only once.
 *
 *  2) It duplicates QPixmap while we calls currentFrame(), that's a very
 *     big overload for us.
 *
 *  3) If we try to scale QMovie by using built-in scale mechanism, it will
 *     manually scale each frame each time, we will call currentFrame().
 *     So if we plan to play movie 10,100,1000 times, it will scale image
 *     10,100,1000 times too:(
 *
 *  4) KviAnimatedPixmap uses internal cache mechanism with KviAnimatedPixmapCache class.
 *     It's managed inside KviAnimatedPixmap and KviAnimatedPixmapCache. No other actions
 *     needed to perform caching.
 *
 * So... Here is my workaround. It's working in this way:
 * You should create new pixmap with constructor KviAnimatedPixmap(QString fileName).
 * It will automagically look at cache and use it, if possible.
 *
 * KviAnimatedPixmap stores animation as a set of QPixmap's, and delays.
 * when started (see start()) it emits frameChanged() events at the frame change.
 *
 * You should use pixmap() methd to access the current frame.
 *
 * This class owns all pixmaps. Do not store links to them.
 */

class KVILIB_API KviAnimatedPixmap : public QObject, public KviAnimatedPixmapInterface
{
	Q_OBJECT
protected:
	QString m_szFileName;
	KviAnimatedPixmapCache::Data * m_pFrameData;

	uint m_uCurrentFrameNumber;
	int m_iStarted;

public:
	/*
	* Creates KviAnimatedPixmap, and loads data from "fileName".
	*/
	KviAnimatedPixmap(QString fileName, int iWidth = 0, int iHeight = 0);

	virtual ~KviAnimatedPixmap();

	/*
	 * Creates new pixmap using "source" as source of images.
	 */
	KviAnimatedPixmap(const KviAnimatedPixmap & source);

	/*
	 * Returns true if animation is started.
	 * Returns false otherways.
	 */
	bool isStarted() const
	{
		return m_iStarted > 0;
	}

	/*
	 * Starts the animation
	 */
	void start();

	/*
	 * Stops the animation
	 */
	void stop();

	/*
	 * Returns true if animation has at least one loaded frame.
	 * Returns false otherways.
	 */
	bool isValid() const
	{
		return (m_pFrameData->count() > 0);
	}

	/*
	 * Returns active frame's pixmap.
	 * Never fails.
	 */

	QPixmap * pixmap()
	{
		if(m_pFrameData->count() > 0)
			return m_pFrameData->at(m_uCurrentFrameNumber).pixmap;
		else
			return KviAnimatedPixmapCache::dummyPixmap();
	}

	/*
	 * Returns active frame number
	 */
	uint activeFrameNumber() const
	{
		return m_uCurrentFrameNumber;
	}

	/*
	 * Returns animation frame count
	 */
	uint framesCount() const
	{
		return m_pFrameData->count();
	}

	/*
	 * Returns current image size
	 */
	const QSize & size() const
	{
		return m_pFrameData->size;
	}

	/*
	 * Resizes all frames to the newSize size, using "ratioMode"
	 * ratio.
	 */
	void resize(QSize newSize, Qt::AspectRatioMode ratioMode);

	/*
	 * Called when the frame changes
	 */
	void nextFrame(bool bEmitSignalAndScheduleNext);

signals:

	/*
	 * Slot, to be connected to m_animationTimer, to receive animation
	 * frame changes.
	 */
	void frameChanged();
};

#endif /* KVI_ANIMATEDPIXMAP_H_ */