summaryrefslogtreecommitdiffstats
path: root/src/gui/image
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/image')
-rw-r--r--src/gui/image/image.pri1
-rw-r--r--src/gui/image/qicon.cpp7
-rw-r--r--src/gui/image/qimage.cpp10
-rw-r--r--src/gui/image/qnativeimage.cpp6
-rw-r--r--src/gui/image/qnativeimage_p.h2
-rw-r--r--src/gui/image/qpixmap.cpp68
-rw-r--r--src/gui/image/qpixmap.h10
-rw-r--r--src/gui/image/qpixmap_mac.cpp8
-rw-r--r--src/gui/image/qpixmap_mac_p.h1
-rw-r--r--src/gui/image/qpixmap_raster.cpp19
-rw-r--r--src/gui/image/qpixmap_raster_p.h8
-rw-r--r--src/gui/image/qpixmap_win.cpp13
-rw-r--r--src/gui/image/qpixmap_x11.cpp10
-rw-r--r--src/gui/image/qpixmap_x11_p.h1
-rw-r--r--src/gui/image/qpixmapcache.cpp367
-rw-r--r--src/gui/image/qpixmapcache.h27
-rw-r--r--src/gui/image/qpixmapcache_p.h96
-rw-r--r--src/gui/image/qpixmapdata.cpp8
-rw-r--r--src/gui/image/qpixmapdata_p.h3
19 files changed, 559 insertions, 106 deletions
diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri
index ca52974..bf348af 100644
--- a/src/gui/image/image.pri
+++ b/src/gui/image/image.pri
@@ -22,6 +22,7 @@ HEADERS += \
image/qpixmap.h \
image/qpixmap_raster_p.h \
image/qpixmapcache.h \
+ image/qpixmapcache_p.h \
image/qpixmapdata_p.h \
image/qpixmapdatafactory_p.h \
image/qpixmapfilter_p.h
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index 3c71f15..471062f 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -304,6 +304,8 @@ QPixmap QPixmapIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::St
QString key = QLatin1String("$qt_icon_")
+ QString::number(pm.cacheKey())
+ QString::number(pe->mode)
+ + QString::number(qApp->palette().cacheKey())
+ + QLatin1Char('_')
+ QString::number(actualSize.width())
+ QLatin1Char('_')
+ QString::number(actualSize.height())
@@ -854,6 +856,9 @@ void QIcon::addPixmap(const QPixmap &pixmap, Mode mode, State state)
QImageWriter::supportedImageFormats() functions to retrieve a
complete list of the supported file formats.
+ Note: When you add a non-empty filename to a QIcon, the icon becomes
+ non-null, even if the file doesn't exist or points to a corrupt file.
+
\sa addPixmap()
*/
void QIcon::addFile(const QString &fileName, const QSize &size, Mode mode, State state)
@@ -919,7 +924,7 @@ QList<QSize> QIcon::availableSizes(Mode mode, State state) const
\relates QIcon
\since 4.2
- Writes the given \a icon to the the given \a stream as a PNG
+ Writes the given \a icon to the given \a stream as a PNG
image. If the icon contains more than one image, all images will
be written to the stream. Note that writing the stream to a file
will not produce a valid image file.
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index c7a20db..25c68bc 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -1691,8 +1691,12 @@ void QImage::setColorTable(const QVector<QRgb> colors)
d->colortable = colors;
d->has_alpha_clut = false;
- for (int i = 0; i < d->colortable.size(); ++i)
- d->has_alpha_clut |= (qAlpha(d->colortable.at(i)) != 255);
+ for (int i = 0; i < d->colortable.size(); ++i) {
+ if (qAlpha(d->colortable.at(i)) != 255) {
+ d->has_alpha_clut = true;
+ break;
+ }
+ }
}
/*!
@@ -4996,7 +5000,7 @@ QPoint QImage::offset() const
/*!
\fn void QImage::setOffset(const QPoint& offset)
- Sets the the number of pixels by which the image is intended to be
+ Sets the number of pixels by which the image is intended to be
offset by when positioning relative to other images, to \a offset.
\sa offset(), {QImage#Image Information}{Image Information}
diff --git a/src/gui/image/qnativeimage.cpp b/src/gui/image/qnativeimage.cpp
index 33e565c..dc01fe4 100644
--- a/src/gui/image/qnativeimage.cpp
+++ b/src/gui/image/qnativeimage.cpp
@@ -65,7 +65,7 @@ typedef struct {
QNativeImage::QNativeImage(int width, int height, QImage::Format format, bool isTextBuffer, QWidget *)
{
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
Q_UNUSED(isTextBuffer);
#endif
BITMAPINFO_MASK bmi;
@@ -78,7 +78,7 @@ QNativeImage::QNativeImage(int width, int height, QImage::Format format, bool is
if (format == QImage::Format_RGB16) {
bmi.bmiHeader.biBitCount = 16;
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (isTextBuffer) {
bmi.bmiHeader.biCompression = BI_RGB;
bmi.redMask = 0;
@@ -116,7 +116,7 @@ QNativeImage::QNativeImage(int width, int height, QImage::Format format, bool is
Q_ASSERT(image.paintEngine()->type() == QPaintEngine::Raster);
static_cast<QRasterPaintEngine *>(image.paintEngine())->setDC(hdc);
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
GdiFlush();
#endif
}
diff --git a/src/gui/image/qnativeimage_p.h b/src/gui/image/qnativeimage_p.h
index 860485a..6402af2 100644
--- a/src/gui/image/qnativeimage_p.h
+++ b/src/gui/image/qnativeimage_p.h
@@ -70,7 +70,7 @@ QT_BEGIN_NAMESPACE
class QWidget;
-class Q_GUI_EXPORT QNativeImage
+class QNativeImage
{
public:
QNativeImage(int width, int height, QImage::Format format, bool isTextBuffer = false, QWidget *widget = 0);
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index efb8260..3ca685c 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -379,6 +379,56 @@ QPixmap QPixmap::copy(const QRect &rect) const
}
/*!
+ \fn QPixmap::scroll(int dx, int dy, int x, int y, int width, int height, QRegion *exposed)
+
+ This convenience function is equivalent to calling QPixmap::scroll(\a dx,
+ \a dy, QRect(\a x, \a y, \a width, \a height), \a exposed).
+
+ \sa QWidget::scroll(), QGraphicsItem::scroll()
+*/
+
+/*!
+ Scrolls the area \a rect of this pixmap by (\a dx, \a dy). The exposed
+ region is left unchanged. You can optionally pass a pointer to an empty
+ QRegion to get the region that is \a exposed by the scroll operation.
+
+ \snippet doc/src/snippets/code/src_gui_image_qpixmap.cpp 2
+
+ You cannot scroll while there is an active painter on the pixmap.
+
+ \sa QWidget::scroll(), QGraphicsItem::scroll()
+*/
+void QPixmap::scroll(int dx, int dy, const QRect &rect, QRegion *exposed)
+{
+ if (isNull() || (dx == 0 && dy == 0))
+ return;
+ QRect dest = rect & this->rect();
+ QRect src = dest.translated(-dx, -dy) & dest;
+ if (src.isEmpty()) {
+ if (exposed)
+ *exposed += dest;
+ return;
+ }
+
+ detach();
+
+ if (!data->scroll(dx, dy, src)) {
+ // Fallback
+ QPixmap pix = *this;
+ QPainter painter(&pix);
+ painter.setCompositionMode(QPainter::CompositionMode_Source);
+ painter.drawPixmap(src.translated(dx, dy), *this, src);
+ painter.end();
+ *this = pix;
+ }
+
+ if (exposed) {
+ *exposed += dest;
+ *exposed -= src.translated(dx, dy);
+ }
+}
+
+/*!
Assigns the given \a pixmap to this pixmap and returns a reference
to this pixmap.
@@ -1232,7 +1282,7 @@ bool QPixmap::convertFromImage(const QImage &image, ColorMode mode)
/*!
\relates QPixmap
- Writes the given \a pixmap to the the given \a stream as a PNG
+ Writes the given \a pixmap to the given \a stream as a PNG
image. Note that writing the stream to a file will not produce a
valid image file.
@@ -1309,14 +1359,6 @@ bool QPixmap::isDetached() const
void QPixmap::deref()
{
if (data && !data->ref.deref()) { // Destroy image if last ref
-#if !defined(QT_NO_DIRECT3D) && defined(Q_WS_WIN)
- if (data->classId() == QPixmapData::RasterClass) {
- QRasterPixmapData *rData = static_cast<QRasterPixmapData*>(data);
- if (rData->texture)
- rData->texture->Release();
- rData->texture = 0;
- }
-#endif
if (data->is_cached && qt_pixmap_cleanup_hook_64)
qt_pixmap_cleanup_hook_64(cacheKey());
delete data;
@@ -1853,7 +1895,7 @@ int QPixmap::defaultDepth()
return QScreen::instance()->depth();
#elif defined(Q_WS_X11)
return QX11Info::appDepth();
-#elif defined(Q_OS_WINCE)
+#elif defined(Q_WS_WINCE)
return QColormap::instance().depth();
#elif defined(Q_WS_WIN)
return 32; // XXX
@@ -1888,12 +1930,6 @@ void QPixmap::detach()
if (id == QPixmapData::RasterClass) {
QRasterPixmapData *rasterData = static_cast<QRasterPixmapData*>(data);
rasterData->image.detach();
-#if defined(Q_WS_WIN) && !defined(QT_NO_DIRECT3D)
- if (rasterData->texture) {
- rasterData->texture->Release();
- rasterData->texture = 0;
- }
-#endif
}
if (data->is_cached && qt_pixmap_cleanup_hook_64 && data->ref == 1)
diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h
index 1863273..a5609e4 100644
--- a/src/gui/image/qpixmap.h
+++ b/src/gui/image/qpixmap.h
@@ -155,6 +155,9 @@ public:
inline QPixmap copy(int x, int y, int width, int height) const;
QPixmap copy(const QRect &rect = QRect()) const;
+ inline void scroll(int dx, int dy, int x, int y, int width, int height, QRegion *exposed = 0);
+ void scroll(int dx, int dy, const QRect &rect, QRegion *exposed = 0);
+
int serialNumber() const;
qint64 cacheKey() const;
@@ -251,8 +254,6 @@ private:
friend class QWidgetPrivate;
friend class QRasterPaintEngine;
friend class QRasterBuffer;
- friend class QDirect3DPaintEngine;
- friend class QDirect3DPaintEnginePrivate;
friend class QDetachedPixmap;
#if !defined(QT_NO_DATASTREAM)
friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QPixmap &);
@@ -274,6 +275,11 @@ inline QPixmap QPixmap::copy(int ax, int ay, int awidth, int aheight) const
return copy(QRect(ax, ay, awidth, aheight));
}
+inline void QPixmap::scroll(int dx, int dy, int ax, int ay, int awidth, int aheight, QRegion *exposed)
+{
+ scroll(dx, dy, QRect(ax, ay, awidth, aheight), exposed);
+}
+
inline bool QPixmap::loadFromData(const QByteArray &buf, const char *format,
Qt::ImageConversionFlags flags)
{
diff --git a/src/gui/image/qpixmap_mac.cpp b/src/gui/image/qpixmap_mac.cpp
index 26d9618..973cd78 100644
--- a/src/gui/image/qpixmap_mac.cpp
+++ b/src/gui/image/qpixmap_mac.cpp
@@ -1290,6 +1290,14 @@ void QMacPixmapData::copy(const QPixmapData *data, const QRect &rect)
has_mask = macData->has_mask;
}
+bool QMacPixmapData::scroll(int dx, int dy, const QRect &rect)
+{
+ Q_UNUSED(dx);
+ Q_UNUSED(dy);
+ Q_UNUSED(rect);
+ return false;
+}
+
/*!
\since 4.2
diff --git a/src/gui/image/qpixmap_mac_p.h b/src/gui/image/qpixmap_mac_p.h
index 75525c4..2b22e6b 100644
--- a/src/gui/image/qpixmap_mac_p.h
+++ b/src/gui/image/qpixmap_mac_p.h
@@ -68,6 +68,7 @@ public:
void resize(int width, int height);
void fromImage(const QImage &image, Qt::ImageConversionFlags flags);
void copy(const QPixmapData *data, const QRect &rect);
+ bool scroll(int dx, int dy, const QRect &rect);
int metric(QPaintDevice::PaintDeviceMetric metric) const;
void fill(const QColor &color);
diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp
index 7dfab70..b5556cd 100644
--- a/src/gui/image/qpixmap_raster.cpp
+++ b/src/gui/image/qpixmap_raster.cpp
@@ -50,12 +50,6 @@
#include <private/qwidget_p.h>
#include <private/qdrawhelper_p.h>
-#if !defined(QT_NO_DIRECT3D) && defined(Q_WS_WIN)
-#include <private/qpaintengine_d3d_p.h>
-#include <d3d9.h>
-extern QDirect3DPaintEngine *qt_d3dEngine();
-#endif
-
QT_BEGIN_NAMESPACE
const uchar qt_pixmap_bit_mask[] = { 0x01, 0x02, 0x04, 0x08,
@@ -63,9 +57,6 @@ const uchar qt_pixmap_bit_mask[] = { 0x01, 0x02, 0x04, 0x08,
QRasterPixmapData::QRasterPixmapData(PixelType type)
: QPixmapData(type, RasterClass)
-#if defined(Q_WS_WIN) && !defined(QT_NO_DIRECT3D)
- , texture(0)
-#endif
{
}
@@ -181,6 +172,16 @@ void QRasterPixmapData::fromImage(const QImage &sourceImage,
setSerialNumber(image.serialNumber());
}
+// from qwindowsurface.cpp
+extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset);
+
+bool QRasterPixmapData::scroll(int dx, int dy, const QRect &rect)
+{
+ if (!image.isNull())
+ qt_scrollRectInImage(image, rect, QPoint(dx, dy));
+ return true;
+}
+
void QRasterPixmapData::fill(const QColor &color)
{
uint pixel;
diff --git a/src/gui/image/qpixmap_raster_p.h b/src/gui/image/qpixmap_raster_p.h
index 095f378..9d3bf72 100644
--- a/src/gui/image/qpixmap_raster_p.h
+++ b/src/gui/image/qpixmap_raster_p.h
@@ -58,9 +58,6 @@
#ifdef Q_WS_WIN
# include "qt_windows.h"
-# ifndef QT_NO_DIRECT3D
-# include <d3d9.h>
-# endif
#endif
QT_BEGIN_NAMESPACE
@@ -75,6 +72,7 @@ public:
void fromFile(const QString &filename, Qt::ImageConversionFlags flags);
void fromImage(const QImage &image, Qt::ImageConversionFlags flags);
+ bool scroll(int dx, int dy, const QRect &rect);
void fill(const QColor &color);
void setMask(const QBitmap &mask);
bool hasAlphaChannel() const;
@@ -87,10 +85,6 @@ protected:
int metric(QPaintDevice::PaintDeviceMetric metric) const;
private:
-#if defined(Q_WS_WIN) && !defined(QT_NO_DIRECT3D)
- friend class QDirect3DPaintEnginePrivate;
- IDirect3DTexture9 *texture;
-#endif
friend class QPixmap;
friend class QBitmap;
friend class QDetachedPixmap;
diff --git a/src/gui/image/qpixmap_win.cpp b/src/gui/image/qpixmap_win.cpp
index 3ec441b..d4ebef7 100644
--- a/src/gui/image/qpixmap_win.cpp
+++ b/src/gui/image/qpixmap_win.cpp
@@ -59,7 +59,7 @@
#include "qdebug.h"
#include "qt_windows.h"
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
#include <winbase.h>
#include "qguifunctions_wince.h"
extern bool qt_wince_is_high_dpi();
@@ -80,7 +80,7 @@ QPixmap QPixmap::grabWindow(WId winId, int x, int y, int w, int h )
if (w < 0) w = r.right - r.left;
if (h < 0) h = r.bottom - r.top;
-#ifdef Q_OS_WINCE_WM
+#ifdef Q_WS_WINCE_WM
if (qt_wince_is_pocket_pc()) {
QWidget *widget = QWidget::find(winId);
if (qobject_cast<QDesktopWidget *>(widget)) {
@@ -101,7 +101,7 @@ QPixmap QPixmap::grabWindow(WId winId, int x, int y, int w, int h )
// copy data
HDC window_dc = GetDC(winId);
BitBlt(bitmap_dc, 0, 0, w, h, window_dc, x, y, SRCCOPY
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
| CAPTUREBLT
#endif
);
@@ -288,7 +288,7 @@ QPixmap QPixmap::fromWinHBITMAP(HBITMAP bitmap, HBitmapFormat format)
}
#ifdef Q_WS_WIN
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
static QImage qt_fromWinHBITMAP(HDC hdc, HBITMAP bitmap, int w, int h)
{
@@ -319,6 +319,7 @@ static QImage qt_fromWinHBITMAP(HDC hdc, HBITMAP bitmap, int w, int h)
} else {
qWarning("qt_fromWinHBITMAP(), failed to get bitmap bits");
}
+ qFree(data);
return image;
}
@@ -391,7 +392,7 @@ QPixmap convertHIconToPixmap( const HICON icon)
DeleteDC(hdc);
return QPixmap::fromImage(image);
}
-#else //ifndef Q_OS_WINCE
+#else //ifndef Q_WS_WINCE
QPixmap convertHIconToPixmap( const HICON icon, bool large)
{
HDC screenDevice = GetDC(0);
@@ -456,7 +457,7 @@ QPixmap convertHIconToPixmap( const HICON icon, bool large)
DeleteDC(hdc);
return QPixmap::fromImage(image);
}
-#endif //ifndef Q_OS_WINCE
+#endif //ifndef Q_WS_WINCE
QPixmap loadIconFromShell32( int resourceId, int size )
{
diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp
index 38916c7..d9c10db 100644
--- a/src/gui/image/qpixmap_x11.cpp
+++ b/src/gui/image/qpixmap_x11.cpp
@@ -2205,6 +2205,16 @@ void QX11PixmapData::copy(const QPixmapData *data, const QRect &rect)
}
}
+bool QX11PixmapData::scroll(int dx, int dy, const QRect &rect)
+{
+ GC gc = XCreateGC(X11->display, hd, 0, 0);
+ XCopyArea(X11->display, hd, hd, gc,
+ rect.left(), rect.top(), rect.width(), rect.height(),
+ rect.left() + dx, rect.top() + dy);
+ XFreeGC(X11->display, gc);
+ return true;
+}
+
#if !defined(QT_NO_XRENDER)
void QX11PixmapData::convertToARGB32(bool preserveContents)
{
diff --git a/src/gui/image/qpixmap_x11_p.h b/src/gui/image/qpixmap_x11_p.h
index 980b10e..c526402 100644
--- a/src/gui/image/qpixmap_x11_p.h
+++ b/src/gui/image/qpixmap_x11_p.h
@@ -74,6 +74,7 @@ public:
void resize(int width, int height);
void fromImage(const QImage &image, Qt::ImageConversionFlags flags);
void copy(const QPixmapData *data, const QRect &rect);
+ bool scroll(int dx, int dy, const QRect &rect);
void fill(const QColor &color);
QBitmap mask() const;
diff --git a/src/gui/image/qpixmapcache.cpp b/src/gui/image/qpixmapcache.cpp
index 458d6b9..810ce65 100644
--- a/src/gui/image/qpixmapcache.cpp
+++ b/src/gui/image/qpixmapcache.cpp
@@ -40,13 +40,9 @@
****************************************************************************/
#include "qpixmapcache.h"
-#include "qcache.h"
#include "qobject.h"
#include "qdebug.h"
-
-#include "qpaintengine.h"
-#include <private/qimage_p.h>
-#include <private/qpixmap_raster_p.h>
+#include "qpixmapcache_p.h"
QT_BEGIN_NAMESPACE
@@ -68,15 +64,17 @@ QT_BEGIN_NAMESPACE
access the global pixmap cache. It creates an internal QCache
object for caching the pixmaps.
- The cache associates a pixmap with a string (key). If two pixmaps
- are inserted into the cache using equal keys, then the last pixmap
- will hide the first pixmap. The QHash and QCache classes do
+ The cache associates a pixmap with a string as a key or with a QPixmapCache::Key.
+ The QPixmapCache::Key is faster than using strings as key.
+ If two pixmaps are inserted into the cache using equal keys, then the
+ last pixmap will hide the first pixmap. The QHash and QCache classes do
exactly the same.
The cache becomes full when the total size of all pixmaps in the
- cache exceeds cacheLimit(). The initial cache limit is 1024 KB (1
- MB); it is changed with setCacheLimit(). A pixmap takes roughly
- (\e{width} * \e{height} * \e{depth})/8 bytes of memory.
+ cache exceeds cacheLimit(). The initial cache limit is
+ 2048 KB(2 MB) for Embedded, 10240 KB (10
+ MB) for Desktops; it is changed with setCacheLimit().
+ A pixmap takes roughly (\e{width} * \e{height} * \e{depth})/8 bytes of memory.
The \e{Qt Quarterly} article
\l{http://doc.trolltech.com/qq/qq12-qpixmapcache.html}{Optimizing
@@ -86,58 +84,123 @@ QT_BEGIN_NAMESPACE
\sa QCache, QPixmap
*/
-#if defined(Q_WS_QWS) || defined(Q_OS_WINCE)
+#if defined(Q_WS_QWS) || defined(Q_WS_WINCE)
static int cache_limit = 2048; // 2048 KB cache limit for embedded
#else
static int cache_limit = 10240; // 10 MB cache limit for desktop
#endif
-// XXX: hw: is this a general concept we need to abstract?
-class QDetachedPixmap : public QPixmap
+/*!
+ Constructs an empty Key object.
+*/
+QPixmapCache::Key::Key() : d(0)
{
-public:
- QDetachedPixmap(const QPixmap &pix) : QPixmap(pix)
- {
- if (data && data->classId() == QPixmapData::RasterClass) {
- QRasterPixmapData *d = static_cast<QRasterPixmapData*>(data);
- if (!d->image.isNull() && d->image.d->paintEngine
- && !d->image.d->paintEngine->isActive())
- {
- delete d->image.d->paintEngine;
- d->image.d->paintEngine = 0;
- }
- }
+}
+
+/*!
+ \internal
+ Constructs a copy of \a other.
+*/
+QPixmapCache::Key::Key(const Key &other)
+{
+ if (other.d)
+ ++(other.d->ref);
+ d = other.d;
+}
+
+/*!
+ Destructor; called immediately before the object is deleted.
+*/
+QPixmapCache::Key::~Key()
+{
+ if (d && --(d->ref) == 0)
+ delete d;
+}
+
+/*!
+ \internal
+
+ Returns true if this key is the same as the given \a key.
+*/
+bool QPixmapCache::Key::operator ==(const Key &key) const
+{
+ return (d == key.d);
+}
+
+/*!
+ \internal
+*/
+QPixmapCache::Key &QPixmapCache::Key::operator =(const Key &other)
+{
+ if (d != other.d) {
+ if (other.d)
+ ++(other.d->ref);
+ if (d && --(d->ref) == 0)
+ delete d;
+ d = other.d;
}
-};
+ return *this;
+}
-class QPMCache : public QObject, public QCache<qint64, QDetachedPixmap>
+class QPMCache : public QObject, public QCache<QPixmapCache::Key, QDetachedPixmap>
{
Q_OBJECT
public:
- QPMCache()
- : QObject(0),
- QCache<qint64, QDetachedPixmap>(cache_limit * 1024),
- theid(0), ps(0), t(false) { }
- ~QPMCache() { }
+ QPMCache();
+ ~QPMCache();
void timerEvent(QTimerEvent *);
bool insert(const QString& key, const QPixmap &pixmap, int cost);
+ QPixmapCache::Key insert(const QPixmap &pixmap, int cost);
+ bool replace(const QPixmapCache::Key &key, const QPixmap &pixmap, int cost);
bool remove(const QString &key);
+ bool remove(const QPixmapCache::Key &key);
+
+ void resizeKeyArray(int size);
+ QPixmapCache::Key createKey();
+ void releaseKey(const QPixmapCache::Key &key);
+ void clear();
QPixmap *object(const QString &key) const;
+ QPixmap *object(const QPixmapCache::Key &key) const;
+
+ static inline QPixmapCache::KeyData *get(const QPixmapCache::Key &key)
+ {return key.d;}
+
+ static QPixmapCache::KeyData* getKeyData(QPixmapCache::Key *key);
private:
- QHash<QString, qint64> cacheKeys;
+ int *keyArray;
int theid;
int ps;
+ int keyArraySize;
+ int freeKey;
+ QHash<QString, QPixmapCache::Key> cacheKeys;
bool t;
};
+
QT_BEGIN_INCLUDE_NAMESPACE
#include "qpixmapcache.moc"
QT_END_INCLUDE_NAMESPACE
+static uint qHash(const QPixmapCache::Key &k)
+{
+ return qHash(QPMCache::get(k)->key);
+}
+
+QPMCache::QPMCache()
+ : QObject(0),
+ QCache<QPixmapCache::Key, QDetachedPixmap>(cache_limit * 1024),
+ keyArray(0), theid(0), ps(0), keyArraySize(0), freeKey(0), t(false)
+{
+}
+QPMCache::~QPMCache()
+{
+ free(keyArray);
+}
+
/*
- This is supposed to cut the cache size down by about 80-90% in a
+ This is supposed to cut the cache size down by about 25% in a
minute once the application becomes idle, to let any inserted pixmap
remain in the cache for some time before it becomes a candidate for
cleaning-up, and to not cut down the size of the cache while the
@@ -146,23 +209,28 @@ QT_END_INCLUDE_NAMESPACE
When the last pixmap has been deleted from the cache, kill the
timer so Qt won't keep the CPU from going into sleep mode.
*/
-
void QPMCache::timerEvent(QTimerEvent *)
{
int mc = maxCost();
bool nt = totalCost() == ps;
+ QList<QPixmapCache::Key> keys = QCache<QPixmapCache::Key, QDetachedPixmap>::keys();
setMaxCost(nt ? totalCost() * 3 / 4 : totalCost() -1);
setMaxCost(mc);
ps = totalCost();
- QHash<QString, qint64>::iterator it = cacheKeys.begin();
+ QHash<QString, QPixmapCache::Key>::iterator it = cacheKeys.begin();
while (it != cacheKeys.end()) {
if (!contains(it.value())) {
+ releaseKey(it.value());
it = cacheKeys.erase(it);
} else {
++it;
}
}
+ for (int i = 0; i < keys.size(); ++i) {
+ if (!contains(keys.at(i)))
+ releaseKey(keys.at(i));
+ }
if (!size()) {
killTimer(theid);
@@ -176,38 +244,154 @@ void QPMCache::timerEvent(QTimerEvent *)
QPixmap *QPMCache::object(const QString &key) const
{
- return QCache<qint64, QDetachedPixmap>::object(cacheKeys.value(key, -1));
+ QPixmapCache::Key cacheKey = cacheKeys.value(key);
+ if (!cacheKey.d || !cacheKey.d->isValid) {
+ const_cast<QPMCache *>(this)->cacheKeys.remove(key);
+ return 0;
+ }
+ QPixmap *ptr = QCache<QPixmapCache::Key, QDetachedPixmap>::object(cacheKey);
+ //We didn't find the pixmap in the cache, the key is not valid anymore
+ if (!ptr) {
+ const_cast<QPMCache *>(this)->cacheKeys.remove(key);
+ const_cast<QPMCache *>(this)->releaseKey(cacheKey);
+ }
+ return ptr;
}
+QPixmap *QPMCache::object(const QPixmapCache::Key &key) const
+{
+ Q_ASSERT(key.d->isValid);
+ QPixmap *ptr = QCache<QPixmapCache::Key, QDetachedPixmap>::object(key);
+ //We didn't find the pixmap in the cache, the key is not valid anymore
+ if (!ptr)
+ const_cast<QPMCache *>(this)->releaseKey(key);
+ return ptr;
+}
bool QPMCache::insert(const QString& key, const QPixmap &pixmap, int cost)
{
- qint64 cacheKey = pixmap.cacheKey();
- if (QCache<qint64, QDetachedPixmap>::object(cacheKey)) {
+ QPixmapCache::Key cacheKey;
+ QPixmapCache::Key oldCacheKey = cacheKeys.value(key);
+ //If for the same key we add already a pixmap we should delete it
+ if (oldCacheKey.d) {
+ QCache<QPixmapCache::Key, QDetachedPixmap>::remove(oldCacheKey);
+ cacheKey = oldCacheKey;
+ } else {
+ cacheKey = createKey();
+ }
+
+ bool success = QCache<QPixmapCache::Key, QDetachedPixmap>::insert(cacheKey, new QDetachedPixmap(pixmap), cost);
+ if (success) {
cacheKeys.insert(key, cacheKey);
- return true;
+ if (!theid) {
+ theid = startTimer(30000);
+ t = false;
+ }
+ } else {
+ //Insertion failed we released the new allocated key
+ releaseKey(cacheKey);
}
- qint64 oldCacheKey = cacheKeys.value(key, -1);
- //If for the same key we add already a pixmap we should delete it
- if (oldCacheKey != -1)
- QCache<qint64, QDetachedPixmap>::remove(oldCacheKey);
+ return success;
+}
- bool success = QCache<qint64, QDetachedPixmap>::insert(cacheKey, new QDetachedPixmap(pixmap), cost);
+QPixmapCache::Key QPMCache::insert(const QPixmap &pixmap, int cost)
+{
+ QPixmapCache::Key cacheKey = createKey();
+ bool success = QCache<QPixmapCache::Key, QDetachedPixmap>::insert(cacheKey, new QDetachedPixmap(pixmap), cost);
if (success) {
- cacheKeys.insert(key, cacheKey);
if (!theid) {
theid = startTimer(30000);
t = false;
}
+ } else {
+ //Insertion failed we released the key and return an invalid one
+ releaseKey(cacheKey);
+ }
+ return cacheKey;
+}
+
+bool QPMCache::replace(const QPixmapCache::Key &key, const QPixmap &pixmap, int cost)
+{
+ Q_ASSERT(key.d->isValid);
+ //If for the same key we add already a pixmap we should delete it
+ QCache<QPixmapCache::Key, QDetachedPixmap>::remove(key);
+
+ bool success = QCache<QPixmapCache::Key, QDetachedPixmap>::insert(key, new QDetachedPixmap(pixmap), cost);
+ if (success && !theid) {
+ theid = startTimer(30000);
+ t = false;
}
return success;
}
bool QPMCache::remove(const QString &key)
{
- qint64 cacheKey = cacheKeys.value(key, -1);
+ QPixmapCache::Key cacheKey = cacheKeys.value(key);
+ //The key was not in the cache
+ if (!cacheKey.d)
+ return false;
cacheKeys.remove(key);
- return QCache<qint64, QDetachedPixmap>::remove(cacheKey);
+ releaseKey(cacheKey);
+ return QCache<QPixmapCache::Key, QDetachedPixmap>::remove(cacheKey);
+}
+
+bool QPMCache::remove(const QPixmapCache::Key &key)
+{
+ releaseKey(key);
+ return QCache<QPixmapCache::Key, QDetachedPixmap>::remove(key);
+}
+
+void QPMCache::resizeKeyArray(int size)
+{
+ if (size <= keyArraySize || size == 0)
+ return;
+ keyArray = reinterpret_cast<int *>(realloc(keyArray, size * sizeof(int)));
+ for (int i = keyArraySize; i != size; ++i)
+ keyArray[i] = i + 1;
+ keyArraySize = size;
+}
+
+QPixmapCache::Key QPMCache::createKey()
+{
+ if (freeKey == keyArraySize)
+ resizeKeyArray(keyArraySize ? keyArraySize << 1 : 2);
+ int id = freeKey;
+ freeKey = keyArray[id];
+ QPixmapCache::Key key;
+ QPixmapCache::KeyData *d = QPMCache::getKeyData(&key);
+ d->key = ++id;
+ return key;
+}
+
+void QPMCache::releaseKey(const QPixmapCache::Key &key)
+{
+ if (key.d->key > keyArraySize || key.d->key <= 0)
+ return;
+ key.d->key--;
+ keyArray[key.d->key] = freeKey;
+ freeKey = key.d->key;
+ key.d->isValid = false;
+ key.d->key = 0;
+}
+
+void QPMCache::clear()
+{
+ free(keyArray);
+ keyArray = 0;
+ freeKey = 0;
+ keyArraySize = 0;
+ //Mark all keys as invalid
+ QList<QPixmapCache::Key> keys = QCache<QPixmapCache::Key, QDetachedPixmap>::keys();
+ for (int i = 0; i < keys.size(); ++i)
+ keys.at(i).d->isValid = false;
+ QCache<QPixmapCache::Key, QDetachedPixmap>::clear();
+}
+
+QPixmapCache::KeyData* QPMCache::getKeyData(QPixmapCache::Key *key)
+{
+ if (!key->d)
+ key->d = new QPixmapCache::KeyData;
+ return key->d;
}
Q_GLOBAL_STATIC(QPMCache, pm_cache)
@@ -222,7 +406,7 @@ Q_GLOBAL_STATIC(QPMCache, pm_cache)
\warning If valid, you should copy the pixmap immediately (this is
fast). Subsequent insertions into the cache could cause the
pointer to become invalid. For this reason, we recommend you use
- find(const QString&, QPixmap&) instead.
+ bool find(const QString&, QPixmap*) instead.
Example:
\snippet doc/src/snippets/code/src_gui_image_qpixmapcache.cpp 0
@@ -235,6 +419,17 @@ QPixmap *QPixmapCache::find(const QString &key)
/*!
+ \obsolete
+
+ Use bool find(const QString&, QPixmap*) instead.
+*/
+
+bool QPixmapCache::find(const QString &key, QPixmap& pixmap)
+{
+ return find(key, &pixmap);
+}
+
+/*!
Looks for a cached pixmap associated with the \a key in the cache.
If the pixmap is found, the function sets \a pm to that pixmap and
returns true; otherwise it leaves \a pm alone and returns false.
@@ -243,14 +438,31 @@ QPixmap *QPixmapCache::find(const QString &key)
\snippet doc/src/snippets/code/src_gui_image_qpixmapcache.cpp 1
*/
-bool QPixmapCache::find(const QString &key, QPixmap& pm)
+bool QPixmapCache::find(const QString &key, QPixmap* pixmap)
{
QPixmap *ptr = pm_cache()->object(key);
- if (ptr)
- pm = *ptr;
+ if (ptr && pixmap)
+ *pixmap = *ptr;
return ptr != 0;
}
+/*!
+ Looks for a cached pixmap associated with the \a key in the cache.
+ If the pixmap is found, the function sets \a pm to that pixmap and
+ returns true; otherwise it leaves \a pm alone and returns false. If
+ the pixmap is not found, it means that the \a key is not valid anymore,
+ so it will be released for the next insertion.
+*/
+bool QPixmapCache::find(const Key &key, QPixmap* pixmap)
+{
+ //The key is not valid anymore, a flush happened before probably
+ if (!key.d || !key.d->isValid)
+ return false;
+ QPixmap *ptr = pm_cache()->object(key);
+ if (ptr && pixmap)
+ *pixmap = *ptr;
+ return ptr != 0;
+}
/*!
Inserts a copy of the pixmap \a pm associated with the \a key into
@@ -272,9 +484,43 @@ bool QPixmapCache::find(const QString &key, QPixmap& pm)
\sa setCacheLimit()
*/
-bool QPixmapCache::insert(const QString &key, const QPixmap &pm)
+bool QPixmapCache::insert(const QString &key, const QPixmap &pixmap)
+{
+ return pm_cache()->insert(key, pixmap, pixmap.width() * pixmap.height() * pixmap.depth() / 8);
+}
+
+/*!
+ Inserts a copy of the pixmap \a pm into
+ the cache and return you the key. The key is always greater than 0.
+ If the key is equals 0 then the insertion failed.
+
+ When a pixmap is inserted and the cache is about to exceed its
+ limit, it removes pixmaps until there is enough room for the
+ pixmap to be inserted.
+
+ The oldest pixmaps (least recently accessed in the cache) are
+ deleted when more space is needed.
+
+ \sa setCacheLimit(), replace()
+*/
+QPixmapCache::Key QPixmapCache::insert(const QPixmap &pixmap)
+{
+ return pm_cache()->insert(pixmap, pixmap.width() * pixmap.height() * pixmap.depth() / 8);
+}
+
+/*!
+ Replace the pixmap associated to the \a key into
+ the cache. It return true if the pixmap \a pm has been correctly
+ inserted into the cache false otherwise.
+
+ \sa setCacheLimit(), insert()
+*/
+bool QPixmapCache::replace(const Key &key, const QPixmap &pixmap)
{
- return pm_cache()->insert(key, pm, pm.width() * pm.height() * pm.depth() / 8);
+ //The key is not valid anymore, a flush happened before probably
+ if (!key.d || !key.d->isValid)
+ return false;
+ return pm_cache()->replace(key, pixmap, pixmap.width() * pixmap.height() * pixmap.depth() / 8);
}
/*!
@@ -314,6 +560,17 @@ void QPixmapCache::remove(const QString &key)
pm_cache()->remove(key);
}
+/*!
+ Removes the pixmap associated with \a key from the cache and release
+ the key for a future insertion.
+*/
+void QPixmapCache::remove(const Key &key)
+{
+ //The key is not valid anymore, a flush happened before probably
+ if (!key.d || !key.d->isValid)
+ return;
+ pm_cache()->remove(key);
+}
/*!
Removes all pixmaps from the cache.
diff --git a/src/gui/image/qpixmapcache.h b/src/gui/image/qpixmapcache.h
index 2750a88..ae64310 100644
--- a/src/gui/image/qpixmapcache.h
+++ b/src/gui/image/qpixmapcache.h
@@ -53,12 +53,35 @@ QT_MODULE(Gui)
class Q_GUI_EXPORT QPixmapCache
{
public:
+ class KeyData;
+ class Key
+ {
+ public:
+ Key();
+ Key(const Key &other);
+ ~Key();
+ bool operator ==(const Key &key) const;
+ inline bool operator !=(const Key &key) const
+ { return !operator==(key); }
+ Key &operator =(const Key &other);
+
+ private:
+ KeyData *d;
+ friend class QPMCache;
+ friend class QPixmapCache;
+ };
+
static int cacheLimit();
static void setCacheLimit(int);
static QPixmap *find(const QString &key);
- static bool find(const QString &key, QPixmap&);
- static bool insert(const QString &key, const QPixmap&);
+ static bool find(const QString &key, QPixmap &pixmap);
+ static bool find(const QString &key, QPixmap *pixmap);
+ static bool find(const Key &key, QPixmap *pixmap);
+ static bool insert(const QString &key, const QPixmap &pixmap);
+ static Key insert(const QPixmap &pixmap);
+ static bool replace(const Key &key, const QPixmap &pixmap);
static void remove(const QString &key);
+ static void remove(const Key &key);
static void clear();
};
diff --git a/src/gui/image/qpixmapcache_p.h b/src/gui/image/qpixmapcache_p.h
new file mode 100644
index 0000000..5aa6eaf
--- /dev/null
+++ b/src/gui/image/qpixmapcache_p.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPIXMAPCACHE_P_H
+#define QPIXMAPCACHE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qpixmapcache.h"
+#include "qpaintengine.h"
+#include <private/qimage_p.h>
+#include <private/qpixmap_raster_p.h>
+#include "qcache.h"
+
+QT_BEGIN_NAMESPACE
+
+class QPixmapCache::KeyData
+{
+public:
+ KeyData() : isValid(true), key(0), ref(1) {}
+ KeyData(const KeyData &other)
+ : isValid(other.isValid), key(other.key), ref(1) {}
+ ~KeyData() {}
+
+ bool isValid;
+ int key;
+ int ref;
+};
+
+// XXX: hw: is this a general concept we need to abstract?
+class QDetachedPixmap : public QPixmap
+{
+public:
+ QDetachedPixmap(const QPixmap &pix) : QPixmap(pix)
+ {
+ if (data && data->classId() == QPixmapData::RasterClass) {
+ QRasterPixmapData *d = static_cast<QRasterPixmapData*>(data);
+ if (!d->image.isNull() && d->image.d->paintEngine
+ && !d->image.d->paintEngine->isActive())
+ {
+ delete d->image.d->paintEngine;
+ d->image.d->paintEngine = 0;
+ }
+ }
+ }
+};
+
+QT_END_NAMESPACE
+
+#endif // QPIXMAPCACHE_P_H
diff --git a/src/gui/image/qpixmapdata.cpp b/src/gui/image/qpixmapdata.cpp
index 3d88f4b..245a866 100644
--- a/src/gui/image/qpixmapdata.cpp
+++ b/src/gui/image/qpixmapdata.cpp
@@ -73,6 +73,14 @@ void QPixmapData::copy(const QPixmapData *data, const QRect &rect)
fromImage(data->toImage().copy(rect), Qt::AutoColor);
}
+bool QPixmapData::scroll(int dx, int dy, const QRect &rect)
+{
+ Q_UNUSED(dx);
+ Q_UNUSED(dy);
+ Q_UNUSED(rect);
+ return false;
+}
+
void QPixmapData::setMask(const QBitmap &mask)
{
if (mask.size().isEmpty()) {
diff --git a/src/gui/image/qpixmapdata_p.h b/src/gui/image/qpixmapdata_p.h
index 7296426..27bc70d 100644
--- a/src/gui/image/qpixmapdata_p.h
+++ b/src/gui/image/qpixmapdata_p.h
@@ -78,6 +78,7 @@ public:
virtual void fromFile(const QString &filename, const char *format,
Qt::ImageConversionFlags flags);
virtual void copy(const QPixmapData *data, const QRect &rect);
+ virtual bool scroll(int dx, int dy, const QRect &rect);
virtual int metric(QPaintDevice::PaintDeviceMetric metric) const = 0;
virtual void fill(const QColor &color) = 0;
@@ -121,7 +122,7 @@ private:
};
#ifdef Q_WS_WIN
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
QPixmap convertHIconToPixmap( const HICON icon);
#else
QPixmap convertHIconToPixmap( const HICON icon, bool large = false);