From a07ae6df3c274639ff68856cd2e68689a3ddbf3f Mon Sep 17 00:00:00 2001 From: Jason Barron Date: Mon, 1 Feb 2010 10:54:53 +0100 Subject: 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 --- src/gui/text/qfontengine_s60_p.h | 1 + src/openvg/openvg.pro | 6 +- src/openvg/qpixmapdata_vg.cpp | 259 ----------------------------- src/openvg/qvg_symbian.cpp | 348 +++++++++++++++++++++++++++++++++++++++ src/openvg/qvgfontglyphcache_p.h | 9 + 5 files changed, 363 insertions(+), 260 deletions(-) create mode 100644 src/openvg/qvg_symbian.cpp diff --git a/src/gui/text/qfontengine_s60_p.h b/src/gui/text/qfontengine_s60_p.h index beeb4cc..9400d55 100644 --- a/src/gui/text/qfontengine_s60_p.h +++ b/src/gui/text/qfontengine_s60_p.h @@ -134,6 +134,7 @@ public: private: friend class QFontPrivate; + friend class QSymbianVGFontGlyphCache; QFixed glyphAdvance(HB_Glyph glyph) const; CFont *fontWithSize(qreal size) const; diff --git a/src/openvg/openvg.pro b/src/openvg/openvg.pro index 0000db8..eb60331 100644 --- a/src/openvg/openvg.pro +++ b/src/openvg/openvg.pro @@ -34,7 +34,11 @@ contains(QT_CONFIG, egl) { qwindowsurface_vgegl.cpp } -symbian: DEFINES += QVG_RECREATE_ON_SIZE_CHANGE QVG_BUFFER_SCROLLING +symbian { + DEFINES += QVG_RECREATE_ON_SIZE_CHANGE QVG_BUFFER_SCROLLING + SOURCES += \ + qvg_symbian.cpp +} include(../qbase.pri) diff --git a/src/openvg/qpixmapdata_vg.cpp b/src/openvg/qpixmapdata_vg.cpp index a4afc95..cb413d0 100644 --- a/src/openvg/qpixmapdata_vg.cpp +++ b/src/openvg/qpixmapdata_vg.cpp @@ -48,15 +48,6 @@ #include "qvg_p.h" #include "qvgimagepool_p.h" -#if defined(Q_OS_SYMBIAN) -#include -#include -#endif -#ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE -#include -typedef VGImage (*pfnVgCreateEGLImageTargetKHR)(VGeglImageKHR); -#endif // QT_SYMBIAN_SUPPORTS_SGIMAGE - QT_BEGIN_NAMESPACE static int qt_vg_pixmap_serial = 0; @@ -421,254 +412,4 @@ Q_OPENVG_EXPORT VGImage qPixmapToVGImage(const QPixmap& pixmap) return VG_INVALID_HANDLE; } -#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; - recreate = false; - source = QImage(); -} - -void QVGPixmapData::fromNativeType(void* pixmap, NativeType type) -{ - if (type == QPixmapData::SgImage && pixmap) { -#if defined(QT_SYMBIAN_SUPPORTS_SGIMAGE) && !defined(QT_NO_EGL) - RSgImage *sgImage = reinterpret_cast(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; - } - - pfnVgCreateEGLImageTargetKHR vgCreateEGLImageTargetKHR = (pfnVgCreateEGLImageTargetKHR) eglGetProcAddress("vgCreateEGLImageTargetKHR"); - - if (eglGetError() != EGL_SUCCESS || !(QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_pixmap")) || !vgCreateEGLImageTargetKHR) { - cleanup(); - driver.Close(); - return; - } - - const EGLint KEglImageAttribs[] = {EGL_IMAGE_PRESERVED_SYMBIAN, EGL_TRUE, EGL_NONE}; - EGLImageKHR eglImage = QEgl::eglCreateImageKHR(QEgl::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(); - QEgl::eglDestroyImageKHR(QEgl::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 - QEgl::eglDestroyImageKHR(QEgl::display(), eglImage); - driver.Close(); -#endif - } else if (type == QPixmapData::FbsBitmap) { - CFbsBitmap *bitmap = reinterpret_cast(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; - } -} - -void* QVGPixmapData::toNativeType(NativeType type) -{ - if (type == QPixmapData::SgImage) { -#if defined(QT_SYMBIAN_SUPPORTS_SGIMAGE) && !defined(QT_NO_EGL) - 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; - } - - pfnVgCreateEGLImageTargetKHR vgCreateEGLImageTargetKHR = (pfnVgCreateEGLImageTargetKHR) eglGetProcAddress("vgCreateEGLImageTargetKHR"); - - if (eglGetError() != EGL_SUCCESS || !(QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_pixmap")) || !vgCreateEGLImageTargetKHR) { - driver.Close(); - return 0; - } - - const EGLint KEglImageAttribs[] = {EGL_IMAGE_PRESERVED_SYMBIAN, EGL_TRUE, EGL_NONE}; - EGLImageKHR eglImage = QEgl::eglCreateImageKHR(QEgl::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) { - QEgl::eglDestroyImageKHR(QEgl::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); - QEgl::eglDestroyImageKHR(QEgl::display(), eglImage); - driver.Close(); - return reinterpret_cast(sgImage); -#endif - } 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 = source.constBits(); - bitmap->BeginDataAccess(); - - uchar *dptr = (uchar*)bitmap->DataAddress(); - Mem::Copy(dptr, sptr, source.byteCount()); - - bitmap->EndDataAccess(); - } else { - delete bitmap; - bitmap = 0; - } - } - - return reinterpret_cast(bitmap); - } - return 0; -} -#endif //Q_OS_SYMBIAN - QT_END_NAMESPACE 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 +#include +#include +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 +#include +#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(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(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(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(bitmap); + } +#else + Q_UNUSED(type); + return 0; +#endif +} + +void QSymbianVGFontGlyphCache::cacheGlyphs(QVGPaintEnginePrivate *d, + const QTextItemInt &ti, + const QVarLengthArray &glyphs) +{ + QFontEngineS60 *fontEngine = static_cast(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 diff --git a/src/openvg/qvgfontglyphcache_p.h b/src/openvg/qvgfontglyphcache_p.h index ced0d735..4ba07ba 100644 --- a/src/openvg/qvgfontglyphcache_p.h +++ b/src/openvg/qvgfontglyphcache_p.h @@ -79,6 +79,15 @@ public: QSet cachedGlyphs; }; +#if defined( Q_OS_SYMBIAN) +class QSymbianVGFontGlyphCache : public QVGFontGlyphCache +{ + void cacheGlyphs(QVGPaintEnginePrivate *d, + const QTextItemInt &ti, + const QVarLengthArray &glyphs); +}; +#endif + QT_END_NAMESPACE #endif // QVGFONTGLYPHCACHE_H -- cgit v0.12