From 0c73b18d0750bee9da4b88de595aa6093b5be820 Mon Sep 17 00:00:00 2001
From: Jani Hautakangas <ext-jani.hautakangas@nokia.com>
Date: Wed, 3 Feb 2010 10:46:53 +0200
Subject: Implementation for QVGPixmapData to/fromSymbianCFbsBitmap functions.

---
 mkspecs/common/symbian/symbian.conf |  2 +-
 src/openvg/qpixmapdata_vg.cpp       | 94 ++++++++++++++++++++++++++++++++++++-
 tests/auto/qpixmap/tst_qpixmap.cpp  | 45 +++++++++++++++++-
 3 files changed, 136 insertions(+), 5 deletions(-)

diff --git a/mkspecs/common/symbian/symbian.conf b/mkspecs/common/symbian/symbian.conf
index b1ef354..7162bad 100644
--- a/mkspecs/common/symbian/symbian.conf
+++ b/mkspecs/common/symbian/symbian.conf
@@ -70,7 +70,7 @@ QMAKE_LIBS_GUI          = $$QMAKE_LIBS_CORE -lfbscli -lbitgdi -lhal -lgdi -lws32
 QMAKE_LIBS_NETWORK      = 
 QMAKE_LIBS_EGL          = -llibEGL
 QMAKE_LIBS_OPENGL       = 
-QMAKE_LIBS_OPENVG       = -llibOpenVG -lgraphicsresource
+QMAKE_LIBS_OPENVG       = -llibOpenVG -lgraphicsresource -lfbscli -lbitgdi -lgdi
 QMAKE_LIBS_COMPAT       = 
 QMAKE_LIBS_QT_ENTRY     = -llibcrt0.lib
 QMAKE_LIBS_S60          = -lavkon
diff --git a/src/openvg/qpixmapdata_vg.cpp b/src/openvg/qpixmapdata_vg.cpp
index cc0e5a1..3087b77 100644
--- a/src/openvg/qpixmapdata_vg.cpp
+++ b/src/openvg/qpixmapdata_vg.cpp
@@ -46,11 +46,13 @@
 #include "qvgimagepool_p.h"
 
 #ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE
+#include <private/qt_s60_p.h>
+#include <fbs.h>
 #include <graphics/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
 
@@ -425,6 +427,34 @@ Q_OPENVG_EXPORT VGImage qPixmapToVGImage(const QPixmap& pixmap)
 }
 
 #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;
@@ -510,7 +540,49 @@ void QVGPixmapData::fromNativeType(void* pixmap, NativeType type)
         eglDestroyImageKHR(context->display(), eglImage);
         SgDriver::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);
@@ -593,7 +665,25 @@ void* QVGPixmapData::toNativeType(NativeType type)
         SgDriver::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);
diff --git a/tests/auto/qpixmap/tst_qpixmap.cpp b/tests/auto/qpixmap/tst_qpixmap.cpp
index 8bcd5e8..d7c6ad3 100644
--- a/tests/auto/qpixmap/tst_qpixmap.cpp
+++ b/tests/auto/qpixmap/tst_qpixmap.cpp
@@ -145,9 +145,11 @@ private slots:
     void fromWinHICON();
 #endif
 
-#if defined(Q_WS_S60)
+#if defined(Q_OS_SYMBIAN)
     void fromSymbianCFbsBitmap_data();
     void fromSymbianCFbsBitmap();
+    void toSymbianCFbsBitmap_data();
+    void toSymbianCFbsBitmap();
 #endif
 
     void onlyNullPixmapsOutsideGuiThread();
@@ -1110,7 +1112,7 @@ void tst_QPixmap::fromWinHICON()
 
 #endif // Q_WS_WIN
 
-#if defined(Q_WS_S60)
+#if defined(Q_OS_SYMBIAN)
 Q_DECLARE_METATYPE(TDisplayMode)
 
 void tst_QPixmap::fromSymbianCFbsBitmap_data()
@@ -1206,6 +1208,45 @@ void tst_QPixmap::fromSymbianCFbsBitmap()
 
     CleanupStack::PopAndDestroy(3);
 }
+
+void tst_QPixmap::toSymbianCFbsBitmap_data()
+{
+    QTest::addColumn<int>("red");
+    QTest::addColumn<int>("green");
+    QTest::addColumn<int>("blue");
+
+    QTest::newRow("red")   << 255 << 0 << 0;
+    QTest::newRow("green") << 0 << 255 << 0;
+    QTest::newRow("blue")  << 0 << 0 << 255;
+}
+
+void tst_QPixmap::toSymbianCFbsBitmap()
+{
+    QFETCH(int, red);
+    QFETCH(int, green);
+    QFETCH(int, blue);
+
+    QPixmap pm(100, 100);
+    pm.fill(QColor(red, green, blue));
+
+    CFbsBitmap *bitmap = pm.toSymbianCFbsBitmap();
+
+    QVERIFY(bitmap != 0);
+
+    // Verify size
+    QCOMPARE(100, (int) bitmap->SizeInPixels().iWidth);
+    QCOMPARE(100, (int) bitmap->SizeInPixels().iHeight);
+
+    // Verify pixel color
+    TRgb pixel;
+    bitmap->GetPixel(pixel, TPoint(0,0));
+    QCOMPARE((int)pixel.Red(), red);
+    QCOMPARE((int)pixel.Green(), green);
+    QCOMPARE((int)pixel.Blue(), blue);
+
+    // Clean up
+    delete bitmap;
+}
 #endif
 
 void tst_QPixmap::onlyNullPixmapsOutsideGuiThread()
-- 
cgit v0.12