src/openvg/qpixmapdata_vg.cpp
changeset 18 2f34d5167611
parent 3 41300fa6a67c
child 19 fcece45ef507
--- a/src/openvg/qpixmapdata_vg.cpp	Tue Feb 02 00:43:10 2010 +0200
+++ b/src/openvg/qpixmapdata_vg.cpp	Fri Apr 16 15:50:13 2010 +0300
@@ -1,6 +1,6 @@
 /****************************************************************************
 **
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
 ** All rights reserved.
 ** Contact: Nokia Corporation (qt-info@nokia.com)
 **
@@ -39,18 +39,21 @@
 **
 ****************************************************************************/
 
+#include "../src/gui/egl/qegl_p.h"
 #include "qpixmapdata_vg_p.h"
 #include "qpaintengine_vg_p.h"
 #include <QtGui/private/qdrawhelper_p.h>
 #include "qvg_p.h"
 #include "qvgimagepool_p.h"
 
+#include <private/qt_s60_p.h>
+#include <fbs.h>
 #ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE
-#include <graphics/sgimage.h>
+#include <sgresource/sgimage.h>
 typedef EGLImageKHR (*pfnEglCreateImageKHR)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, EGLint*);
 typedef EGLBoolean (*pfnEglDestroyImageKHR)(EGLDisplay, EGLImageKHR);
 typedef VGImage (*pfnVgCreateEGLImageTargetKHR)(VGeglImageKHR);
-#endif
+#endif // QT_SYMBIAN_SUPPORTS_SGIMAGE
 
 QT_BEGIN_NAMESPACE
 
@@ -232,7 +235,7 @@
 // This function works around QImage::bits() making a deep copy if the
 // QImage is not const.  We force it to be const and then get the bits.
 // XXX: Should add a QImage::constBits() in the future to replace this.
-static inline const uchar *qt_vg_imageBits(const QImage& image)
+const uchar *qt_vg_imageBits(const QImage& image)
 {
     return image.bits();
 }
@@ -425,6 +428,34 @@
 }
 
 #if defined(Q_OS_SYMBIAN)
