summaryrefslogtreecommitdiffstats
path: root/src/gui/image
diff options
context:
space:
mode:
authorJason Barron <jbarron@trolltech.com>2009-09-23 06:31:23 (GMT)
committerJason Barron <jbarron@trolltech.com>2009-09-23 13:10:41 (GMT)
commit7dcf984f85a3a75ce4c078cc931bd9d2304bc235 (patch)
treed18699427b8ffe5843e82c3057c70b9db53d136d /src/gui/image
parent48d0f84958fdc2dcffab75f33842a9dbc3d4d7b1 (diff)
downloadQt-7dcf984f85a3a75ce4c078cc931bd9d2304bc235.zip
Qt-7dcf984f85a3a75ce4c078cc931bd9d2304bc235.tar.gz
Qt-7dcf984f85a3a75ce4c078cc931bd9d2304bc235.tar.bz2
Modify functions for native pixmap data conversion on Symbian.
We need a way to support converion to and from multiple native pixmap types from multiple pixmap backends. Instead of adding more virtual functions to QPixmapData, make the existing one more generic but pass an opaque pointer and a type and do some internal casting. Currently this function is Symbian only, but could easily be extended to work on other platforms. Reviewed-by: Aleksandar Babic Reviewed-by: Jani Hautakangas
Diffstat (limited to 'src/gui/image')
-rw-r--r--src/gui/image/qpixmap.h6
-rw-r--r--src/gui/image/qpixmap_s60.cpp410
-rw-r--r--src/gui/image/qpixmap_s60_p.h21
-rw-r--r--src/gui/image/qpixmapdata.cpp5
-rw-r--r--src/gui/image/qpixmapdata_p.h15
5 files changed, 235 insertions, 222 deletions
diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h
index 2ed65ea..a891637 100644
--- a/src/gui/image/qpixmap.h
+++ b/src/gui/image/qpixmap.h
@@ -161,10 +161,8 @@ public:
#endif
#if defined(Q_OS_SYMBIAN)
- enum ConversionMode { CopyData, DuplicateHandle };
-
- CFbsBitmap *toSymbianCFbsBitmap(ConversionMode mode = DuplicateHandle) const;
- static QPixmap fromSymbianCFbsBitmap(CFbsBitmap *bitmap, ConversionMode mode = DuplicateHandle);
+ CFbsBitmap *toSymbianCFbsBitmap() const;
+ static QPixmap fromSymbianCFbsBitmap(CFbsBitmap *bitmap);
RSgImage* toSymbianRSgImage() const;
static QPixmap fromSymbianRSgImage(RSgImage *sgImage);
#endif
diff --git a/src/gui/image/qpixmap_s60.cpp b/src/gui/image/qpixmap_s60.cpp
index 303e923..cab6116 100644
--- a/src/gui/image/qpixmap_s60.cpp
+++ b/src/gui/image/qpixmap_s60.cpp
@@ -297,231 +297,55 @@ QPixmap QPixmap::grabWindow(WId winId, int x, int y, int w, int h)
}
/*!
- \enum QPixmap::ConversionMode
-
- \bold{Symbian only:} This enum defines how the conversion between \c
- CFbsBitmap and QPixmap is performed.
-
- \warning This enum is only available on Symbian.
-
- \value CopyData Copied CFbsBitmap data.
-
- \value DuplicateHandle Duplicates CFbsBitmap handle. This also means
- that pixmap data will be explicitly shared.
-
- \sa fromSymbianCFbsBitmap(), toSymbianCFbsBitmap()
-*/
-
-
-/*!
- \fn CFbsBitmap *QPixmap::toSymbianCFbsBitmap(ConversionMode mode)
+ \fn CFbsBitmap *QPixmap::toSymbianCFbsBitmap()
\since 4.6
- Creates \c CFbsBitmap that is equivalent to the QPixmap, based on
- the given \a mode. If the creation then this function returns 0.
+ Creates a \c CFbsBitmap that is equivalent to the QPixmap. Internally this
+ function will try to duplicate the handle instead of copying the data,
+ however in scenarios where this is not possible the data will be copied.
+ If the creation fails or the pixmap is null, then this function returns 0.
It is the caller's responsibility to release the \c CFbsBitmap data
after use either by deleting the bitmap or calling \c Reset().
- \warning On S60 3.1 and S60 3.2 conversion mode will always be CopyData
- if QPixmap pixels have alpha values.
+ \warning On S60 3.1 and S60 3.2, semi-transparent pixmaps are always copied
+ and not duplicated.
\warning This function is only available on Symbian OS.
\sa fromSymbianCFbsBitmap()
*/
-CFbsBitmap *QPixmap::toSymbianCFbsBitmap(ConversionMode mode) const
+CFbsBitmap *QPixmap::toSymbianCFbsBitmap() const
{
- QS60PixmapData *s60data = static_cast<QS60PixmapData *>(data.data());
-
- if (isNull() || !s60data->cfbsBitmap)
+ QPixmapData *data = pixmapData();
+ if (data->isNull())
return 0;
- bool convertToArgb32 = false;
-
- QSysInfo::SymbianVersion symbianVersion = QSysInfo::symbianVersion();
- if (symbianVersion == QSysInfo::SV_9_2 || symbianVersion == QSysInfo::SV_9_3) {
- // Convert argb32_premultiplied to argb32 since Symbian 9.2 and Symbian 9.3 do
- // not support premultipied format.
-
- if (s60data->image.format() == QImage::Format_ARGB32_Premultiplied) {
- mode = CopyData;
- convertToArgb32 = true;
- }
- }
-
- CFbsBitmap *bitmap = 0;
-
- TDisplayMode displayMode = s60data->cfbsBitmap->DisplayMode();
-
- if(displayMode == EGray2) {
- //Symbian thinks set pixels are white/transparent, Qt thinks they are foreground/solid
- //So invert mono bitmaps so that masks work correctly.
- s60data->image.invertPixels();
- mode = CopyData;
- }
-
- if (mode == CopyData) {
- QImage source;
-
- if (convertToArgb32) {
- source = s60data->image.convertToFormat(QImage::Format_ARGB32);
- displayMode = EColor16MA;
- } else {
- source = s60data->image;
- }
-
- CFbsBitmap *newBitmap = createSymbianCFbsBitmap(TSize(source.width(), source.height()), displayMode);
- const uchar *sptr = source.bits();
- s60data->symbianBitmapDataAccess->beginDataAccess(newBitmap);
-
- uchar *dptr = (uchar*)newBitmap->DataAddress();
- Mem::Copy(dptr, sptr, source.numBytes());
-
- s60data->symbianBitmapDataAccess->endDataAccess(newBitmap);
-
- bitmap = newBitmap;
- } else {
-
- QT_TRAP_THROWING(bitmap = new (ELeave) CFbsBitmap);
-
- TInt err = bitmap->Duplicate(s60data->cfbsBitmap->Handle());
- if (err != KErrNone) {
- qWarning("Could not duplicate CFbsBitmap");
- delete bitmap;
- bitmap = 0;
- }
- }
-
- if(displayMode == EGray2) {
- // restore pixels
- s60data->image.invertPixels();
- }
-
- return bitmap;
+ return reinterpret_cast<CFbsBitmap*>(data->toNativeType(QPixmapData::FbsBitmap));
}
/*!
- \fn QPixmap QPixmap::fromSymbianCFbsBitmap(CFbsBitmap *bitmap, ConversionMode mode)
+ \fn QPixmap QPixmap::fromSymbianCFbsBitmap(CFbsBitmap *bitmap)
\since 4.6
- Creates a QPixmap from native \c CFbsBitmap \a bitmap. The conversion
- is based on the specified \a mode. Conversion mode is always QPixmap::CopyData
- if given \a bitmap does not have display mode of TDisplayMode::EGray2,
- \c TDisplayMode::EColor16MU or \c TDisplayMode::EColor16MAP.
-
+ Creates a QPixmap from a \c CFbsBitmap \a bitmap. Internally this function
+ will try to duplicate the bitmap handle instead of copying the data, however
+ in scenarios where this is not possible the data will be copied.
+ To be sure that QPixmap does not modify your original instance, you should
+ make a copy of your \c CFbsBitmap before calling this function.
If the CFbsBitmap is not valid this function will return a null QPixmap.
\warning This function is only available on Symbian OS.
\sa toSymbianCFbsBitmap(), {QPixmap#Pixmap Conversion}{Pixmap Conversion}
*/
-QPixmap QPixmap::fromSymbianCFbsBitmap(CFbsBitmap *bitmap, ConversionMode mode)
+QPixmap QPixmap::fromSymbianCFbsBitmap(CFbsBitmap *bitmap)
{
- if (bitmap) {
-
- bool deleteSourceBitmap = false;
-
-#ifdef Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE
-
- // Rasterize extended bitmaps
-
- TUid extendedBitmapType = bitmap->ExtendedBitmapType();
- if (extendedBitmapType != KNullUid) {
- CFbsBitmap *rasterBitmap = createSymbianCFbsBitmap(bitmap->SizeInPixels(), EColor16MA);
-
- CFbsBitmapDevice *rasterBitmapDev = 0;
- QT_TRAP_THROWING(rasterBitmapDev = CFbsBitmapDevice::NewL(rasterBitmap));
-
- CFbsBitGc *rasterBitmapGc = 0;
- TInt err = rasterBitmapDev->CreateContext(rasterBitmapGc);
- if (err != KErrNone) {
- delete rasterBitmap;
- delete rasterBitmapDev;
- rasterBitmapDev = 0;
- return QPixmap();
- }
-
- rasterBitmapGc->BitBlt(TPoint( 0, 0), bitmap);
-
- bitmap = rasterBitmap;
-
- delete rasterBitmapDev;
- delete rasterBitmapGc;
-
- rasterBitmapDev = 0;
- rasterBitmapGc = 0;
-
- deleteSourceBitmap = true;
- }
-#endif
-
-
- deleteSourceBitmap = bitmap->IsCompressedInRAM();
- CFbsBitmap *sourceBitmap = uncompress(bitmap);
-
- TDisplayMode displayMode = sourceBitmap->DisplayMode();
- QImage::Format format = qt_TDisplayMode2Format(displayMode);
-
- QImage::Format opaqueFormat = QNativeImage::systemFormat();
- QImage::Format alphaFormat = QImage::Format_ARGB32_Premultiplied;
-
- if (format != opaqueFormat && format != alphaFormat && format != QImage::Format_MonoLSB)
- mode = CopyData;
-
-
- QPixmapData::PixelType type = (format!=QImage::Format_MonoLSB)
- ? QPixmapData::PixmapType
- : QPixmapData::BitmapType;
-
- QS60PixmapData *pixmapData = 0;
-
- if (mode == CopyData) {
-
- TSize size = sourceBitmap->SizeInPixels();
-
- QSymbianBitmapDataAccess da;
- da.beginDataAccess(sourceBitmap);
- uchar *bytes = (uchar*)sourceBitmap->DataAddress();
- QImage img = QImage(bytes, size.iWidth, size.iHeight, format);
- da.endDataAccess(sourceBitmap);
-
- pixmapData = new QS60PixmapData(type);
- pixmapData->fromImage(img, Qt::AutoColor);
-
- if(deleteSourceBitmap)
- delete sourceBitmap;
-
- if(displayMode == EGray2) {
- //Symbian thinks set pixels are white/transparent, Qt thinks they are foreground/solid
- //So invert mono bitmaps so that masks work correctly.
- pixmapData->image.invertPixels();
- }
- } else {
- CFbsBitmap* duplicate = 0;
- QT_TRAP_THROWING(duplicate = new (ELeave) CFbsBitmap);
-
- TInt err = duplicate->Duplicate(sourceBitmap->Handle());
- if (err != KErrNone) {
- qWarning("Could not duplicate CFbsBitmap");
-
- if(deleteSourceBitmap)
- delete sourceBitmap;
-
- delete duplicate;
- return QPixmap();
- }
-
- pixmapData = new QS60PixmapData(type);
- pixmapData->fromSymbianBitmap(duplicate);
-
- if(deleteSourceBitmap)
- delete sourceBitmap;
- }
-
- return QPixmap(pixmapData);
- }
+ if (!bitmap)
+ return QPixmap();
- return QPixmap();
+ QPixmap pixmap;
+ pixmap.pixmapData()->fromNativeType(reinterpret_cast<void*>(bitmap), QPixmapData::FbsBitmap);
+ return pixmap;
}
QS60PixmapData::QS60PixmapData(PixelType type) : QRasterPixmapData(type),
@@ -921,7 +745,7 @@ QPixmap QPixmap::fromSymbianRSgImage(RSgImage *sgImage)
return QPixmap();
QPixmap pixmap;
- pixmap.pixmapData()->fromRSgImage(sgImage);
+ pixmap.pixmapData()->fromNativeType(reinterpret_cast<void*>(sgImage), QPixmapData::SgImage);
return pixmap;
}
@@ -949,9 +773,193 @@ RSgImage *QPixmap::toSymbianRSgImage() const
if (isNull())
return 0;
- RSgImage *sgImage = pixmapData()->toRSgImage();
+ RSgImage *sgImage = reinterpret_cast<RSgImage*>(pixmapData()->toNativeType(QPixmapData::SgImage));
return sgImage;
}
+void* QS60PixmapData::toNativeType(NativeType type)
+{
+ if (type == QPixmapData::SgImage) {
+ return 0;
+ } else if (type == QPixmapData::FbsBitmap) {
+
+ if (isNull() || !cfbsBitmap)
+ return 0;
+
+ bool convertToArgb32 = false;
+ bool needsCopy = false;
+
+ QSysInfo::SymbianVersion symbianVersion = QSysInfo::symbianVersion();
+ if (symbianVersion == QSysInfo::SV_9_2 || symbianVersion == QSysInfo::SV_9_3) {
+ // Convert argb32_premultiplied to argb32 since Symbian 9.2 and Symbian 9.3 do
+ // not support premultipied format.
+
+ if (image.format() == QImage::Format_ARGB32_Premultiplied) {
+ needsCopy = true;
+ convertToArgb32 = true;
+ }
+ }
+
+ CFbsBitmap *bitmap = 0;
+
+ TDisplayMode displayMode = cfbsBitmap->DisplayMode();
+
+ if(displayMode == EGray2) {
+ //Symbian thinks set pixels are white/transparent, Qt thinks they are foreground/solid
+ //So invert mono bitmaps so that masks work correctly.
+ image.invertPixels();
+ needsCopy = true;
+ }
+
+ if (needsCopy) {
+ QImage source;
+
+ if (convertToArgb32) {
+ source = image.convertToFormat(QImage::Format_ARGB32);
+ displayMode = EColor16MA;
+ } else {
+ source = image;
+ }
+
+ CFbsBitmap *newBitmap = createSymbianCFbsBitmap(TSize(source.width(), source.height()), displayMode);
+ const uchar *sptr = source.bits();
+ symbianBitmapDataAccess->beginDataAccess(newBitmap);
+
+ uchar *dptr = (uchar*)newBitmap->DataAddress();
+ Mem::Copy(dptr, sptr, source.numBytes());
+
+ symbianBitmapDataAccess->endDataAccess(newBitmap);
+
+ bitmap = newBitmap;
+ } else {
+
+ QT_TRAP_THROWING(bitmap = new (ELeave) CFbsBitmap);
+
+ TInt err = bitmap->Duplicate(cfbsBitmap->Handle());
+ if (err != KErrNone) {
+ qWarning("Could not duplicate CFbsBitmap");
+ delete bitmap;
+ bitmap = 0;
+ }
+ }
+
+ if(displayMode == EGray2) {
+ // restore pixels
+ image.invertPixels();
+ }
+
+ return reinterpret_cast<void*>(bitmap);
+
+ }
+
+ return 0;
+}
+
+void QS60PixmapData::fromNativeType(void* pixmap, NativeType nativeType)
+{
+ if (nativeType == QPixmapData::SgImage) {
+ return;
+ } else if (nativeType == QPixmapData::FbsBitmap && pixmap) {
+
+ CFbsBitmap *bitmap = reinterpret_cast<CFbsBitmap*>(pixmap);
+
+ bool deleteSourceBitmap = false;
+ bool needsCopy = false;
+
+#ifdef Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE
+
+ // Rasterize extended bitmaps
+
+ TUid extendedBitmapType = bitmap->ExtendedBitmapType();
+ if (extendedBitmapType != KNullUid) {
+ CFbsBitmap *rasterBitmap = createSymbianCFbsBitmap(bitmap->SizeInPixels(), EColor16MA);
+
+ CFbsBitmapDevice *rasterBitmapDev = 0;
+ QT_TRAP_THROWING(rasterBitmapDev = CFbsBitmapDevice::NewL(rasterBitmap));
+
+ CFbsBitGc *rasterBitmapGc = 0;
+ TInt err = rasterBitmapDev->CreateContext(rasterBitmapGc);
+ if (err != KErrNone) {
+ delete rasterBitmap;
+ delete rasterBitmapDev;
+ rasterBitmapDev = 0;
+ return;
+ }
+
+ rasterBitmapGc->BitBlt(TPoint( 0, 0), bitmap);
+
+ bitmap = rasterBitmap;
+
+ delete rasterBitmapDev;
+ delete rasterBitmapGc;
+
+ rasterBitmapDev = 0;
+ rasterBitmapGc = 0;
+
+ deleteSourceBitmap = true;
+ }
+#endif
+
+
+ deleteSourceBitmap = bitmap->IsCompressedInRAM();
+ CFbsBitmap *sourceBitmap = uncompress(bitmap);
+
+ TDisplayMode displayMode = sourceBitmap->DisplayMode();
+ QImage::Format format = qt_TDisplayMode2Format(displayMode);
+
+ QImage::Format opaqueFormat = QNativeImage::systemFormat();
+ QImage::Format alphaFormat = QImage::Format_ARGB32_Premultiplied;
+
+ if (format != opaqueFormat && format != alphaFormat && format != QImage::Format_MonoLSB)
+ needsCopy = true;
+
+
+ type = (format != QImage::Format_MonoLSB)
+ ? QPixmapData::PixmapType
+ : QPixmapData::BitmapType;
+
+ if (needsCopy) {
+
+ TSize size = sourceBitmap->SizeInPixels();
+
+ QSymbianBitmapDataAccess da;
+ da.beginDataAccess(sourceBitmap);
+ uchar *bytes = (uchar*)sourceBitmap->DataAddress();
+ QImage img = QImage(bytes, size.iWidth, size.iHeight, format);
+ da.endDataAccess(sourceBitmap);
+
+ fromImage(img, Qt::AutoColor);
+
+ if(deleteSourceBitmap)
+ delete sourceBitmap;
+
+ if(displayMode == EGray2) {
+ //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 {
+ CFbsBitmap* duplicate = 0;
+ QT_TRAP_THROWING(duplicate = new (ELeave) CFbsBitmap);
+
+ TInt err = duplicate->Duplicate(sourceBitmap->Handle());
+ if (err != KErrNone) {
+ qWarning("Could not duplicate CFbsBitmap");
+
+ if(deleteSourceBitmap)
+ delete sourceBitmap;
+
+ delete duplicate;
+ return;
+ }
+
+ fromSymbianBitmap(duplicate);
+
+ if(deleteSourceBitmap)
+ delete sourceBitmap;
+ }
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/image/qpixmap_s60_p.h b/src/gui/image/qpixmap_s60_p.h
index 21f1bb3..4498c05 100644
--- a/src/gui/image/qpixmap_s60_p.h
+++ b/src/gui/image/qpixmap_s60_p.h
@@ -66,17 +66,17 @@ class QSymbianBitmapDataAccess;
class QSymbianFbsHeapLock
{
public:
-
+
enum LockAction {
Unlock
};
-
+
explicit QSymbianFbsHeapLock(LockAction a);
~QSymbianFbsHeapLock();
- void relock();
-
+ void relock();
+
private:
-
+
LockAction action;
bool wasLocked;
};
@@ -102,13 +102,16 @@ public:
void beginDataAccess();
void endDataAccess(bool readOnly=false) const;
+ void* toNativeType(NativeType type);
+ void fromNativeType(void* pixmap, NativeType type);
+
private:
- void release();
- void fromSymbianBitmap(CFbsBitmap* bitmap);
- bool initSymbianBitmapContext();
+ void release();
+ void fromSymbianBitmap(CFbsBitmap* bitmap);
+ bool initSymbianBitmapContext();
QSymbianBitmapDataAccess *symbianBitmapDataAccess;
-
+
CFbsBitmap *cfbsBitmap;
CFbsBitmapDevice *bitmapDevice;
CBitmapContext *bitmapContext;
diff --git a/src/gui/image/qpixmapdata.cpp b/src/gui/image/qpixmapdata.cpp
index 65899a4..93fc2eb 100644
--- a/src/gui/image/qpixmapdata.cpp
+++ b/src/gui/image/qpixmapdata.cpp
@@ -224,14 +224,15 @@ QImage* QPixmapData::buffer()
}
#if defined(Q_OS_SYMBIAN)
-RSgImage* QPixmapData::toRSgImage()
+void* QPixmapData::toNativeType(NativeType /* type */)
{
return 0;
}
-void QPixmapData::fromRSgImage(RSgImage* rsgImage)
+void QPixmapData::fromNativeType(void* /* pixmap */, NativeType /* typre */)
{
return;
}
#endif
+
QT_END_NAMESPACE
diff --git a/src/gui/image/qpixmapdata_p.h b/src/gui/image/qpixmapdata_p.h
index 5920a06..3e85236 100644
--- a/src/gui/image/qpixmapdata_p.h
+++ b/src/gui/image/qpixmapdata_p.h
@@ -56,10 +56,6 @@
#include <QtGui/qpixmap.h>
#include <QtCore/qatomic.h>
-#if defined(Q_OS_SYMBIAN)
-class RSgImage;
-#endif
-
QT_BEGIN_NAMESPACE
class Q_GUI_EXPORT QPixmapData
@@ -70,6 +66,12 @@ public:
// Must match QPixmap::Type
PixmapType, BitmapType
};
+#if defined(Q_OS_SYMBIAN)
+ enum NativeType {
+ FbsBitmap,
+ SgImage
+ };
+#endif
enum ClassId { RasterClass, X11Class, MacClass, DirectFBClass,
OpenGLClass, OpenVGClass, CustomClass = 1024 };
@@ -114,8 +116,8 @@ public:
inline bool isNull() const { return is_null; }
#if defined(Q_OS_SYMBIAN)
- virtual RSgImage* toRSgImage();
- virtual void fromRSgImage(RSgImage* rsgImage);
+ virtual void* toNativeType(NativeType type);
+ virtual void fromNativeType(void* pixmap, NativeType type);
#endif
protected:
@@ -129,6 +131,7 @@ private:
friend class QPixmap;
friend class QGLContextPrivate;
friend class QX11PixmapData;
+ friend class QS60PixmapData;
friend class QGLTextureCache; //Needs to check the reference count
friend class QExplicitlySharedDataPointer<QPixmapData>;