Index: gui/image/qimage.cpp =================================================================== --- gui/image/qimage.cpp (revision 459861) +++ gui/image/qimage.cpp (working copy) @@ -786,6 +786,47 @@ d = new QImageData; d->ref.ref(); + changeImageData(d, data, width, height, bpl, format, readOnly, cleanupFunction, cleanupInfo, depth); + + return d; +} + +QImageData *QImageData::resize(QImageData *d, uchar *data, int width, int height, int bpl, QImage::Format format, bool readOnly, QImageCleanupFunction cleanupFunction, void *cleanupInfo) +{ + if (!d){ + return create(data, width, height, bpl, format, readOnly, cleanupFunction, cleanupInfo); + } + + const int depth = qt_depthForFormat(format); + const int calc_bytes_per_line = ((width * depth + 31) / 32) * 4; + const int min_bytes_per_line = (width * depth + 7) / 8; + + if (bpl <= 0) + bpl = calc_bytes_per_line; + + if (width <= 0 || height <= 0 || !data + || INT_MAX / sizeof(uchar *) < uint(height) + || INT_MAX / uint(depth) < uint(width) + || bpl <= 0 + || height <= 0 + || bpl < min_bytes_per_line + || INT_MAX / uint(bpl) < uint(height) + || (format == QImage::Format_Invalid)) + { + if (!d->ref.deref()){ + delete d; + } + return nullptr; // invalid parameter(s) + } + + changeImageData(d, data, width, height, bpl, format, readOnly, cleanupFunction, cleanupInfo, depth); + d->paintEngine->updateEngineAfterResize(); + + return d; +} + +void QImageData::changeImageData(QImageData *d, uchar *data, int width, int height, int bpl, QImage::Format format, bool readOnly, QImageCleanupFunction cleanupFunction, void *cleanupInfo, int depth) +{ d->own_data = false; d->ro_data = readOnly; d->data = data; @@ -799,8 +840,6 @@ d->cleanupFunction = cleanupFunction; d->cleanupInfo = cleanupInfo; - - return d; } /*! @@ -826,6 +865,11 @@ d = QImageData::create(data, width, height, 0, format, false, cleanupFunction, cleanupInfo); } +void QImage::resize(uchar* data, int width, int height, Format format, QImageCleanupFunction cleanupFunction, void *cleanupInfo) +{ + d = QImageData::resize(d, data, width, height, 0, format, false, cleanupFunction, cleanupInfo); +} + /*! Constructs an image with the given \a width, \a height and \a format, that uses an existing read-only memory buffer, \a Index: gui/image/qimage.h =================================================================== --- gui/image/qimage.h (revision 459861) +++ gui/image/qimage.h (working copy) @@ -132,6 +132,8 @@ QImage(const uchar *data, int width, int height, Format format, QImageCleanupFunction cleanupFunction = 0, void *cleanupInfo = 0); QImage(uchar *data, int width, int height, int bytesPerLine, Format format, QImageCleanupFunction cleanupFunction = 0, void *cleanupInfo = 0); QImage(const uchar *data, int width, int height, int bytesPerLine, Format format, QImageCleanupFunction cleanupFunction = 0, void *cleanupInfo = 0); + + void resize(uchar *data, int width, int height, Format format, QImageCleanupFunction cleanupFunction = 0, void *cleanupInfo = 0); #ifndef QT_NO_IMAGEFORMAT_XPM explicit QImage(const char * const xpm[]); Index: gui/image/qimage_p.h =================================================================== --- gui/image/qimage_p.h (revision 459861) +++ gui/image/qimage_p.h (working copy) @@ -67,7 +67,8 @@ ~QImageData(); static QImageData *create(const QSize &size, QImage::Format format, int numColors = 0); static QImageData *create(uchar *data, int w, int h, int bpl, QImage::Format format, bool readOnly, QImageCleanupFunction cleanupFunction = 0, void *cleanupInfo = 0); - + static QImageData *resize(QImageData *d, uchar *data, int w, int h, int bpl, QImage::Format format, bool readOnly, QImageCleanupFunction cleanupFunction, void *cleanupInfo); + static void changeImageData(QImageData *d, uchar *data, int width, int height, int bpl, QImage::Format format, bool readOnly, QImageCleanupFunction cleanupFunction, void *cleanupInfo, int depth); QAtomicInt ref; int width; Index: gui/painting/qpaintengine.cpp =================================================================== --- gui/painting/qpaintengine.cpp (revision 459861) +++ gui/painting/qpaintengine.cpp (working copy) @@ -624,6 +624,11 @@ drawPixmap(r, pm, QRectF(QPointF(0, 0), pm.size())); } +void QPaintEngine::updateEngineAfterResize() +{ + // overwritten by specialized classes +} + /*! \fn Type QPaintEngine::type() const Index: gui/painting/qpaintengine.h =================================================================== --- gui/painting/qpaintengine.h (revision 459861) +++ gui/painting/qpaintengine.h (working copy) @@ -178,6 +178,8 @@ virtual void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s); virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags = Qt::AutoColor); + + virtual void updateEngineAfterResize(); void setPaintDevice(QPaintDevice *device); QPaintDevice *paintDevice() const; Index: gui/painting/qpaintengine_raster.cpp =================================================================== --- gui/painting/qpaintengine_raster.cpp (revision 459861) +++ gui/painting/qpaintengine_raster.cpp (working copy) @@ -392,61 +392,8 @@ d->basicStroker.setLineToHook(qt_ft_outline_line_to); d->basicStroker.setCubicToHook(qt_ft_outline_cubic_to); - d->baseClip.reset(new QClipData(d->device->height())); - d->baseClip->setClipRect(QRect(0, 0, d->device->width(), d->device->height())); + updateEngineAfterResize(); - d->image_filler.init(d->rasterBuffer.data(), this); - d->image_filler.type = QSpanData::Texture; - - d->image_filler_xform.init(d->rasterBuffer.data(), this); - d->image_filler_xform.type = QSpanData::Texture; - - d->solid_color_filler.init(d->rasterBuffer.data(), this); - d->solid_color_filler.type = QSpanData::Solid; - - d->deviceDepth = d->device->depth(); - - d->mono_surface = false; - gccaps &= ~PorterDuff; - - QImage::Format format = QImage::Format_Invalid; - - switch (d->device->devType()) { - case QInternal::Pixmap: - qWarning("QRasterPaintEngine: unsupported for pixmaps..."); - break; - case QInternal::Image: - format = d->rasterBuffer->prepare(static_cast(d->device)); - break; - default: - qWarning("QRasterPaintEngine: unsupported target device %d\n", d->device->devType()); - d->device = 0; - return; - } - - switch (format) { - case QImage::Format_MonoLSB: - case QImage::Format_Mono: - d->mono_surface = true; - break; - case QImage::Format_ARGB8565_Premultiplied: - case QImage::Format_ARGB8555_Premultiplied: - case QImage::Format_ARGB6666_Premultiplied: - case QImage::Format_ARGB4444_Premultiplied: - case QImage::Format_ARGB32_Premultiplied: - case QImage::Format_ARGB32: - gccaps |= PorterDuff; - break; - case QImage::Format_RGB32: - case QImage::Format_RGB444: - case QImage::Format_RGB555: - case QImage::Format_RGB666: - case QImage::Format_RGB888: - case QImage::Format_RGB16: - break; - default: - break; - } } @@ -2552,6 +2499,72 @@ return d->rasterBuffer.data(); } +void QRasterPaintEngine::updateEngineAfterResize() +{ + Q_D(QRasterPaintEngine); + + d->baseClip.reset(new QClipData(d->device->height())); + d->baseClip->setClipRect(QRect(0, 0, d->device->width(), d->device->height())); + + d->image_filler.init(d->rasterBuffer.data(), this); + d->image_filler.type = QSpanData::Texture; + + d->image_filler_xform.init(d->rasterBuffer.data(), this); + d->image_filler_xform.type = QSpanData::Texture; + + d->solid_color_filler.init(d->rasterBuffer.data(), this); + d->solid_color_filler.type = QSpanData::Solid; + + d->deviceDepth = d->device->depth(); + + d->mono_surface = false; + gccaps = AllFeatures; + gccaps &= ~PorterDuff; + + QImage::Format format = QImage::Format_Invalid; + + switch (d->device->devType()) { + case QInternal::Pixmap: + qWarning("QRasterPaintEngine: unsupported for pixmaps..."); + break; + case QInternal::Image: + format = d->rasterBuffer->prepare(static_cast(d->device)); + break; + default: + qWarning("QRasterPaintEngine: unsupported target device %d\n", d->device->devType()); + d->device = 0; + return; + } + + switch (format) { + case QImage::Format_MonoLSB: + case QImage::Format_Mono: + d->mono_surface = true; + break; + case QImage::Format_ARGB8565_Premultiplied: + case QImage::Format_ARGB8555_Premultiplied: + case QImage::Format_ARGB6666_Premultiplied: + case QImage::Format_ARGB4444_Premultiplied: + case QImage::Format_ARGB32_Premultiplied: + case QImage::Format_ARGB32: + gccaps |= PorterDuff; + break; + case QImage::Format_RGB32: + case QImage::Format_RGB444: + case QImage::Format_RGB555: + case QImage::Format_RGB666: + case QImage::Format_RGB888: + case QImage::Format_RGB16: + break; + default: + break; + } + + if (isActive()){ + begin(d->device); + } +} + /*! \internal */ Index: gui/painting/qpaintengine_raster_p.h =================================================================== --- gui/painting/qpaintengine_raster_p.h (revision 459861) +++ gui/painting/qpaintengine_raster_p.h (working copy) @@ -225,6 +225,7 @@ #endif QRasterBuffer *rasterBuffer(); + virtual void updateEngineAfterResize() override; void alphaPenBlt(const void* src, int bpl, int depth, int rx,int ry,int w,int h); Type type() const { return Raster; } Index: plugins/platforms/windows/qwindowsbackingstore.cpp =================================================================== --- plugins/platforms/windows/qwindowsbackingstore.cpp (revision 459861) +++ plugins/platforms/windows/qwindowsbackingstore.cpp (working copy) @@ -1,4 +1,4 @@ -/**************************************************************************** +/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal @@ -147,7 +147,12 @@ QImage::Format format = QWindowsNativeImage::systemFormat(); if (format == QImage::Format_RGB32 && rasterWindow()->window()->format().hasAlpha()) format = QImage::Format_ARGB32_Premultiplied; - m_image.reset(new QWindowsNativeImage(size.width(), size.height(), format)); + if (m_image.isNull()) { + m_image.reset(new QWindowsNativeImage(size.width(), size.height(), format)); + } + else { + m_image->resize(size.width(), size.height(), format); + } } } Index: plugins/platforms/windows/qwindowsnativeimage.cpp =================================================================== --- plugins/platforms/windows/qwindowsnativeimage.cpp (revision 459861) +++ plugins/platforms/windows/qwindowsnativeimage.cpp (working copy) @@ -1,4 +1,4 @@ -/**************************************************************************** +/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal @@ -117,14 +117,39 @@ m_bitmap(0), m_null_bitmap(0) { + resize(width, height, format); +} + +QWindowsNativeImage::~QWindowsNativeImage() +{ + if (m_hdc) { + cleanupDIB(); + DeleteDC(m_hdc); + } +} + +QImage::Format QWindowsNativeImage::systemFormat() +{ + static const int depth = QWindowsContext::instance()->screenDepth(); + return depth == 16 ? QImage::Format_RGB16 : QImage::Format_RGB32; +} + +void QWindowsNativeImage::resize(int width, int height, QImage::Format format) +{ if (width != 0 && height != 0) { + cleanupDIB(); uchar *bits; m_bitmap = createDIB(m_hdc, width, height, format, &bits); - m_null_bitmap = (HBITMAP)SelectObject(m_hdc, m_bitmap); - m_image = QImage(bits, width, height, format); + m_null_bitmap = (HBITMAP) SelectObject(m_hdc, m_bitmap); + if (m_image.isNull()){ + m_image = QImage(bits, width, height, format); + }else{ + m_image.resize(bits, width, height, format); + } Q_ASSERT(m_image.paintEngine()->type() == QPaintEngine::Raster); static_cast(m_image.paintEngine())->setDC(m_hdc); - } else { + } + else { m_image = QImage(width, height, format); } @@ -133,22 +158,14 @@ #endif } -QWindowsNativeImage::~QWindowsNativeImage() +void QWindowsNativeImage::cleanupDIB() { - if (m_hdc) { - if (m_bitmap) { - if (m_null_bitmap) - SelectObject(m_hdc, m_null_bitmap); - DeleteObject(m_bitmap); - } - DeleteDC(m_hdc); + if (m_bitmap) { + if (m_null_bitmap) + SelectObject(m_hdc, m_null_bitmap); + DeleteObject(m_bitmap); } } -QImage::Format QWindowsNativeImage::systemFormat() -{ - static const int depth = QWindowsContext::instance()->screenDepth(); - return depth == 16 ? QImage::Format_RGB16 : QImage::Format_RGB32; -} QT_END_NAMESPACE Index: plugins/platforms/windows/qwindowsnativeimage.h =================================================================== --- plugins/platforms/windows/qwindowsnativeimage.h (revision 459861) +++ plugins/platforms/windows/qwindowsnativeimage.h (working copy) @@ -1,4 +1,4 @@ -/**************************************************************************** +/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal @@ -59,6 +59,9 @@ ~QWindowsNativeImage(); + + void resize(int width, int height, QImage::Format format); + inline int width() const { return m_image.width(); } inline int height() const { return m_image.height(); } @@ -70,6 +73,8 @@ static QImage::Format systemFormat(); private: + void cleanupDIB(); + const HDC m_hdc; QImage m_image;