~ubuntu-branches/ubuntu/raring/libkdegames/raring-proposed

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
/***************************************************************************
 *   Copyright 2010-2012 Stefan Majewsky <majewsky@gmx.net>                *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Library General Public License          *
 *   version 2 as published by the Free Software Foundation                *
 *                                                                         *
 *   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 Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library 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.         *
 ***************************************************************************/

#ifndef KGAMERENDERER_H
#define KGAMERENDERER_H

class QGraphicsView;
#include <QtCore/QHash>
#include <QtCore/QObject>
#include <QtGui/QPixmap>

#include <libkdegames_export.h>

class KGameRendererPrivate;
class KGameRendererClient;
class KGameRendererClientPrivate;
class KgTheme;
class KgThemeProvider;

#ifndef KDEGAMES_QCOLOR_QHASH
#	define KDEGAMES_QCOLOR_QHASH
	inline uint qHash(const QColor& color)
	{
		return color.rgba();
	}
#endif // KDEGAMES_QCOLOR_QHASH

/**
 * @class KGameRenderer  kgamerenderer.h <KGameRenderer>
 * @since 4.6
 * @short Cache-enabled rendering of SVG themes.
 *
 * KGameRenderer is a light-weight rendering framework for the rendering of
 * SVG themes (as represented by KgTheme) into pixmap caches.
 *
 * @section terminology Terminology
 *
 * @li Themes in the context of KGameRenderer are KgTheme instances. The theme
 *     selection by a KgRenderer can be managed by a KgThemeProvider.
 * @li A sprite is either a single pixmap ("non-animated sprites") or a sequence
 *     of pixmaps which are shown consecutively to produce an animation
 *     ("animated sprites"). Non-animated sprites correspond to a single element
 *     with the same key in the SVG theme file. The element keys for the pixmaps
 *     of an animated sprite are produced by appending the frameSuffix() to the
 *     sprite key.
 *
 * @section clients Access to the pixmaps
 *
 * Sprite pixmaps can be retrieved from KGameRenderer in the main thread using
 * the synchronous KGameRenderer::spritePixmap() method. However, it is highly
 * recommended to use the asynchronous interface provided by the interface class
 * KGameRendererClient. A client corresponds to one pixmap and registers itself
 * with the corresponding KGameRenderer instance to get notified when a new
 * pixmap is available.
 *
 * For QGraphicsView-based applications, the KGameRenderedItem class provides a
 * QGraphicsPixmapItem which is a KGameRendererClient and displays the pixmap
 * for a given sprite.
 *
 * @section strategies Rendering strategy
 *
 * For each theme, KGameRenderer keeps two caches around: an in-process cache of
 * QPixmaps, and a disk cache containing QImages (powered by KImageCache). You
 * therefore will not need to implement any caching for the pixmaps provided by
 * KGameRenderer.
 *
 * When requests from a KGameRendererClient cannot be served immediately because
 * the requested sprite is not in the caches, a rendering request is sent to a
 * worker thread.
 *
 * @section legacy Support for legacy themes
 *
 * When porting applications to KGameRenderer, you probably have to support
 * the format of existing themes. KGameRenderer provides the frameBaseIndex()
 * and frameSuffix() properties for this purpose. It is recommended not to
 * change these properties in new applications.
 *
 */
class KDEGAMES_EXPORT KGameRenderer : public QObject
{
	Q_OBJECT
	Q_PROPERTY(const KgTheme* theme READ theme NOTIFY themeChanged)
	Q_PROPERTY(KgThemeProvider* themeProvider READ themeProvider NOTIFY readOnlyProperty)
	public:
		///Describes the various strategies which KGameRenderer can use to speed
		///up rendering.
		///\see setStrategyEnabled
		enum Strategy
		{
			///If set, pixmaps will be cached in a shared disk cache (using
			///KSharedDataCache). This is especially useful for complex SVG
			///themes because KGameRenderer will not load the SVG if all needed
			///pixmaps are available from the disk cache.
			UseDiskCache = 1 << 0,
			///If set, pixmap requests from KGameRendererClients will be
			///handled asynchronously if possible. This is especially useful
			///when many clients are requesting complex pixmaps at one time.
			UseRenderingThreads = 1 << 1
		};
		Q_DECLARE_FLAGS(Strategies, Strategy)

		///Constructs a new KGameRenderer that renders @a prov->currentTheme().
		///@param cacheSize the cache size in megabytes (if not given, a sane
		///default is used)
		///@warning This constructor may only be called from the main thread.
		explicit KGameRenderer(KgThemeProvider* prov, unsigned cacheSize = 0);
		///@overload that allows to use KGameRenderer without a theme provider
		///          (useful when there is only one theme)
		///@note Takes ownership of @a theme.
		explicit KGameRenderer(KgTheme* theme, unsigned cacheSize = 0);
		///Deletes this KGameRenderer instance, as well as all clients using it.
		virtual ~KGameRenderer();

