From 4b815774358c3c981dc8bbbcb0dd68abe2e812f2 Mon Sep 17 00:00:00 2001 From: Jani Hautakangas Date: Wed, 16 Dec 2009 15:21:10 +0200 Subject: Fix for QTBUG-4908 SVG transparency rendering problem. QPixmap::copy discarded alpha channel. This fix also removes usage of member variables CFbsBitGc and CFbsBitmapDevice. Now those are used only in function scope. Reviewed-by: Sami Merila --- src/gui/image/qpixmap_s60.cpp | 97 +++++++++++++-------------------- src/gui/image/qpixmap_s60_p.h | 6 +- src/gui/painting/qwindowsurface_s60.cpp | 8 ++- tests/auto/qpixmap/tst_qpixmap.cpp | 6 ++ 4 files changed, 51 insertions(+), 66 deletions(-) diff --git a/src/gui/image/qpixmap_s60.cpp b/src/gui/image/qpixmap_s60.cpp index 610317d..8194db5 100644 --- a/src/gui/image/qpixmap_s60.cpp +++ b/src/gui/image/qpixmap_s60.cpp @@ -235,7 +235,7 @@ static CFbsBitmap* uncompress(CFbsBitmap* bitmap) QT_TRAP_THROWING(bitmapGc = CFbsBitGc::NewL()); bitmapGc->Activate(bitmapDevice); - bitmapGc->DrawBitmap(TPoint(), bitmap); + bitmapGc->BitBlt(TPoint(), bitmap); delete bitmapGc; delete bitmapDevice; @@ -346,8 +346,6 @@ QPixmap QPixmap::fromSymbianCFbsBitmap(CFbsBitmap *bitmap) QS60PixmapData::QS60PixmapData(PixelType type) : QRasterPixmapData(type), symbianBitmapDataAccess(new QSymbianBitmapDataAccess), cfbsBitmap(0), - bitmapDevice(0), - bitmapGc(0), pengine(0), bytes(0), formatLocked(false) @@ -385,8 +383,6 @@ void QS60PixmapData::resize(int width, int height) if(cfbsBitmap->SizeInPixels() != newSize) { cfbsBitmap->Resize(TSize(width, height)); - bitmapDevice->Resize(TSize(width, height)); - bitmapGc->Resized(); if(pengine) { delete pengine; pengine = 0; @@ -397,21 +393,10 @@ void QS60PixmapData::resize(int width, int height) } } -bool QS60PixmapData::initSymbianBitmapContext() -{ - QT_TRAP_THROWING(bitmapDevice = CFbsBitmapDevice::NewL(cfbsBitmap)); - QT_TRAP_THROWING(bitmapGc = CFbsBitGc::NewL()); - bitmapGc->Activate(bitmapDevice); - - return true; -} - void QS60PixmapData::release() { if (cfbsBitmap) { QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); - delete bitmapGc; - delete bitmapDevice; delete cfbsBitmap; lock.relock(); } @@ -419,8 +404,6 @@ void QS60PixmapData::release() delete pengine; image = QImage(); cfbsBitmap = 0; - bitmapGc = 0; - bitmapDevice = 0; pengine = 0; bytes = 0; } @@ -428,42 +411,52 @@ void QS60PixmapData::release() /*! * Takes ownership of bitmap. Used by window surface */ -void QS60PixmapData::fromSymbianBitmap(CFbsBitmap* bitmap) +void QS60PixmapData::fromSymbianBitmap(CFbsBitmap* bitmap, bool lockFormat) { - cfbsBitmap = bitmap; - formatLocked = true; + Q_ASSERT(bitmap); - if(!initSymbianBitmapContext()) { - qWarning("Could not create CBitmapContext"); - release(); - return; - } + release(); + + cfbsBitmap = bitmap; + formatLocked = lockFormat; - setSerialNumber(cfbsBitmap->Handle()); + setSerialNumber(cfbsBitmap->Handle()); - UPDATE_BUFFER(); + UPDATE_BUFFER(); - // Create default palette if needed - if (cfbsBitmap->DisplayMode() == EGray2) { - image.setColorCount(2); - image.setColor(0, QColor(Qt::color0).rgba()); - image.setColor(1, QColor(Qt::color1).rgba()); + // Create default palette if needed + if (cfbsBitmap->DisplayMode() == EGray2) { + image.setColorCount(2); + image.setColor(0, QColor(Qt::color0).rgba()); + image.setColor(1, QColor(Qt::color1).rgba()); //Symbian thinks set pixels are white/transparent, Qt thinks they are foreground/solid //So invert mono bitmaps so that masks work correctly. image.invertPixels(); - } else if (cfbsBitmap->DisplayMode() == EGray256) { - for (int i=0; i < 256; ++i) - image.setColor(i, qRgb(i, i, i)); - }else if (cfbsBitmap->DisplayMode() == EColor256) { - const TColor256Util *palette = TColor256Util::Default(); - for (int i=0; i < 256; ++i) - image.setColor(i, (QRgb)(palette->Color256(i).Value())); - } + } else if (cfbsBitmap->DisplayMode() == EGray256) { + for (int i=0; i < 256; ++i) + image.setColor(i, qRgb(i, i, i)); + } else if (cfbsBitmap->DisplayMode() == EColor256) { + const TColor256Util *palette = TColor256Util::Default(); + for (int i=0; i < 256; ++i) + image.setColor(i, (QRgb)(palette->Color256(i).Value())); + } +} + +QImage QS60PixmapData::toImage(const QRect &r) const +{ + QS60PixmapData *that = const_cast(this); + that->beginDataAccess(); + QImage copy = that->image.copy(r); + that->endDataAccess(); + + return copy; } void QS60PixmapData::fromImage(const QImage &img, Qt::ImageConversionFlags flags) { + release(); + QImage sourceImage; if (pixelType() == BitmapType) { @@ -517,8 +510,8 @@ void QS60PixmapData::fromImage(const QImage &img, Qt::ImageConversionFlags flags } cfbsBitmap = createSymbianCFbsBitmap(TSize(sourceImage.width(), sourceImage.height()), mode); - if (!(cfbsBitmap && initSymbianBitmapContext())) { - qWarning("Could not create CFbsBitmap and/or CBitmapContext"); + if (!cfbsBitmap) { + qWarning("Could not create CFbsBitmap"); release(); return; } @@ -544,17 +537,8 @@ void QS60PixmapData::fromImage(const QImage &img, Qt::ImageConversionFlags flags void QS60PixmapData::copy(const QPixmapData *data, const QRect &rect) { - if (data->pixelType() == BitmapType) { - QBitmap::fromImage(data->toImage().copy(rect)); - return; - } - const QS60PixmapData *s60Data = static_cast(data); - - resize(rect.width(), rect.height()); - cfbsBitmap->SetDisplayMode(s60Data->cfbsBitmap->DisplayMode()); - - bitmapGc->BitBlt(TPoint(0, 0), s60Data->cfbsBitmap, qt_QRect2TRect(rect)); + fromImage(s60Data->toImage(rect), Qt::AutoColor | Qt::OrderedAlphaDither); } bool QS60PixmapData::scroll(int dx, int dy, const QRect &rect) @@ -661,12 +645,7 @@ void QS60PixmapData::setAlphaChannel(const QPixmap &alphaChannel) QImage QS60PixmapData::toImage() const { - QS60PixmapData *that = const_cast(this); - that->beginDataAccess(); - QImage copy = that->image.copy(); - that->endDataAccess(); - - return copy; + return toImage(QRect()); } QPaintEngine* QS60PixmapData::paintEngine() const diff --git a/src/gui/image/qpixmap_s60_p.h b/src/gui/image/qpixmap_s60_p.h index 8631ebd..2d93622 100644 --- a/src/gui/image/qpixmap_s60_p.h +++ b/src/gui/image/qpixmap_s60_p.h @@ -109,14 +109,12 @@ public: private: void release(); - void fromSymbianBitmap(CFbsBitmap* bitmap); - bool initSymbianBitmapContext(); + void fromSymbianBitmap(CFbsBitmap* bitmap, bool lockFormat=false); + QImage toImage(const QRect &r) const; QSymbianBitmapDataAccess *symbianBitmapDataAccess; CFbsBitmap *cfbsBitmap; - CFbsBitmapDevice *bitmapDevice; - CFbsBitGc *bitmapGc; QPaintEngine *pengine; uchar* bytes; diff --git a/src/gui/painting/qwindowsurface_s60.cpp b/src/gui/painting/qwindowsurface_s60.cpp index c66da71..15427c6 100644 --- a/src/gui/painting/qwindowsurface_s60.cpp +++ b/src/gui/painting/qwindowsurface_s60.cpp @@ -68,12 +68,14 @@ QS60WindowSurface::QS60WindowSurface(QWidget* widget) mode = EColor16MA; // Try for transparency anyway // We create empty CFbsBitmap here -> it will be resized in setGeometry - CFbsBitmap *bitmap = q_check_ptr(new CFbsBitmap); // CBase derived object needs check on new + CFbsBitmap *bitmap = q_check_ptr(new CFbsBitmap); // CBase derived object needs check on new qt_symbian_throwIfError( bitmap->Create( TSize(0, 0), mode ) ); QS60PixmapData *data = new QS60PixmapData(QPixmapData::PixmapType); - data->fromSymbianBitmap(bitmap); - d_ptr->device = QPixmap(data); + if (data) { + data->fromSymbianBitmap(bitmap, true); + d_ptr->device = QPixmap(data); + } setStaticContentsSupport(true); } diff --git a/tests/auto/qpixmap/tst_qpixmap.cpp b/tests/auto/qpixmap/tst_qpixmap.cpp index 0effd01..0164c9d 100644 --- a/tests/auto/qpixmap/tst_qpixmap.cpp +++ b/tests/auto/qpixmap/tst_qpixmap.cpp @@ -1289,6 +1289,12 @@ void tst_QPixmap::copy() QPixmap expected(10, 10); expected.fill(Qt::blue); QVERIFY(lenientCompare(dest, expected)); + + QPixmap trans; + trans.fill(Qt::transparent); + + QPixmap transCopy = trans.copy(); + QVERIFY(pixmapsAreEqual(&trans, &transCopy)); } #ifdef QT3_SUPPORT -- cgit v0.12