summaryrefslogtreecommitdiffstats
path: root/src/openvg/qvg_symbian.cpp
diff options
context:
space:
mode:
authorJason Barron <jbarron@trolltech.com>2010-02-01 09:54:53 (GMT)
committerJason Barron <jbarron@trolltech.com>2010-07-12 07:03:03 (GMT)
commita07ae6df3c274639ff68856cd2e68689a3ddbf3f (patch)
tree0a5e09ae25ac92803f869fa09af3cc0d6cb54db9 /src/openvg/qvg_symbian.cpp
parent8757747b05940d8ce6e9550b382a7ea196db90b4 (diff)
downloadQt-a07ae6df3c274639ff68856cd2e68689a3ddbf3f.zip
Qt-a07ae6df3c274639ff68856cd2e68689a3ddbf3f.tar.gz
Qt-a07ae6df3c274639ff68856cd2e68689a3ddbf3f.tar.bz2
Add new file for Symbian specific VG stuff and add Symbian glyph cache.
Factor out the Symbian specific bits of QVGPixmapData into a separate file and introduce our subclassed implementation of the VG font cache. Also make our font cache a friend of the S60 font engine because the cache needs to access the CFont member to create the glyph image. Reviewed-by: Alessandro Portale
Diffstat (limited to 'src/openvg/qvg_symbian.cpp')
-rw-r--r--src/openvg/qvg_symbian.cpp348
1 files changed, 348 insertions, 0 deletions
diff --git a/src/openvg/qvg_symbian.cpp b/src/openvg/qvg_symbian.cpp
new file mode 100644
index 0000000..4a429d5
--- /dev/null
+++ b/src/openvg/qvg_symbian.cpp
@@ -0,0 +1,348 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qpixmapdata_vg_p.h"
+#include "qvgfontglyphcache_p.h"
+
+#ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE
+#include <private/qt_s60_p.h>
+#include <fbs.h>
+#include <sgresource/sgimage.h>
+typedef EGLImageKHR (*pfnEglCreateImageKHR)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, EGLint*);
+typedef EGLBoolean (*pfnEglDestroyImageKHR)(EGLDisplay, EGLImageKHR);
+typedef VGImage (*pfnVgCreateEGLImageTargetKHR)(VGeglImageKHR);
+#endif
+
+#if 1//defined(SYMBIAN_GDI_GLYPHDATA) && defined(QT_SYMBIAN_SUPPORTS_SGIMAGE)
+#include <graphics/glyphdataiterator.h>
+#include <private/qfontengine_s60_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+extern int qt_vg_pixmap_serial;
+
+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;
+ recreate = false;
+ source = QImage();
+}
+
+void QVGPixmapData::fromNativeType(void* pixmap, NativeType type)
+{
+#if defined(QT_SYMBIAN_SUPPORTS_SGIMAGE) && !defined(QT_NO_EGL)
+ if (type == QPixmapData::SgImage && pixmap) {
+ RSgImage *sgImage = reinterpret_cast<RSgImage*>(pixmap);
+ // when "0" used as argument then
+ // default display, context are used
+ if (!context)
+ context = qt_vg_create_context(0, QInternal::Pixmap);
+
+ destroyImages();
+ prevSize = QSize();
+
+ TInt err = 0;
+
+ RSgDriver driver;
+ err = driver.Open();
+ if (err != KErrNone) {
+ cleanup();
+ return;
+ }
+
+ if (sgImage->IsNull()) {
+ cleanup();
+ driver.Close();
+ return;
+ }
+
+ TSgImageInfo sgImageInfo;
+ err = sgImage->GetInfo(sgImageInfo);
+ if (err != KErrNone) {
+ cleanup();
+ driver.Close();
+ return;
+ }
+
+ pfnEglCreateImageKHR eglCreateImageKHR = (pfnEglCreateImageKHR) eglGetProcAddress("eglCreateImageKHR");
+ pfnEglDestroyImageKHR eglDestroyImageKHR = (pfnEglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR");
+ pfnVgCreateEGLImageTargetKHR vgCreateEGLImageTargetKHR = (pfnVgCreateEGLImageTargetKHR) eglGetProcAddress("vgCreateEGLImageTargetKHR");
+
+ if (eglGetError() != EGL_SUCCESS || !eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateEGLImageTargetKHR) {
+ cleanup();
+ driver.Close();
+ return;
+ }
+
+ const EGLint KEglImageAttribs[] = {EGL_IMAGE_PRESERVED_SYMBIAN, EGL_TRUE, EGL_NONE};
+ EGLImageKHR eglImage = eglCreateImageKHR(context->display(),
+ EGL_NO_CONTEXT,
+ EGL_NATIVE_PIXMAP_KHR,
+ (EGLClientBuffer)sgImage,
+ (EGLint*)KEglImageAttribs);
+
+ if (eglGetError() != EGL_SUCCESS) {
+ cleanup();
+ driver.Close();
+ return;
+ }
+
+ vgImage = vgCreateEGLImageTargetKHR(eglImage);
+ if (vgGetError() != VG_NO_ERROR) {
+ cleanup();
+ eglDestroyImageKHR(context->display(), eglImage);
+ driver.Close();
+ return;
+ }
+
+ w = sgImageInfo.iSizeInPixels.iWidth;
+ h = sgImageInfo.iSizeInPixels.iHeight;
+ d = 32; // We always use ARGB_Premultiplied for VG pixmaps.
+ is_null = (w <= 0 || h <= 0);
+ source = QImage();
+ recreate = false;
+ prevSize = QSize(w, h);
+ //setSerialNumber(++qt_vg_pixmap_serial);
+ // release stuff
+ eglDestroyImageKHR(context->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);
+ Q_UNUSED(type);
+#endif
+}
+
+void* QVGPixmapData::toNativeType(NativeType type)
+{
+#if defined(QT_SYMBIAN_SUPPORTS_SGIMAGE) && !defined(QT_NO_EGL)
+ if (type == QPixmapData::SgImage) {
+ toVGImage();
+
+ if (!isValid() || vgImage == VG_INVALID_HANDLE)
+ return 0;
+
+ TInt err = 0;
+
+ RSgDriver driver;
+ err = driver.Open();
+ if (err != KErrNone)
+ return 0;
+
+ TSgImageInfo sgInfo;
+ sgInfo.iPixelFormat = EUidPixelFormatARGB_8888_PRE;
+ sgInfo.iSizeInPixels.SetSize(w, h);
+ sgInfo.iUsage = ESgUsageBitOpenVgImage | ESgUsageBitOpenVgSurface;
+
+ RSgImage *sgImage = q_check_ptr(new RSgImage());
+ err = sgImage->Create(sgInfo, NULL, NULL);
+ if (err != KErrNone) {
+ driver.Close();
+ return 0;
+ }
+
+ pfnEglCreateImageKHR eglCreateImageKHR = (pfnEglCreateImageKHR) eglGetProcAddress("eglCreateImageKHR");
+ pfnEglDestroyImageKHR eglDestroyImageKHR = (pfnEglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR");
+ pfnVgCreateEGLImageTargetKHR vgCreateEGLImageTargetKHR = (pfnVgCreateEGLImageTargetKHR) eglGetProcAddress("vgCreateEGLImageTargetKHR");
+
+ if (eglGetError() != EGL_SUCCESS || !eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateEGLImageTargetKHR) {
+ driver.Close();
+ return 0;
+ }
+
+ const EGLint KEglImageAttribs[] = {EGL_IMAGE_PRESERVED_SYMBIAN, EGL_TRUE, EGL_NONE};
+ EGLImageKHR eglImage = eglCreateImageKHR(context->display(),
+ EGL_NO_CONTEXT,
+ EGL_NATIVE_PIXMAP_KHR,
+ (EGLClientBuffer)sgImage,
+ (EGLint*)KEglImageAttribs);
+ if (eglGetError() != EGL_SUCCESS) {
+ sgImage->Close();
+ driver.Close();
+ return 0;
+ }
+
+ VGImage dstVgImage = vgCreateEGLImageTargetKHR(eglImage);
+ if (vgGetError() != VG_NO_ERROR) {
+ eglDestroyImageKHR(context->display(), eglImage);
+ sgImage->Close();
+ driver.Close();
+ return 0;
+ }
+
+ vgCopyImage(dstVgImage, 0, 0,
+ vgImage, 0, 0,
+ w, h, VG_FALSE);
+
+ if (vgGetError() != VG_NO_ERROR) {
+ sgImage->Close();
+ sgImage = 0;
+ }
+ // release stuff
+ vgDestroyImage(dstVgImage);
+ eglDestroyImageKHR(context->display(), eglImage);
+ driver.Close();
+ return reinterpret_cast<void*>(sgImage);
+ } else if (type == QPixmapData::FbsBitmap) {
+ 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);
+ return 0;
+#endif
+}
+
+void QSymbianVGFontGlyphCache::cacheGlyphs(QVGPaintEnginePrivate *d,
+ const QTextItemInt &ti,
+ const QVarLengthArray<glyph_t> &glyphs)
+{
+ QFontEngineS60 *fontEngine = static_cast<QFontEngineS60*>(ti.fontEngine);
+ CFont *font = fontEngine->m_font;
+
+ RGlyphDataIterator iter;
+ int err = iter.Open(*font, glyphs.data(), glyphs.count());
+
+// for (; err == KErrNone; err = iter.Next()) {
+// const RSgImage& image = iter.Image();
+// const TRect& rect = iter.Rect();
+// const TOpenFontCharMetrics& metrics = iter.Metrics();
+//
+// QPixmap pix = QPixmap::fromSymbianRSgImage(*image);
+//
+// }
+// iter.Close();
+//
+// if (err != KErrNotFound) {
+// // Handle the error...
+// }
+}
+
+QT_END_NAMESPACE