		///@return the primary view which is used by newly created
		///KGameRenderedItem instances associated with this renderer
		///@see KGameRenderedItem::setPrimaryView
		QGraphicsView* defaultPrimaryView() const;
		///Set the primary view which will be used by newly created
		///KGameRenderedItem instances associated with this renderer.
		///Calls to this method will have no effect on existing instances.
		///@see KGameRenderedItem::setPrimaryView
		void setDefaultPrimaryView(QGraphicsView* view);
		///@return the frame base index. @see setFrameBaseIndex()
		int frameBaseIndex() const;
		///Sets the frame base index, i.e. the lowest frame index. Usually,
		///frame numbering starts at zero, so the frame base index is zero.
		///
		///For example, if you set the frame base index to 42, and use the
		///default frame suffix, the 3 frames of an animated sprite "foo" are
		///provided by the SVG elements "foo_42", "foo_43" and "foo_44".
		///
		///It is recommended not to alter the frame base index unless you need
		///to support legacy themes.
		void setFrameBaseIndex(int frameBaseIndex);
		///@return the frame suffix. @see setFrameSuffix()
		QString frameSuffix() const;
		///Sets the frame suffix. This suffix will be added to a sprite key
		///to create the corresponding SVG element key, after any occurrence of
		///"%1" in the suffix has been replaced by the frame number.
		///@note Giving a suffix which does not include "%1" will reset to the
		///default suffix "_%1".
		///
		///For example, if the frame suffix is set to "_%1" (the default), the
		///SVG element key for the frame no. 23 of the sprite "foo" is "foo_23".
		///@note Frame numbering starts at zero unless you setFrameBaseIndex().
		void setFrameSuffix(const QString& suffix);
		///@return the optimization strategies used by this renderer
		///@see setStrategyEnabled()
		Strategies strategies() const;
		///Enables/disables an optimization strategy for this renderer. By
		///default, both the UseDiskCache and the UseRenderingThreads strategies
		///are enabled. This is a sane default for 99% of all games. You might 
		///only want to disable optimizations if the graphics are so simple that
		///the optimisations create an overhead in your special case.
		///
		///If you disable UseDiskCache, you should do so before setTheme(),
		///because changes to UseDiskCache cause a full theme reload.
		void setStrategyEnabled(Strategy strategy, bool enabled = true);

		///@return the KgTheme instance used by this renderer
		const KgTheme* theme() const;
		///@return the KgThemeProvider instance used by this renderer, or 0 if
		///        the renderer was created with a single static theme
		KgThemeProvider* themeProvider() const;

		///@return the bounding rectangle of the sprite with this @a key
		///This is equal to QSvgRenderer::boundsOnElement() of the corresponding
		///SVG element.
		QRectF boundsOnSprite(const QString& key, int frame = -1) const;
		///@return the count of frames available for the sprite with this @a key
		///If this sprite is not animated (i.e. there are no SVG elements for
		///any frames), this method returns 0. If the sprite does not exist at
		///all, -1 is returned.
		///
		///If the sprite is animated, the method counts frames starting at zero
		///(unless you change the frameBaseIndex()), and returns the number of
		///frames for which corresponding elements exist in the SVG file.
		///
		///For example, if the SVG contains the elements "foo_0", "foo_1" and
		///"foo_3", frameCount("foo") returns 2 for the default frame suffix.
		///(The element "foo_3" is ignored because "foo_2" is missing.)
		int frameCount(const QString& key) const;
		///@return if the sprite with the given @a key exists
		///This is the same as \code renderer.frameCount(key) >= 0 \endcode
		bool spriteExists(const QString& key) const;
		///@return a rendered pixmap
		///@param key the key of the sprite
		///@param size the size of the resulting pixmap
		///@param frame the number of the frame which you want
		///@param customColors the custom color replacements for this client.
		///       That is, for each entry in this has, the key color will be
		///       replaced by its value if it is encountered in the sprite.
		///@note  For non-animated frames, set @a frame to -1 or omit it.
		///@note  Custom colors increase the rendering time considerably, so use
		///       this feature only if you really need its flexibility.

		// The parentheses around QHash<QColor, QColor>() avoid compile
		// errors on platforms with older gcc versions, e.g. OS X 10.6.
		QPixmap spritePixmap(const QString& key, const QSize& size, int frame = -1, const QHash<QColor, QColor>& customColors = (QHash<QColor, QColor>())) const;
	Q_SIGNALS:
		void themeChanged(const KgTheme* theme);
		///This signal is never emitted. It is provided because QML likes to
		///complain about properties without NOTIFY signals, even readonly ones.
		void readOnlyProperty();
	private:
		friend class KGameRendererPrivate;
		friend class KGameRendererClient;
		friend class KGameRendererClientPrivate;
		KGameRendererPrivate* const d;
		Q_PRIVATE_SLOT(d, void _k_setTheme(const KgTheme*));
};

Q_DECLARE_OPERATORS_FOR_FLAGS(KGameRenderer::Strategies)

#endif // KGAMERENDERER_H