source: vendor/trolltech/current/src/kernel/qpixmapcache.cpp

Last change on this file was 2, checked in by dmik, 20 years ago

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 9.7 KB
Line 
1/****************************************************************************
2** $Id: qpixmapcache.cpp 2 2005-11-16 15:49:26Z dmik $
3**
4** Implementation of QPixmapCache class
5**
6** Created : 950504
7**
8** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
9**
10** This file is part of the kernel module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#include "qpixmapcache.h"
39#include "qcache.h"
40#include "qobject.h"
41#include "qcleanuphandler.h"
42
43
44// REVISED: paul
45/*!
46 \class QPixmapCache qpixmapcache.h
47
48 \brief The QPixmapCache class provides an application-global cache for
49 pixmaps.
50
51 \ingroup environment
52 \ingroup graphics
53 \ingroup images
54
55 This class is a tool for optimized drawing with QPixmap. You can
56 use it to store temporary pixmaps that are expensive to generate
57 without using more storage space than cacheLimit(). Use insert()
58 to insert pixmaps, find() to find them and clear() to empty the
59 cache.
60
61 For example, QRadioButton has a non-trivial visual representation
62 so we don't want to regenerate a pixmap whenever a radio button is
63 displayed or changes state. In the function
64 QRadioButton::drawButton(), we do not draw the radio button
65 directly. Instead, we first check the global pixmap cache for a
66 pixmap with the key "$qt_radio_nnn_", where \c nnn is a numerical
67 value that specifies the the radio button state. If a pixmap is
68 found, we bitBlt() it onto the widget and return. Otherwise, we
69 create a new pixmap, draw the radio button in the pixmap, and
70 finally insert the pixmap in the global pixmap cache, using the
71 key above. The bitBlt() is ten times faster than drawing the
72 radio button. All radio buttons in the program share the cached
73 pixmap since QPixmapCache is application-global.
74
75 QPixmapCache contains no member data, only static functions to
76 access the global pixmap cache. It creates an internal QCache for
77 caching the pixmaps.
78
79 The cache associates a pixmap with a string (key). If two pixmaps
80 are inserted into the cache using equal keys, then the last pixmap
81 will hide the first pixmap. The QDict and QCache classes do
82 exactly the same.
83
84 The cache becomes full when the total size of all pixmaps in the
85 cache exceeds cacheLimit(). The initial cache limit is 1024 KByte
86 (1 MByte); it is changed with setCacheLimit(). A pixmap takes
87 roughly width*height*depth/8 bytes of memory.
88
89 See the \l QCache documentation for more details about the cache
90 mechanism.
91*/
92
93
94static const int cache_size = 149; // size of internal hash array
95#ifdef Q_WS_MAC9
96static int cache_limit = 256; // 256 KB cache limit
97#else
98static int cache_limit = 1024; // 1024 KB cache limit
99#endif
100
101class QPMCache: public QObject, public QCache<QPixmap>
102{
103public:
104 QPMCache():
105 QObject( 0, "global pixmap cache" ),
106 QCache<QPixmap>( cache_limit * 1024, cache_size ),
107 id( 0 ), ps( 0 ), t( FALSE )
108 {
109 setAutoDelete( TRUE );
110 }
111 ~QPMCache() {}
112 void timerEvent( QTimerEvent * );
113 bool insert( const QString& k, const QPixmap *d, int c, int p = 0 );
114private:
115 int id;
116 int ps;
117 bool t;
118};
119
120
121/*
122 This is supposed to cut the cache size down by about 80-90% in a
123 minute once the application becomes idle, to let any inserted pixmap
124 remain in the cache for some time before it becomes a candidate for
125 cleaning-up, and to not cut down the size of the cache while the
126 cache is in active use.
127
128 When the last pixmap has been deleted from the cache, kill the
129 timer so Qt won't keep the CPU from going into sleep mode.
130*/
131
132void QPMCache::timerEvent( QTimerEvent * )
133{
134 int mc = maxCost();
135 bool nt = totalCost() == ps;
136 setMaxCost( nt ? totalCost() * 3 / 4 : totalCost() -1 );
137 setMaxCost( mc );
138 ps = totalCost();
139
140 if ( !count() ) {
141 killTimer( id );
142 id = 0;
143 } else if ( nt != t ) {
144 killTimer( id );
145 id = startTimer( nt ? 10000 : 30000 );
146 t = nt;
147 }
148}
149
150bool QPMCache::insert( const QString& k, const QPixmap *d, int c, int p )
151{
152 bool r = QCache<QPixmap>::insert( k, d, c, p );
153 if ( r && !id ) {
154 id = startTimer( 30000 );
155 t = FALSE;
156 }
157 return r;
158}
159
160static QPMCache *pm_cache = 0; // global pixmap cache
161
162static QSingleCleanupHandler<QPMCache> qpm_cleanup_cache;
163
164/*!
165 Returns the pixmap associated with the \a key in the cache, or
166 null if there is no such pixmap.
167
168 \warning If valid, you should copy the pixmap immediately (this is
169 fast). Subsequent insertions into the cache could cause the
170 pointer to become invalid. For this reason, we recommend you use
171 find(const QString&, QPixmap&) instead.
172
173 Example:
174 \code
175 QPixmap* pp;
176 QPixmap p;
177 if ( (pp=QPixmapCache::find("my_big_image", pm)) ) {
178 p = *pp;
179 } else {
180 p.load("bigimage.png");
181 QPixmapCache::insert("my_big_image", new QPixmap(p));
182 }
183 painter->drawPixmap(0, 0, p);
184 \endcode
185*/
186
187QPixmap *QPixmapCache::find( const QString &key )
188{
189 return pm_cache ? pm_cache->find(key) : 0;
190}
191
192
193/*!
194 \overload
195
196 Looks for a cached pixmap associated with the \a key in the cache.
197 If a pixmap is found, the function sets \a pm to that pixmap and
198 returns TRUE; otherwise leaves \a pm alone and returns FALSE.
199
200 Example:
201 \code
202 QPixmap p;
203 if ( !QPixmapCache::find("my_big_image", pm) ) {
204 pm.load("bigimage.png");
205 QPixmapCache::insert("my_big_image", pm);
206 }
207 painter->drawPixmap(0, 0, p);
208 \endcode
209*/
210
211bool QPixmapCache::find( const QString &key, QPixmap& pm )
212{
213 QPixmap* p = pm_cache ? pm_cache->find(key) : 0;
214 if ( p ) pm = *p;
215 return !!p;
216}
217
218
219/*!
220 \obsolete
221 Inserts the pixmap \a pm associated with \a key into the cache.
222 Returns TRUE if successful, or FALSE if the pixmap is too big for the cache.
223
224 <strong>
225 Note: \a pm must be allocated on the heap (using \c new).
226
227 If this function returns FALSE, you must delete \a pm yourself.
228
229 If this function returns TRUE, do not use \a pm afterwards or
230 keep references to it because any other insertions into the cache,
231 whether from anywhere in the application or within Qt itself, could cause
232 the pixmap to be discarded from the cache and the pointer to
233 become invalid.
234
235 Due to these dangers, we strongly recommend that you use
236 insert(const QString&, const QPixmap&) instead.
237 </strong>
238*/
239
240bool QPixmapCache::insert( const QString &key, QPixmap *pm )
241{
242 if ( !pm_cache ) { // create pixmap cache
243 pm_cache = new QPMCache;
244 Q_CHECK_PTR( pm_cache );
245 qpm_cleanup_cache.set( &pm_cache );
246 }
247 return pm_cache->insert( key, pm, pm->width()*pm->height()*pm->depth()/8 );
248}
249
250/*!
251 Inserts a copy of the pixmap \a pm associated with the \a key into
252 the cache.
253
254 All pixmaps inserted by the Qt library have a key starting with
255 "$qt", so your own pixmap keys should never begin "$qt".
256
257 When a pixmap is inserted and the cache is about to exceed its
258 limit, it removes pixmaps until there is enough room for the
259 pixmap to be inserted.
260
261 The oldest pixmaps (least recently accessed in the cache) are
262 deleted when more space is needed.
263
264 \sa setCacheLimit().
265*/
266
267bool QPixmapCache::insert( const QString &key, const QPixmap& pm )
268{
269 if ( !pm_cache ) { // create pixmap cache
270 pm_cache = new QPMCache;
271 Q_CHECK_PTR( pm_cache );
272 qpm_cleanup_cache.set( &pm_cache );
273 }
274 QPixmap *p = new QPixmap(pm);
275 bool rt = pm_cache->insert( key, p, p->width()*p->height()*p->depth()/8 );
276 if ( !rt )
277 delete p;
278
279 return rt;
280}
281
282/*!
283 Returns the cache limit (in kilobytes).
284
285 The default setting is 1024 kilobytes.
286
287 \sa setCacheLimit().
288*/
289
290int QPixmapCache::cacheLimit()
291{
292 return cache_limit;
293}
294
295/*!
296 Sets the cache limit to \a n kilobytes.
297
298 The default setting is 1024 kilobytes.
299
300 \sa cacheLimit()
301*/
302
303void QPixmapCache::setCacheLimit( int n )
304{
305#ifdef Q_WS_MAC9
306 if(n > 256)
307 qWarning("QPixmapCache::setCacheLimit: Setting cache limits high is harmfull to mac9's health");
308#endif
309 cache_limit = n;
310 if ( pm_cache )
311 pm_cache->setMaxCost( 1024*cache_limit );
312}
313
314
315/*!
316 Removes the pixmap associated with \a key from the cache.
317*/
318void QPixmapCache::remove( const QString &key )
319{
320 if ( pm_cache )
321 pm_cache->remove( key );
322}
323
324
325/*!
326 Removes all pixmaps from the cache.
327*/
328
329void QPixmapCache::clear()
330{
331 if ( pm_cache )
332 pm_cache->clear();
333}
Note: See TracBrowser for help on using the repository browser.