summaryrefslogtreecommitdiff
path: root/src/gui/image/qpixmap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/image/qpixmap.cpp')
-rw-r--r--src/gui/image/qpixmap.cpp277
1 files changed, 132 insertions, 145 deletions
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index e7fc000978..7f5b943fe3 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -43,6 +43,7 @@
#include "qpixmap.h"
#include "qpixmapdata_p.h"
+#include "qimagepixmapcleanuphooks_p.h"
#include "qbitmap.h"
#include "qcolormap.h"
@@ -76,19 +77,15 @@
# include <private/qpixmap_x11_p.h>
#endif
+#if defined(Q_OS_SYMBIAN)
+# include <private/qt_s60_p.h>
+#endif
+
#include "qpixmap_raster_p.h"
QT_BEGIN_NAMESPACE
// ### Qt 5: remove
-typedef void (*_qt_pixmap_cleanup_hook)(int);
-Q_GUI_EXPORT _qt_pixmap_cleanup_hook qt_pixmap_cleanup_hook = 0;
-
-// ### Qt 5: rename
-typedef void (*_qt_pixmap_cleanup_hook_64)(qint64);
-Q_GUI_EXPORT _qt_pixmap_cleanup_hook_64 qt_pixmap_cleanup_hook_64 = 0;
-
-// ### Qt 5: remove
Q_GUI_EXPORT qint64 qt_pixmap_id(const QPixmap &pixmap)
{
return pixmap.cacheKey();
@@ -123,7 +120,6 @@ void QPixmap::init(int w, int h, int type)
data = QGraphicsSystem::createDefaultPixmapData(static_cast<QPixmapData::PixelType>(type));
data->resize(w, h);
- data->ref.ref();
}
/*!
@@ -225,7 +221,6 @@ QPixmap::QPixmap(const QSize &s, int type)
QPixmap::QPixmap(QPixmapData *d)
: QPaintDevice(), data(d)
{
- data->ref.ref();
}
/*!
@@ -281,11 +276,9 @@ QPixmap::QPixmap(const QPixmap &pixmap)
return;
}
if (pixmap.paintingActive()) { // make a deep copy
- data = 0;
operator=(pixmap.copy());
} else {
data = pixmap.data;
- data->ref.ref();
}
}
@@ -329,7 +322,8 @@ QPixmap::QPixmap(const char * const xpm[])
QPixmap::~QPixmap()
{
- deref();
+ if (data->is_cached && data->ref == 1)
+ QImagePixmapCleanupHooks::executePixmapHooks(this);
}
/*!
@@ -374,11 +368,64 @@ QPixmap QPixmap::copy(const QRect &rect) const
else
d = QGraphicsSystem::createDefaultPixmapData(data->pixelType());
- d->copy(data, r);
+ d->copy(data.data(), r);
return QPixmap(d);
}
/*!
+ \fn QPixmap::scroll(int dx, int dy, int x, int y, int width, int height, QRegion *exposed)
+ \since 4.6
+
+ 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()
+*/
+
+/*!
+ \since 4.6
+
+ 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.
@@ -394,8 +441,6 @@ QPixmap &QPixmap::operator=(const QPixmap &pixmap)
if (pixmap.paintingActive()) { // make a deep copy
*this = pixmap.copy();
} else {
- pixmap.data->ref.ref(); // avoid 'x = x'
- deref();
data = pixmap.data;
}
return *this;
@@ -502,7 +547,7 @@ bool QPixmap::isQBitmap() const
*/
bool QPixmap::isNull() const
{
- return data->width() == 0;
+ return data->isNull();
}
/*!
@@ -600,13 +645,13 @@ void QPixmap::resize_helper(const QSize &s)
QPixmap pm(QSize(w, h), data->type);
bool uninit = false;
#if defined(Q_WS_X11)
- QX11PixmapData *x11Data = data->classId() == QPixmapData::X11Class ? static_cast<QX11PixmapData*>(data) : 0;
+ QX11PixmapData *x11Data = data->classId() == QPixmapData::X11Class ? static_cast<QX11PixmapData*>(data.data()) : 0;
if (x11Data) {
pm.x11SetScreen(x11Data->xinfo.screen());
- uninit = x11Data->uninit;
+ uninit = x11Data->flags & QX11PixmapData::Uninitialized;
}
#elif defined(Q_WS_MAC)
- QMacPixmapData *macData = data->classId() == QPixmapData::MacClass ? static_cast<QMacPixmapData*>(data) : 0;
+ QMacPixmapData *macData = data->classId() == QPixmapData::MacClass ? static_cast<QMacPixmapData*>(data.data()) : 0;
if (macData)
uninit = macData->uninit;
#endif
@@ -618,14 +663,9 @@ void QPixmap::resize_helper(const QSize &s)
p.drawPixmap(0, 0, *this, 0, 0, qMin(width(), w), qMin(height(), h));
}
-#if defined(Q_WS_MAC)
-#ifndef QT_MAC_NO_QUICKDRAW
- if(macData && macData->qd_alpha)
- macData->macQDUpdateAlpha();
-#endif
-#elif defined(Q_WS_X11)
+#if defined(Q_WS_X11)
if (x11Data && x11Data->x11_mask) {
- QX11PixmapData *pmData = static_cast<QX11PixmapData*>(pm.data);
+ QX11PixmapData *pmData = static_cast<QX11PixmapData*>(pm.data.data());
pmData->x11_mask = (Qt::HANDLE)XCreatePixmap(X11->display,
RootWindow(x11Data->xinfo.display(),
x11Data->xinfo.screen()),
@@ -794,19 +834,11 @@ bool QPixmap::load(const QString &fileName, const char *format, Qt::ImageConvers
if (QPixmapCache::find(key, *this))
return true;
- QImage image = QImageReader(fileName, format).read();
- if (image.isNull())
- return false;
- QPixmap pm;
- if (data->pixelType() == QPixmapData::BitmapType)
- pm = QBitmap::fromImage(image, flags);
- else
- pm = fromImage(image, flags);
- if (!pm.isNull()) {
- *this = pm;
+ if (data->fromFile(fileName, format, flags)) {
QPixmapCache::insert(key, *this);
return true;
}
+
return false;
}
@@ -831,21 +863,7 @@ bool QPixmap::load(const QString &fileName, const char *format, Qt::ImageConvers
bool QPixmap::loadFromData(const uchar *buf, uint len, const char *format, Qt::ImageConversionFlags flags)
{
- QByteArray a = QByteArray::fromRawData(reinterpret_cast<const char *>(buf), len);
- QBuffer b(&a);
- b.open(QIODevice::ReadOnly);
-
- QImage image = QImageReader(&b, format).read();
- QPixmap pm;
- if (data->pixelType() == QPixmapData::BitmapType)
- pm = QBitmap::fromImage(image, flags);
- else
- pm = fromImage(image, flags);
- if (!pm.isNull()) {
- *this = pm;
- return true;
- }
- return false;
+ return data->fromData(buf, len, format, flags);
}
/*!
@@ -1119,7 +1137,7 @@ Qt::HANDLE QPixmap::handle() const
{
#if defined(Q_WS_X11)
if (data->classId() == QPixmapData::X11Class)
- return static_cast<QX11PixmapData*>(data)->handle();
+ return static_cast<const QX11PixmapData*>(data.constData())->handle();
#endif
return 0;
}
@@ -1267,7 +1285,7 @@ QDataStream &operator>>(QDataStream &stream, QPixmap &pixmap)
return stream;
}
-#endif //QT_NO_DATASTREAM
+#endif // QT_NO_DATASTREAM
#ifdef QT3_SUPPORT
Q_GUI_EXPORT void copyBlt(QPixmap *dst, int dx, int dy,
@@ -1306,22 +1324,12 @@ bool QPixmap::isDetached() const
return data->ref == 1;
}
+/*! \internal
+ ### Qt5 - remove me.
+*/
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;
- data = 0;
- }
+ Q_ASSERT_X(false, "QPixmap::deref()", "Do not call this function anymore!");
}
/*!
@@ -1404,10 +1412,9 @@ QPixmap QPixmap::scaled(const QSize& s, Qt::AspectRatioMode aspectMode, Qt::Tran
if (newSize == size())
return *this;
- QPixmap pix;
- QTransform wm;
- wm.scale((qreal)newSize.width() / width(), (qreal)newSize.height() / height());
- pix = transformed(wm, mode);
+ QTransform wm = QTransform::fromScale((qreal)newSize.width() / width(),
+ (qreal)newSize.height() / height());
+ QPixmap pix = transformed(wm, mode);
return pix;
}
@@ -1434,9 +1441,8 @@ QPixmap QPixmap::scaledToWidth(int w, Qt::TransformationMode mode) const
if (w <= 0)
return QPixmap();
- QTransform wm;
qreal factor = (qreal) w / width();
- wm.scale(factor, factor);
+ QTransform wm = QTransform::fromScale(factor, factor);
return transformed(wm, mode);
}
@@ -1463,9 +1469,8 @@ QPixmap QPixmap::scaledToHeight(int h, Qt::TransformationMode mode) const
if (h <= 0)
return QPixmap();
- QTransform wm;
qreal factor = (qreal) h / height();
- wm.scale(factor, factor);
+ QTransform wm = QTransform::fromScale(factor, factor);
return transformed(wm, mode);
}
@@ -1520,9 +1525,9 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode)
\brief The QPixmap class is an off-screen image representation
that can be used as a paint device.
- \ingroup multimedia
+ \ingroup painting
\ingroup shared
- \mainclass
+
Qt provides four classes for handling image data: QImage, QPixmap,
QBitmap and QPicture. QImage is designed and optimized for I/O,
@@ -1530,24 +1535,24 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode)
designed and optimized for showing images on screen. QBitmap is
only a convenience class that inherits QPixmap, ensuring a depth
of 1. The isQBitmap() function returns true if a QPixmap object is
- really a bitmap, otherwise returns false. Finally, the QPicture class is a
- paint device that records and replays QPainter commands.
+ really a bitmap, otherwise returns false. Finally, the QPicture class
+ is a paint device that records and replays QPainter commands.
A QPixmap can easily be displayed on the screen using QLabel or
one of QAbstractButton's subclasses (such as QPushButton and
QToolButton). QLabel has a pixmap property, whereas
- QAbstractButton has an icon property. And because QPixmap is a
- QPaintDevice subclass, QPainter can be used to draw directly onto
- pixmaps.
+ QAbstractButton has an icon property.
In addition to the ordinary constructors, a QPixmap can be
constructed using the static grabWidget() and grabWindow()
functions which creates a QPixmap and paints the given widget, or
- window, in it.
+ window, into it.
+
+ QPixmap objects can be passed around by value since the QPixmap
+ class uses implicit data sharing. For more information, see the \l
+ {Implicit Data Sharing} documentation. QPixmap objects can also be
+ streamed.
- Note that the pixel data in a pixmap is internal and is managed by
- the underlying window system. Pixels can only be accessed through
- QPainter functions or by converting the QPixmap to a QImage.
Depending on the system, QPixmap is stored using a RGB32 or a
premultiplied alpha format. If the image has an alpha channel, and
if the system allows, the preferred format is premultiplied alpha.
@@ -1558,6 +1563,13 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode)
QPixmap are stored on the client side and don't use any GDI
resources).
+ Note that the pixel data in a pixmap is internal and is managed by
+ the underlying window system. Because QPixmap is a QPaintDevice
+ subclass, QPainter can be used to draw directly onto pixmaps.
+ Pixels can only be accessed through QPainter functions or by
+ converting the QPixmap to a QImage. However, the fill() function
+ is available for initializing the entire pixmap with a given color.
+
There are functions to convert between QImage and
QPixmap. Typically, the QImage class is used to load an image
file, optionally manipulating the image data, before the QImage
@@ -1572,11 +1584,6 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode)
there are several functions that enables transformation of the
pixmap.
- QPixmap objects can be passed around by value since the QPixmap
- class uses implicit data sharing. For more information, see the \l
- {Implicit Data Sharing} documentation. QPixmap objects can also be
- streamed.
-
\tableofcontents
\section1 Reading and Writing Image Files
@@ -1633,12 +1640,15 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode)
The hasAlphaChannel() returns true if the pixmap has a format that
respects the alpha channel, otherwise returns false, while the
hasAlpha() function returns true if the pixmap has an alpha
- channel \e or a mask (otherwise false).
+ channel \e or a mask (otherwise false). The mask() function returns
+ the mask as a QBitmap object, which can be set using setMask().
- The alphaChannel() function returns the alpha channel as a new
- QPixmap object, while the mask() function returns the mask as a
- QBitmap object. The alpha channel and mask can be set using the
- setAlphaChannel() and setMask() functions, respectively.
+ The createHeuristicMask() function creates and returns a 1-bpp
+ heuristic mask (i.e. a QBitmap) for this pixmap. It works by
+ selecting a color from one of the corners and then chipping away
+ pixels of that color, starting at all the edges. The
+ createMaskFromColor() function creates and returns a mask (i.e. a
+ QBitmap) for the pixmap based on a given color.
\row
\o Low-level information
@@ -1676,14 +1686,7 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode)
\section1 Pixmap Transformations
QPixmap supports a number of functions for creating a new pixmap
- that is a transformed version of the original: The
- createHeuristicMask() function creates and returns a 1-bpp
- heuristic mask (i.e. a QBitmap) for this pixmap. It works by
- selecting a color from one of the corners and then chipping away
- pixels of that color, starting at all the edges. The
- createMaskFromColor() function creates and returns a mask (i.e. a
- QBitmap) for the pixmap based on a given color.
-
+ that is a transformed version of the original:
The scaled(), scaledToWidth() and scaledToHeight() functions
return scaled copies of the pixmap, while the copy() function
@@ -1698,11 +1701,6 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode)
function returns the actual matrix used for transforming the
pixmap.
- There are also functions for changing attributes of a pixmap.
- in-place: The fill() function fills the entire image with the
- given color, the setMask() function sets a mask bitmap, and the
- setAlphaChannel() function sets the pixmap's alpha channel.
-
\sa QBitmap, QImage, QImageReader, QImageWriter
*/
@@ -1721,7 +1719,7 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode)
Returns true if this pixmap has an alpha channel, \e or has a
mask, otherwise returns false.
- \sa hasAlphaChannel(), alphaChannel(), mask()
+ \sa hasAlphaChannel(), mask()
*/
bool QPixmap::hasAlpha() const
{
@@ -1732,7 +1730,7 @@ bool QPixmap::hasAlpha() const
Returns true if the pixmap has a format that respects the alpha
channel, otherwise returns false.
- \sa alphaChannel(), hasAlpha()
+ \sa hasAlpha()
*/
bool QPixmap::hasAlphaChannel() const
{
@@ -1740,7 +1738,7 @@ bool QPixmap::hasAlphaChannel() const
}
/*!
- \reimp
+ \internal
*/
int QPixmap::metric(PaintDeviceMetric metric) const
{
@@ -1749,6 +1747,7 @@ int QPixmap::metric(PaintDeviceMetric metric) const
/*!
\fn void QPixmap::setAlphaChannel(const QPixmap &alphaChannel)
+ \obsolete
Sets the alpha channel of this pixmap to the given \a alphaChannel
by converting the \a alphaChannel into 32 bit and using the
@@ -1786,6 +1785,8 @@ void QPixmap::setAlphaChannel(const QPixmap &alphaChannel)
}
/*!
+ \obsolete
+
Returns the alpha channel of the pixmap as a new grayscale QPixmap in which
each pixel's red, green, and blue values are given the alpha value of the
original pixmap. The color depth of the returned pixmap is the system depth
@@ -1804,7 +1805,9 @@ void QPixmap::setAlphaChannel(const QPixmap &alphaChannel)
\image alphachannelimage.png The pixmap and channelImage QPixmaps
\warning This is an expensive operation. The alpha channel of the
- pixmap is extracted dynamically from the pixeldata.
+ pixmap is extracted dynamically from the pixeldata. Most usecases of this
+ function are covered by QPainter and compositionModes which will normally
+ execute faster.
\sa setAlphaChannel(), {QPixmap#Pixmap Information}{Pixmap
Information}
@@ -1815,7 +1818,7 @@ QPixmap QPixmap::alphaChannel() const
}
/*!
- \reimp
+ \internal
*/
QPaintEngine *QPixmap::paintEngine() const
{
@@ -1825,7 +1828,7 @@ QPaintEngine *QPixmap::paintEngine() const
/*!
\fn QBitmap QPixmap::mask() const
- Extracts a bitmap mask from the pixmap's alphachannel.
+ Extracts a bitmap mask from the pixmap's alpha channel.
\warning This is potentially an expensive operation. The mask of
the pixmap is extracted dynamically from the pixeldata.
@@ -1853,18 +1856,17 @@ 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
#elif defined(Q_WS_MAC)
return 32;
+#elif defined(Q_OS_SYMBIAN)
+ return S60->screenDepth;
#endif
}
-typedef void (*_qt_pixmap_cleanup_hook_64)(qint64);
-extern _qt_pixmap_cleanup_hook_64 qt_pixmap_cleanup_hook_64;
-
/*!
Detaches the pixmap from shared pixmap data.
@@ -1886,21 +1888,15 @@ void QPixmap::detach()
{
QPixmapData::ClassId id = data->classId();
if (id == QPixmapData::RasterClass) {
- QRasterPixmapData *rasterData = static_cast<QRasterPixmapData*>(data);
+ QRasterPixmapData *rasterData = static_cast<QRasterPixmapData*>(data.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)
- qt_pixmap_cleanup_hook_64(cacheKey());
+ if (data->is_cached && data->ref == 1)
+ QImagePixmapCleanupHooks::executePixmapHooks(this);
#if defined(Q_WS_MAC)
- QMacPixmapData *macData = id == QPixmapData::MacClass ? static_cast<QMacPixmapData*>(data) : 0;
+ QMacPixmapData *macData = id == QPixmapData::MacClass ? static_cast<QMacPixmapData*>(data.data()) : 0;
if (macData) {
if (macData->cg_mask) {
CGImageRelease(macData->cg_mask);
@@ -1911,18 +1907,13 @@ void QPixmap::detach()
if (data->ref != 1) {
*this = copy();
-#if defined(Q_WS_MAC) && !defined(QT_MAC_NO_QUICKDRAW)
- if (id == QPixmapData::MacClass) {
- macData->qd_alpha = 0;
- }
-#endif
}
++data->detach_no;
#if defined(Q_WS_X11)
if (data->classId() == QPixmapData::X11Class) {
- QX11PixmapData *d = static_cast<QX11PixmapData*>(data);
- d->uninit = false;
+ QX11PixmapData *d = static_cast<QX11PixmapData*>(data.data());
+ d->flags &= ~QX11PixmapData::Uninitialized;
// reset the cache data
if (d->hd2) {
@@ -1958,15 +1949,11 @@ QPixmap QPixmap::fromImage(const QImage &image, Qt::ImageConversionFlags flags)
if (image.isNull())
return QPixmap();
- QPixmapData *data;
QGraphicsSystem* gs = QApplicationPrivate::graphicsSystem();
- if (gs)
- data = gs->createPixmapData(QPixmapData::PixmapType);
- else
- data = QGraphicsSystem::createDefaultPixmapData(QPixmapData::PixmapType);
-
+ QScopedPointer<QPixmapData> data(gs ? gs->createPixmapData(QPixmapData::PixmapType)
+ : QGraphicsSystem::createDefaultPixmapData(QPixmapData::PixmapType));
data->fromImage(image, flags);
- return QPixmap(data);
+ return QPixmap(data.take());
}
/*!
@@ -2011,7 +1998,7 @@ QPixmap QPixmap::fromImage(const QImage &image, Qt::ImageConversionFlags flags)
*/
QPixmapData* QPixmap::pixmapData() const
{
- return data;
+ return data.data();
}
/*!