/**************************************************************************** ** ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying ** this package. ** ** 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.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** ** ** ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qvolatileimage_p.h" #include "qvolatileimagedata_p.h" #include #include QT_BEGIN_NAMESPACE class QVolatileImagePaintEnginePrivate : public QRasterPaintEnginePrivate { public: QVolatileImagePaintEnginePrivate() { } QVolatileImage *img; }; class QVolatileImagePaintEngine : public QRasterPaintEngine { Q_DECLARE_PRIVATE(QVolatileImagePaintEngine) public: QVolatileImagePaintEngine(QPaintDevice *device, QVolatileImage *img); bool begin(QPaintDevice *device); bool end(); void drawPixmap(const QPointF &p, const QPixmap &pm); void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); }; QVolatileImage::QVolatileImage() : d(new QVolatileImageData) { } QVolatileImage::QVolatileImage(int w, int h, QImage::Format format) : d(new QVolatileImageData(w, h, format)) { } QVolatileImage::QVolatileImage(const QImage &sourceImage) : d(new QVolatileImageData(sourceImage)) { } QVolatileImage::QVolatileImage(void *nativeImage, void *nativeMask) : d(new QVolatileImageData(nativeImage, nativeMask)) { } // Need non-inline, non-autogenerated copy ctor, dtor, op= to keep the // fwd declared QSharedData working. QVolatileImage::QVolatileImage(const QVolatileImage &other) : d(other.d) { } QVolatileImage::~QVolatileImage() { } QVolatileImage &QVolatileImage::operator=(const QVolatileImage &rhs) { d = rhs.d; return *this; } bool QVolatileImage::paintingActive() const { return d->pengine && d->pengine->isActive(); } bool QVolatileImage::isNull() const { return d->image.isNull(); } QImage::Format QVolatileImage::format() const { return d->image.format(); } int QVolatileImage::width() const { return d->image.width(); } int QVolatileImage::height() const { return d->image.height(); } int QVolatileImage::bytesPerLine() const { return d->image.bytesPerLine(); } int QVolatileImage::byteCount() const { return d->image.byteCount(); } int QVolatileImage::depth() const { return d->image.depth(); } bool QVolatileImage::hasAlphaChannel() const { return d->image.hasAlphaChannel(); } void QVolatileImage::beginDataAccess() const { d->beginDataAccess(); } void QVolatileImage::endDataAccess(bool readOnly) const { d->endDataAccess(readOnly); } /*! Access to pixel data via bits() or constBits() should be guarded by begin/endDataAccess(). */ uchar *QVolatileImage::bits() { return d->image.bits(); } const uchar *QVolatileImage::constBits() const { return d->image.constBits(); } bool QVolatileImage::ensureFormat(QImage::Format format) { return d->ensureFormat(format); } /*! This will always perform a copy of the pixel data. */ QImage QVolatileImage::toImage() const { d->beginDataAccess(); QImage newImage = d->image.copy(); // no sharing allowed d->endDataAccess(true); return newImage; } /*! Returns a reference to the image that is potentially using some native buffer internally. Access to the image's pixel data should be guarded by begin/endDataAccess(). Use it when there is a need for QImage APIs not provided by this class. The returned QImage must never be shared or assigned to. */ QImage &QVolatileImage::imageRef() // non-const, in order to cause a detach { d->ensureImage(); return d->image; } void *QVolatileImage::duplicateNativeImage() const { return d->duplicateNativeImage(); } void QVolatileImage::setAlphaChannel(const QPixmap &alphaChannel) { ensureFormat(QImage::Format_ARGB32_Premultiplied); beginDataAccess(); imageRef().setAlphaChannel(alphaChannel.toImage()); endDataAccess(); d->ensureImage(); } void QVolatileImage::fill(uint pixelValue) { beginDataAccess(); imageRef().fill(pixelValue); endDataAccess(); d->ensureImage(); } void QVolatileImage::copyFrom(QVolatileImage *source, const QRect &rect) { if (source->isNull()) { return; } QRect r = rect; if (rect.isNull()) { r = QRect(0, 0, source->width(), source->height()); } source->beginDataAccess(); QImage &srcImgRef(source->imageRef()); int srcbpl = srcImgRef.bytesPerLine(); int srcbpp = srcImgRef.depth() / 8; const uchar *sptr = srcImgRef.constBits() + r.y() * srcbpl; beginDataAccess(); QImage &dstImgRef(imageRef()); int dstbpl = dstImgRef.bytesPerLine(); uchar *dptr = dstImgRef.bits(); for (int y = 0; y < r.height(); ++y) { qMemCopy(dptr, sptr + r.x() * srcbpp, r.width() * srcbpp); sptr += srcbpl; dptr += dstbpl; } endDataAccess(); source->endDataAccess(true); } /*! To be called from the PixmapData's paintEngine(). */ QPaintEngine *QVolatileImage::paintEngine() { if (!d->pengine) { d->pengine = new QVolatileImagePaintEngine(&imageRef(), this); } return d->pengine; } QVolatileImagePaintEngine::QVolatileImagePaintEngine(QPaintDevice *device, QVolatileImage *img) : QRasterPaintEngine(*(new QVolatileImagePaintEnginePrivate), device) { Q_D(QVolatileImagePaintEngine); d->img = img; } bool QVolatileImagePaintEngine::begin(QPaintDevice *device) { Q_D(QVolatileImagePaintEngine); d->img->beginDataAccess(); return QRasterPaintEngine::begin(device); } bool QVolatileImagePaintEngine::end() { Q_D(QVolatileImagePaintEngine); bool ret = QRasterPaintEngine::end(); d->img->endDataAccess(); return ret; } // For non-RasterClass pixmaps drawPixmap() would call toImage() which is slow in // our case. Therefore drawPixmap() is rerouted to drawImage(). void QVolatileImagePaintEngine::drawPixmap(const QPointF &p, const QPixmap &pm) { #ifdef Q_OS_SYMBIAN void *nativeData = pm.pixmapData()->toNativeType(QPixmapData::VolatileImage); if (nativeData) { QVolatileImage *img = static_cast(nativeData); img->beginDataAccess(); QRasterPaintEngine::drawImage(p, img->imageRef()); img->endDataAccess(true); } else { QRasterPaintEngine::drawPixmap(p, pm); } #else QRasterPaintEngine::drawPixmap(p, pm); #endif } void QVolatileImagePaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) { #ifdef Q_OS_SYMBIAN void *nativeData = pm.pixmapData()->toNativeType(QPixmapData::VolatileImage); if (nativeData) { QVolatileImage *img = static_cast(nativeData); img->beginDataAccess(); QRasterPaintEngine::drawImage(r, img->imageRef(), sr); img->endDataAccess(true); } else { QRasterPaintEngine::drawPixmap(r, pm, sr); } #else QRasterPaintEngine::drawPixmap(r, pm, sr); #endif } QT_END_NAMESPACE