+
+static CFbsBitmap* createBlitCopy(CFbsBitmap* bitmap)
+{
+      CFbsBitmap *copy = q_check_ptr(new CFbsBitmap);
+      if(!copy)
+        return 0;
+
+      if (copy->Create(bitmap->SizeInPixels(), bitmap->DisplayMode()) != KErrNone) {
+          delete copy;
+          copy = 0;
+
+          return 0;
+      }
+
+      CFbsBitmapDevice* bitmapDevice = 0;
+      CFbsBitGc *bitmapGc = 0;
+      QT_TRAP_THROWING(bitmapDevice = CFbsBitmapDevice::NewL(copy));
+      QT_TRAP_THROWING(bitmapGc = CFbsBitGc::NewL());
+      bitmapGc->Activate(bitmapDevice);
+
+      bitmapGc->BitBlt(TPoint(), bitmap);
+
+      delete bitmapGc;
+      delete bitmapDevice;
+
+      return copy;
+}
+
 void QVGPixmapData::cleanup()
 {
     is_null = w = h = 0;
@@ -447,23 +478,24 @@
 
         TInt err = 0;
 
-        err = SgDriver::Open();
-        if(err != KErrNone) {
+        RSgDriver driver;
+        err = driver.Open();
+        if (err != KErrNone) {
             cleanup();
             return;
         }
 
-        if(sgImage->IsNull()) {
+        if (sgImage->IsNull()) {
             cleanup();
-            SgDriver::Close();
+            driver.Close();
             return;
         }
 
         TSgImageInfo sgImageInfo;
         err = sgImage->GetInfo(sgImageInfo);
-        if(err != KErrNone) {
+        if (err != KErrNone) {
             cleanup();
-            SgDriver::Close();
+            driver.Close();
             return;
         }
 
@@ -471,9 +503,9 @@
         pfnEglDestroyImageKHR eglDestroyImageKHR = (pfnEglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR");
         pfnVgCreateEGLImageTargetKHR vgCreateEGLImageTargetKHR = (pfnVgCreateEGLImageTargetKHR) eglGetProcAddress("vgCreateEGLImageTargetKHR");
 
-        if(eglGetError() != EGL_SUCCESS || !eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateEGLImageTargetKHR) {
+        if (eglGetError() != EGL_SUCCESS || !eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateEGLImageTargetKHR) {
             cleanup();
-            SgDriver::Close();
+            driver.Close();
             return;
         }
 
@@ -484,17 +516,17 @@
                 (EGLClientBuffer)sgImage,
                 (EGLint*)KEglImageAttribs);
 
-        if(eglGetError() != EGL_SUCCESS) {
+        if (eglGetError() != EGL_SUCCESS) {
             cleanup();
-            SgDriver::Close();
+            driver.Close();
             return;
         }
 
         vgImage = vgCreateEGLImageTargetKHR(eglImage);
-        if(vgGetError() != VG_NO_ERROR) {
+        if (vgGetError() != VG_NO_ERROR) {
             cleanup();
-            eglDestroyImageKHR(context->display(), eglImage);
-            SgDriver::Close();
+            eglDestroyImageKHR(QEglContext::display(), eglImage);
+            driver.Close();
             return;
         }
 
@@ -507,10 +539,52 @@
         prevSize = QSize(w, h);
         setSerialNumber(++qt_vg_pixmap_serial);
         // release stuff
-        eglDestroyImageKHR(context->display(), eglImage);
-        SgDriver::Close();
+        eglDestroyImageKHR(QEglContext::display(), eglImage);
+        driver.Close();
     } else if (type == QPixmapData::FbsBitmap) {
+        CFbsBitmap *bitmap = reinterpret_cast<CFbsBitmap*>(pixmap);
 
+        bool deleteSourceBitmap = false;
+
+#ifdef Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE
+
+        // Rasterize extended bitmaps
+
+        TUid extendedBitmapType = bitmap->ExtendedBitmapType();
+        if (extendedBitmapType != KNullUid) {
+            bitmap = createBlitCopy(bitmap);
+            deleteSourceBitmap = true;
+        }
+#endif
+
+        if (bitmap->IsCompressedInRAM()) {
+            bitmap = createBlitCopy(bitmap);
+            deleteSourceBitmap = true;
+        }
+
+        TDisplayMode displayMode = bitmap->DisplayMode();
+        QImage::Format format = qt_TDisplayMode2Format(displayMode);
+
+        TSize size = bitmap->SizeInPixels();
+
+        bitmap->BeginDataAccess();
+        uchar *bytes = (uchar*)bitmap->DataAddress();
+        QImage img = QImage(bytes, size.iWidth, size.iHeight, format);
+        img = img.copy();
+        bitmap->EndDataAccess();
+
+        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.
+            img.invertPixels();
+        } else if(displayMode == EColor16M) {
+            img = img.rgbSwapped(); // EColor16M is BGR
+        }
+
+        fromImage(img, Qt::AutoColor);
+
+        if(deleteSourceBitmap)
+            delete bitmap;
     }
 #else
     Q_UNUSED(pixmap);
@@ -524,29 +598,25 @@
     if (type == QPixmapData::SgImage) {
         toVGImage();
 
-        if(!isValid() || vgImage == VG_INVALID_HANDLE)
+        if (!isValid() || vgImage == VG_INVALID_HANDLE)
             return 0;
 
         TInt err = 0;
 
-        err = SgDriver::Open();
-        if(err != KErrNone)
+        RSgDriver driver;
+        err = driver.Open();
+        if (err != KErrNone)
             return 0;
 
         TSgImageInfo sgInfo;
         sgInfo.iPixelFormat = EUidPixelFormatARGB_8888_PRE;
         sgInfo.iSizeInPixels.SetSize(w, h);
-        sgInfo.iUsage = ESgUsageOpenVgImage | ESgUsageOpenVgTarget;
-        sgInfo.iShareable = ETrue;
-        sgInfo.iCpuAccess = ESgCpuAccessNone;
-        sgInfo.iScreenId = KSgScreenIdMain; //KSgScreenIdAny;
-        sgInfo.iUserAttributes = NULL;
-        sgInfo.iUserAttributeCount = 0;
+        sgInfo.iUsage = ESgUsageBitOpenVgImage | ESgUsageBitOpenVgSurface;
 
         RSgImage *sgImage = q_check_ptr(new RSgImage());
         err = sgImage->Create(sgInfo, NULL, NULL);
-        if(err != KErrNone) {
-            SgDriver::Close();
+        if (err != KErrNone) {
+            driver.Close();
             return 0;
         }
 
@@ -554,8 +624,8 @@
         pfnEglDestroyImageKHR eglDestroyImageKHR = (pfnEglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR");
         pfnVgCreateEGLImageTargetKHR vgCreateEGLImageTargetKHR = (pfnVgCreateEGLImageTargetKHR) eglGetProcAddress("vgCreateEGLImageTargetKHR");
 
-        if(eglGetError() != EGL_SUCCESS || !eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateEGLImageTargetKHR) {
-            SgDriver::Close();
+        if (eglGetError() != EGL_SUCCESS || !eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateEGLImageTargetKHR) {
+            driver.Close();
             return 0;
         }
 
@@ -565,17 +635,17 @@
                 EGL_NATIVE_PIXMAP_KHR,
                 (EGLClientBuffer)sgImage,
                 (EGLint*)KEglImageAttribs);
-        if(eglGetError() != EGL_SUCCESS) {
+        if (eglGetError() != EGL_SUCCESS) {
             sgImage->Close();
-            SgDriver::Close();
+            driver.Close();
             return 0;
         }
 
         VGImage dstVgImage = vgCreateEGLImageTargetKHR(eglImage);
-        if(vgGetError() != VG_NO_ERROR) {
-            eglDestroyImageKHR(context->display(), eglImage);
+        if (vgGetError() != VG_NO_ERROR) {
+            eglDestroyImageKHR(QEglContext::display(), eglImage);
             sgImage->Close();
-            SgDriver::Close();
+            driver.Close();
             return 0;
         }
 
@@ -583,17 +653,35 @@
                 vgImage, 0, 0,
                 w, h, VG_FALSE);
 
-        if(vgGetError() != VG_NO_ERROR) {
+        if (vgGetError() != VG_NO_ERROR) {
             sgImage->Close();
             sgImage = 0;
         }
         // release stuff
         vgDestroyImage(dstVgImage);
-        eglDestroyImageKHR(context->display(), eglImage);
-        SgDriver::Close();
+        eglDestroyImageKHR(QEglContext::display(), eglImage);
+        driver.Close();
         return reinterpret_cast<void*>(sgImage);
     } else if (type == QPixmapData::FbsBitmap) {
-        return 0;
+        CFbsBitmap *bitmap = q_check_ptr(new CFbsBitmap);
+
+        if (bitmap) {
+            if (bitmap->Create(TSize(source.width(), source.height()),
+                              EColor16MAP) == KErrNone) {
+                const uchar *sptr = qt_vg_imageBits(source);
+                bitmap->BeginDataAccess();
+
+                uchar *dptr = (uchar*)bitmap->DataAddress();
+                Mem::Copy(dptr, sptr, source.byteCount());
+
+                bitmap->EndDataAccess();
+            } else {
+                delete bitmap;
+                bitmap = 0;
+            }
+        }
+
+        return reinterpret_cast<void*>(bitmap);
     }
 #else
     Q_UNUSED(type);