From d7b41ca83bd11647a90b78fa388d278cf98189ab Mon Sep 17 00:00:00 2001 From: Jason Barron Date: Mon, 1 Feb 2010 09:46:44 +0100 Subject: Make cacheGlyphs() function (and the destructor) virtual. This class will be implemented differently on Symbian due to the presence of a class that allows cross process sharing of glyph images so make this function virtual. Reviewed-by: Rhys Weatherley --- src/openvg/qpaintengine_vg.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp index 4b22d5e..9290b79 100644 --- a/src/openvg/qpaintengine_vg.cpp +++ b/src/openvg/qpaintengine_vg.cpp @@ -84,9 +84,9 @@ class QVGFontGlyphCache { public: QVGFontGlyphCache(); - ~QVGFontGlyphCache(); + virtual ~QVGFontGlyphCache(); - void cacheGlyphs(QVGPaintEnginePrivate *d, QFontEngine *fontEngine, const glyph_t *g, int count); + virtual void cacheGlyphs(QVGPaintEnginePrivate *d, QFontEngine *fontEngine, const glyph_t *g, int count); void setScaleFromText(const QFont &font, QFontEngine *fontEngine); -- cgit v0.12 From 8757747b05940d8ce6e9550b382a7ea196db90b4 Mon Sep 17 00:00:00 2001 From: Jason Barron Date: Mon, 1 Feb 2010 09:50:51 +0100 Subject: Move QVGFontGlyphCache from source file into a separate header Needed in order to subclass and override in the Symbian specific implementation. Reviewed-by: Rhys Weatherley --- src/openvg/openvg.pro | 3 +- src/openvg/qpaintengine_vg.cpp | 19 +-------- src/openvg/qpaintengine_vg_p.h | 1 - src/openvg/qvgfontglyphcache_p.h | 84 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+), 20 deletions(-) create mode 100644 src/openvg/qvgfontglyphcache_p.h diff --git a/src/openvg/openvg.pro b/src/openvg/openvg.pro index 883f0f3..0000db8 100644 --- a/src/openvg/openvg.pro +++ b/src/openvg/openvg.pro @@ -17,7 +17,8 @@ HEADERS += \ qpixmapdata_vg_p.h \ qpixmapfilter_vg_p.h \ qvgcompositionhelper_p.h \ - qvgimagepool_p.h + qvgimagepool_p.h \ + qvgfontglyphcache_p.h SOURCES += \ qpaintengine_vg.cpp \ qpixmapdata_vg.cpp \ diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp index 9290b79..564b390 100644 --- a/src/openvg/qpaintengine_vg.cpp +++ b/src/openvg/qpaintengine_vg.cpp @@ -44,6 +44,7 @@ #include "qpixmapfilter_vg_p.h" #include "qvgcompositionhelper_p.h" #include "qvgimagepool_p.h" +#include "qvgfontglyphcache_p.h" #if !defined(QT_NO_EGL) #include #include "qwindowsurface_vgegl_p.h" @@ -80,24 +81,6 @@ Q_DECL_IMPORT extern int qt_defaultDpiY(); class QVGPaintEnginePrivate; -class QVGFontGlyphCache -{ -public: - QVGFontGlyphCache(); - virtual ~QVGFontGlyphCache(); - - virtual void cacheGlyphs(QVGPaintEnginePrivate *d, QFontEngine *fontEngine, const glyph_t *g, int count); - - void setScaleFromText(const QFont &font, QFontEngine *fontEngine); - - VGFont font; - VGfloat scaleX; - VGfloat scaleY; - - uint cachedGlyphsMask[256 / 32]; - QSet cachedGlyphs; -}; - typedef QHash QVGFontCache; #endif diff --git a/src/openvg/qpaintengine_vg_p.h b/src/openvg/qpaintengine_vg_p.h index 33c49ba..75cf053 100644 --- a/src/openvg/qpaintengine_vg_p.h +++ b/src/openvg/qpaintengine_vg_p.h @@ -172,7 +172,6 @@ private: bool clearRect(const QRectF &rect, const QColor &color); }; - QT_END_NAMESPACE #endif diff --git a/src/openvg/qvgfontglyphcache_p.h b/src/openvg/qvgfontglyphcache_p.h new file mode 100644 index 0000000..ced0d735 --- /dev/null +++ b/src/openvg/qvgfontglyphcache_p.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** 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 QtOpenVG 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$ +** +****************************************************************************/ + +#ifndef QVGFONTGLYPHCACHE_H +#define QVGFONTGLYPHCACHE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +QT_BEGIN_NAMESPACE + +class QVGPaintEnginePrivate; + +class QVGFontGlyphCache +{ +public: + QVGFontGlyphCache(); + virtual ~QVGFontGlyphCache(); + + virtual void cacheGlyphs(QVGPaintEnginePrivate *d, + QFontEngine *fontEngine, + const glyph_t *g, int count); + void setScaleFromText(const QFont &font, QFontEngine *fontEngine); + + VGFont font; + VGfloat scaleX; + VGfloat scaleY; + + uint cachedGlyphsMask[256 / 32]; + QSet cachedGlyphs; +}; + +QT_END_NAMESPACE + +#endif // QVGFONTGLYPHCACHE_H -- cgit v0.12 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 From 4c392ee7f9f7445620269fbd3250a17a982e2369 Mon Sep 17 00:00:00 2001 From: Jason Barron Date: Mon, 15 Feb 2010 16:19:04 +0100 Subject: Factor out RSgImage -> VGImage conversion to separate function. This code will now be used by both the fromNativeType() function and the upcoming glyph cache implementation. We also change the #ifdef's location here slightly because even if we do not have support for RSgImage, we still want to be able to support the CFbsBitmap conversion functions for the OpenVG graphics system. Reviewed-by: Alessandro Portale --- src/openvg/qvg_symbian.cpp | 148 +++++++++++++++++++++++---------------------- 1 file changed, 75 insertions(+), 73 deletions(-) diff --git a/src/openvg/qvg_symbian.cpp b/src/openvg/qvg_symbian.cpp index 4a429d5..09962f6 100644 --- a/src/openvg/qvg_symbian.cpp +++ b/src/openvg/qvg_symbian.cpp @@ -87,6 +87,70 @@ static CFbsBitmap* createBlitCopy(CFbsBitmap* bitmap) return copy; } +static VGImage sgImageToVGImage(QEglContext *context, const RSgImage &sgImage) +{ + // when "0" used as argument then + // default display, context are used + if (!context) + context = qt_vg_create_context(0, QInternal::Pixmap); + + VGImage vgImage = VG_INVALID_HANDLE; + + TInt err = 0; + + RSgDriver driver; + err = driver.Open(); + if (err != KErrNone) { + return vgImage; + } + + if (sgImage.IsNull()) { + driver.Close(); + return vgImage; + } + + TSgImageInfo sgImageInfo; + err = sgImage.GetInfo(sgImageInfo); + if (err != KErrNone) { + driver.Close(); + return vgImage; + } + + 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 vgImage; + } + + 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) { + driver.Close(); + return vgImage; + } + + vgImage = vgCreateEGLImageTargetKHR(eglImage); + if (vgGetError() != VG_NO_ERROR) { + eglDestroyImageKHR(context->display(), eglImage); + driver.Close(); + return vgImage; + } + + //setSerialNumber(++qt_vg_pixmap_serial); + // release stuff + eglDestroyImageKHR(context->display(), eglImage); + driver.Close(); + return vgImage; +} + void QVGPixmapData::cleanup() { is_null = w = h = 0; @@ -96,82 +160,25 @@ void QVGPixmapData::cleanup() void QVGPixmapData::fromNativeType(void* pixmap, NativeType type) { -#if defined(QT_SYMBIAN_SUPPORTS_SGIMAGE) && !defined(QT_NO_EGL) if (type == QPixmapData::SgImage && pixmap) { +#if defined(QT_SYMBIAN_SUPPORTS_SGIMAGE) && !defined(QT_NO_EGL) 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; + VGImage vgImage = sgImageToVGImage(context, *sgImage); + if (vgImage != VG_INVALID_HANDLE) { + w = vgGetParameteri(vgImage, VG_IMAGE_WIDTH); + h = vgGetParameteri(vgImage, VG_IMAGE_HEIGHT); + d = 32; // We always use ARGB_Premultiplied for VG pixmaps. } - 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(); + source = QImage(); // vgGetImageSubData() some day? recreate = false; prevSize = QSize(w, h); //setSerialNumber(++qt_vg_pixmap_serial); - // release stuff - eglDestroyImageKHR(context->display(), eglImage); - driver.Close(); +#endif } else if (type == QPixmapData::FbsBitmap) { CFbsBitmap *bitmap = reinterpret_cast(pixmap); @@ -217,16 +224,12 @@ void QVGPixmapData::fromNativeType(void* pixmap, NativeType type) 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) { +#if defined(QT_SYMBIAN_SUPPORTS_SGIMAGE) && !defined(QT_NO_EGL) toVGImage(); if (!isValid() || vgImage == VG_INVALID_HANDLE) @@ -293,13 +296,14 @@ void* QVGPixmapData::toNativeType(NativeType type) eglDestroyImageKHR(context->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 = qt_vg_imageBits(source); + const uchar *sptr = const_cast(source).bits(); bitmap->BeginDataAccess(); uchar *dptr = (uchar*)bitmap->DataAddress(); @@ -314,8 +318,6 @@ void* QVGPixmapData::toNativeType(NativeType type) return reinterpret_cast(bitmap); } -#else - Q_UNUSED(type); return 0; #endif } -- cgit v0.12 From 940930dd8102511e6890ed661cf3d2dd88c2e1f4 Mon Sep 17 00:00:00 2001 From: Jason Barron Date: Mon, 15 Feb 2010 16:23:23 +0100 Subject: Enable cross-process glyph cache for OpenVG graphics system on Symbian. This introduces a specialized OpenVG font cache for the Symbian platform. By using RGlyphDataIterator we can create a VGImage to store inside a VGFont without having to upload our own glyph image. This works by utilizing RSgImage which can be used to share handles to graphics memory across processes thus allowing glyph images to be shared by multiple processes and reducing graphics memory usage. Reviewed-by: Alessandro Portale --- src/gui/text/qfontengine_s60_p.h | 2 +- src/openvg/qpaintengine_vg.cpp | 4 +++ src/openvg/qvg_symbian.cpp | 75 +++++++++++++++++++++++++++++----------- src/openvg/qvgfontglyphcache_p.h | 2 +- 4 files changed, 61 insertions(+), 22 deletions(-) diff --git a/src/gui/text/qfontengine_s60_p.h b/src/gui/text/qfontengine_s60_p.h index 9400d55..d65f13b 100644 --- a/src/gui/text/qfontengine_s60_p.h +++ b/src/gui/text/qfontengine_s60_p.h @@ -54,7 +54,7 @@ // #include "qconfig.h" -#include "qfontengine_p.h" +#include #include "qsize.h" #include diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp index 564b390..01c7a7e 100644 --- a/src/openvg/qpaintengine_vg.cpp +++ b/src/openvg/qpaintengine_vg.cpp @@ -3406,7 +3406,11 @@ void QVGPaintEngine::drawStaticTextItem(QStaticTextItem *textItem) if (it != d->fontCache.constEnd()) { glyphCache = it.value(); } else { +#ifdef Q_OS_SYMBIAN + glyphCache = new QSymbianVGFontGlyphCache(); +#else glyphCache = new QVGFontGlyphCache(); +#endif if (glyphCache->font == VG_INVALID_HANDLE) { qWarning("QVGPaintEngine::drawTextItem: OpenVG fonts are not supported by the OpenVG engine"); delete glyphCache; diff --git a/src/openvg/qvg_symbian.cpp b/src/openvg/qvg_symbian.cpp index 09962f6..e6086d0 100644 --- a/src/openvg/qvg_symbian.cpp +++ b/src/openvg/qvg_symbian.cpp @@ -45,16 +45,17 @@ #ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE #include #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) +#ifdef SYMBIAN_GDI_GLYPHDATA // defined in gdi.h +#define QT_SYMBIAN_HARDWARE_GLYPH_CACHE #include #include #endif +#endif QT_BEGIN_NAMESPACE @@ -319,32 +320,66 @@ void* QVGPixmapData::toNativeType(NativeType type) return reinterpret_cast(bitmap); } return 0; -#endif } void QSymbianVGFontGlyphCache::cacheGlyphs(QVGPaintEnginePrivate *d, const QTextItemInt &ti, const QVarLengthArray &glyphs) { +#ifdef QT_SYMBIAN_HARDWARE_GLYPH_CACHE QFontEngineS60 *fontEngine = static_cast(ti.fontEngine); - CFont *font = fontEngine->m_font; + CFont *cfont = fontEngine->m_activeFont; + +// QVarLengthArray adjustedGlyphs(glyphs); +// for (int i = 0; i < glyphs.count(); ++i) +// adjustedGlyphs[i] |= 0x80000000; 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... -// } + int err = iter.Open(*cfont, (const unsigned int*)glyphs.constData(), glyphs.count()); + + if (err == KErrNotSupported || err == KErrInUse) { // Fallback in possibly supported error cases + iter.Close(); + qWarning("Falling back to default QVGFontGlyphCache"); + return QVGFontGlyphCache::cacheGlyphs(d, ti, glyphs); + } + + for (; err == KErrNone; err = iter.Next()) { + // Skip this glyph if we have already cached it before. + const unsigned int glyph = iter.GlyphCode(); + if (((glyph < 256) && ((cachedGlyphsMask[glyph / 32] & (1 << (glyph % 32))) != 0)) + || cachedGlyphs.contains(glyph)) + continue; + + const RSgImage& image = iter.Image(); + const TOpenFontCharMetrics& metrics = iter.Metrics(); + + TRect glyphBounds; + metrics.GetHorizBounds(glyphBounds); + VGImage vgImage = sgImageToVGImage(0, image); + VGfloat origin[2]; + VGfloat escapement[2]; + origin[0] = -glyphBounds.iTl.iX + 0.5f; + origin[1] = -glyphBounds.iTl.iY + 0.5f; + escapement[0] = metrics.HorizAdvance(); + escapement[1] = 0; + vgSetGlyphToImage(font, iter.GlyphCode(), vgImage, origin, escapement); + vgDestroyImage(vgImage); + + // Add to cache + if (glyph < 256) + cachedGlyphsMask[glyph / 32] |= (1 << (glyph % 32)); + else + cachedGlyphs.insert(glyph); + } + iter.Close(); + + if (err == KErrNoMemory || err == KErrNoGraphicsMemory) + qWarning("Not enough memory to cache glyph"); + else if (err != KErrNotFound) + qWarning("Received error %d from glyph cache", err); +#else + QVGFontGlyphCache::cacheGlyphs(d, ti, glyphs); +#endif } QT_END_NAMESPACE diff --git a/src/openvg/qvgfontglyphcache_p.h b/src/openvg/qvgfontglyphcache_p.h index 4ba07ba..ee11082 100644 --- a/src/openvg/qvgfontglyphcache_p.h +++ b/src/openvg/qvgfontglyphcache_p.h @@ -79,7 +79,7 @@ public: QSet cachedGlyphs; }; -#if defined( Q_OS_SYMBIAN) +#if defined(Q_OS_SYMBIAN) class QSymbianVGFontGlyphCache : public QVGFontGlyphCache { void cacheGlyphs(QVGPaintEnginePrivate *d, -- cgit v0.12 From 8c6bfd9f2d34822e39812c07e821fa17ab3fdcb2 Mon Sep 17 00:00:00 2001 From: Jason Barron Date: Fri, 26 Feb 2010 13:47:45 +0100 Subject: Ensure glyphs are upright instead of upside-down. The OpenVG paint engine traditionally takes glyph images from the alphaMapForGlyph() function which returns the glyph image in the upright projection. When it constructs a VGImage from this image, it passes a positive data stride which will read the top scanline of the source image into the bottom scanline of the VGImage due to the VG coordinate system. It then uses the path transform where the 'sy' value of the matrix is set to -1 and this re-inverts everything when drawing. With the Symbian based glyph cache, the VGImage is constructed from a RSgImage which is a hardware resource and compensates for the coordinate system used by VG and GL at the time it is created. In the case of the hardware glyph cache, the glyph image is read into the RSgImage using a negative data stride so it does not need to be inverted when drawn. To allow for this, introduce a flag which indicates that the 'sy' entry of the matrix should be flipped such that the glyph is drawn normally. Also in this patch is a change to the glyph origin which now uses the bottom of the glyph metric bounding rect instead of the top due to orientation of the glyph inside the VGImage. Reviewed-by: Alessandro Portale --- src/openvg/qpaintengine_vg.cpp | 6 ++++++ src/openvg/qvg_symbian.cpp | 7 ++++++- src/openvg/qvgfontglyphcache_p.h | 3 +++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp index 01c7a7e..4992ef5 100644 --- a/src/openvg/qpaintengine_vg.cpp +++ b/src/openvg/qpaintengine_vg.cpp @@ -3272,6 +3272,7 @@ QVGFontGlyphCache::QVGFontGlyphCache() { font = vgCreateFont(0); scaleX = scaleY = 0.0; + invertedGlyphs = false; memset(cachedGlyphsMask, 0, sizeof(cachedGlyphsMask)); } @@ -3430,6 +3431,11 @@ void QVGPaintEngine::drawStaticTextItem(QStaticTextItem *textItem) #if defined(QVG_NO_IMAGE_GLYPHS) glyphTransform.scale(glyphCache->scaleX, glyphCache->scaleY); #endif + + // Some glyph caches can create the VGImage upright + if (glyphCache->invertedGlyphs) + glyphTransform.scale(1, -1); + d->setTransform(VG_MATRIX_GLYPH_USER_TO_SURFACE, glyphTransform); // Add the glyphs from the text item into the glyph cache. diff --git a/src/openvg/qvg_symbian.cpp b/src/openvg/qvg_symbian.cpp index e6086d0..8c954e6 100644 --- a/src/openvg/qvg_symbian.cpp +++ b/src/openvg/qvg_symbian.cpp @@ -322,6 +322,11 @@ void* QVGPixmapData::toNativeType(NativeType type) return 0; } +QSymbianVGFontGlyphCache::QSymbianVGFontGlyphCache() : QVGFontGlyphCache() +{ + invertedGlyphs = true; +} + void QSymbianVGFontGlyphCache::cacheGlyphs(QVGPaintEnginePrivate *d, const QTextItemInt &ti, const QVarLengthArray &glyphs) @@ -359,7 +364,7 @@ void QSymbianVGFontGlyphCache::cacheGlyphs(QVGPaintEnginePrivate *d, VGfloat origin[2]; VGfloat escapement[2]; origin[0] = -glyphBounds.iTl.iX + 0.5f; - origin[1] = -glyphBounds.iTl.iY + 0.5f; + origin[1] = glyphBounds.iBr.iY + 0.5f; escapement[0] = metrics.HorizAdvance(); escapement[1] = 0; vgSetGlyphToImage(font, iter.GlyphCode(), vgImage, origin, escapement); diff --git a/src/openvg/qvgfontglyphcache_p.h b/src/openvg/qvgfontglyphcache_p.h index ee11082..8f25322 100644 --- a/src/openvg/qvgfontglyphcache_p.h +++ b/src/openvg/qvgfontglyphcache_p.h @@ -74,6 +74,7 @@ public: VGFont font; VGfloat scaleX; VGfloat scaleY; + bool invertedGlyphs; uint cachedGlyphsMask[256 / 32]; QSet cachedGlyphs; @@ -82,6 +83,8 @@ public: #if defined(Q_OS_SYMBIAN) class QSymbianVGFontGlyphCache : public QVGFontGlyphCache { +public: + QSymbianVGFontGlyphCache(); void cacheGlyphs(QVGPaintEnginePrivate *d, const QTextItemInt &ti, const QVarLengthArray &glyphs); -- cgit v0.12 From 420f10e0e13a744dc6a6b47f55f39138a9618641 Mon Sep 17 00:00:00 2001 From: Jason Barron Date: Mon, 1 Feb 2010 09:50:51 +0100 Subject: Move QVGFontGlyphCache from source file into a separate header Needed in order to subclass and override in the Symbian specific implementation. Reviewed-by: Rhys Weatherley --- src/openvg/qvgfontglyphcache_p.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/openvg/qvgfontglyphcache_p.h b/src/openvg/qvgfontglyphcache_p.h index 8f25322..2bf79aa 100644 --- a/src/openvg/qvgfontglyphcache_p.h +++ b/src/openvg/qvgfontglyphcache_p.h @@ -75,7 +75,6 @@ public: VGfloat scaleX; VGfloat scaleY; bool invertedGlyphs; - uint cachedGlyphsMask[256 / 32]; QSet cachedGlyphs; }; -- cgit v0.12 From 3606cd38f7fbcfb9a9d6cb43d5a99da65891e0b1 Mon Sep 17 00:00:00 2001 From: Jason Barron Date: Tue, 9 Mar 2010 10:07:32 +0100 Subject: Don't invert glyphs for the default VG font cache on Symbian. If the hardware glyph cache API is not represent and in use, then the glyphs will not be inverted. Reviewed-by: TrustMe --- src/openvg/qvg_symbian.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/openvg/qvg_symbian.cpp b/src/openvg/qvg_symbian.cpp index 8c954e6..214fedf 100644 --- a/src/openvg/qvg_symbian.cpp +++ b/src/openvg/qvg_symbian.cpp @@ -324,7 +324,9 @@ void* QVGPixmapData::toNativeType(NativeType type) QSymbianVGFontGlyphCache::QSymbianVGFontGlyphCache() : QVGFontGlyphCache() { +#ifdef QT_SYMBIAN_HARDWARE_GLYPH_CACHE invertedGlyphs = true; +#endif } void QSymbianVGFontGlyphCache::cacheGlyphs(QVGPaintEnginePrivate *d, -- cgit v0.12 From edd3ffa92df8c6e0fb68f3eb6e10872e69532c90 Mon Sep 17 00:00:00 2001 From: Jason Barron Date: Thu, 17 Jun 2010 08:33:58 +0200 Subject: Convert to new EGL API. Recent changes in Qt's EGL layer required some changes in the code used to convert RSgImage to/from VGImage. Reviewed-by: Gunnar Sletta --- src/openvg/qvg_symbian.cpp | 85 +++++++++++++++++++--------------------- src/openvg/qvgfontglyphcache_p.h | 4 +- 2 files changed, 42 insertions(+), 47 deletions(-) diff --git a/src/openvg/qvg_symbian.cpp b/src/openvg/qvg_symbian.cpp index 214fedf..9bcb6f5 100644 --- a/src/openvg/qvg_symbian.cpp +++ b/src/openvg/qvg_symbian.cpp @@ -43,22 +43,35 @@ #include "qvgfontglyphcache_p.h" #ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE -#include -#include -#include -#include -typedef EGLImageKHR (*pfnEglCreateImageKHR)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, EGLint*); -typedef EGLBoolean (*pfnEglDestroyImageKHR)(EGLDisplay, EGLImageKHR); -typedef VGImage (*pfnVgCreateEGLImageTargetKHR)(VGeglImageKHR); -#ifdef SYMBIAN_GDI_GLYPHDATA // defined in gdi.h -#define QT_SYMBIAN_HARDWARE_GLYPH_CACHE -#include -#include -#endif +# include +# include +# include +# include +# ifdef SYMBIAN_GDI_GLYPHDATA // defined in gdi.h +# define QT_SYMBIAN_HARDWARE_GLYPH_CACHE +# include +# include +# endif #endif QT_BEGIN_NAMESPACE +typedef VGImage (*_vgCreateEGLImageTargetKHR)(VGeglImageKHR); +static _vgCreateEGLImageTargetKHR qt_vgCreateEGLImageTargetKHR = 0; + +namespace QVG +{ + VGImage vgCreateEGLImageTargetKHR(VGeglImageKHR eglImage); +} + +VGImage QVG::vgCreateEGLImageTargetKHR(VGeglImageKHR eglImage) +{ + if (!qt_vgCreateEGLImageTargetKHR && QEgl::hasExtension("EGL_KHR_image")) + qt_vgCreateEGLImageTargetKHR = (_vgCreateEGLImageTargetKHR) eglGetProcAddress("vgCreateEGLImageTargetKHR"); + + return qt_vgCreateEGLImageTargetKHR ? qt_vgCreateEGLImageTargetKHR(eglImage) : 0; +} + extern int qt_vg_pixmap_serial; static CFbsBitmap* createBlitCopy(CFbsBitmap* bitmap) @@ -117,37 +130,28 @@ static VGImage sgImageToVGImage(QEglContext *context, const RSgImage &sgImage) return vgImage; } - 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 vgImage; - } - const EGLint KEglImageAttribs[] = {EGL_IMAGE_PRESERVED_SYMBIAN, EGL_TRUE, EGL_NONE}; - EGLImageKHR eglImage = eglCreateImageKHR(context->display(), + EGLImageKHR eglImage = QEgl::eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, (EGLClientBuffer)&sgImage, (EGLint*)KEglImageAttribs); - if (eglGetError() != EGL_SUCCESS) { + if (!eglImage || eglGetError() != EGL_SUCCESS) { driver.Close(); return vgImage; } - vgImage = vgCreateEGLImageTargetKHR(eglImage); - if (vgGetError() != VG_NO_ERROR) { - eglDestroyImageKHR(context->display(), eglImage); + vgImage = QVG::vgCreateEGLImageTargetKHR(eglImage); + if (!vgImage || vgGetError() != VG_NO_ERROR) { + QEgl::eglDestroyImageKHR(QEgl::display(), eglImage); driver.Close(); return vgImage; } //setSerialNumber(++qt_vg_pixmap_serial); // release stuff - eglDestroyImageKHR(context->display(), eglImage); + QEgl::eglDestroyImageKHR(QEgl::display(), eglImage); driver.Close(); return vgImage; } @@ -255,30 +259,21 @@ void* QVGPixmapData::toNativeType(NativeType type) 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(), + EGLImageKHR eglImage = QEgl::eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, (EGLClientBuffer)sgImage, (EGLint*)KEglImageAttribs); - if (eglGetError() != EGL_SUCCESS) { + if (!eglImage || eglGetError() != EGL_SUCCESS) { sgImage->Close(); driver.Close(); return 0; } - VGImage dstVgImage = vgCreateEGLImageTargetKHR(eglImage); - if (vgGetError() != VG_NO_ERROR) { - eglDestroyImageKHR(context->display(), eglImage); + VGImage dstVgImage = QVG::vgCreateEGLImageTargetKHR(eglImage); + if (!dstVgImage || vgGetError() != VG_NO_ERROR) { + QEgl::eglDestroyImageKHR(QEgl::display(), eglImage); sgImage->Close(); driver.Close(); return 0; @@ -294,7 +289,7 @@ void* QVGPixmapData::toNativeType(NativeType type) } // release stuff vgDestroyImage(dstVgImage); - eglDestroyImageKHR(context->display(), eglImage); + QEgl::eglDestroyImageKHR(QEgl::display(), eglImage); driver.Close(); return reinterpret_cast(sgImage); #endif @@ -330,8 +325,8 @@ QSymbianVGFontGlyphCache::QSymbianVGFontGlyphCache() : QVGFontGlyphCache() } void QSymbianVGFontGlyphCache::cacheGlyphs(QVGPaintEnginePrivate *d, - const QTextItemInt &ti, - const QVarLengthArray &glyphs) + QFontEngine *fontEngine, + const glyph_t *g, int count) { #ifdef QT_SYMBIAN_HARDWARE_GLYPH_CACHE QFontEngineS60 *fontEngine = static_cast(ti.fontEngine); @@ -385,7 +380,7 @@ void QSymbianVGFontGlyphCache::cacheGlyphs(QVGPaintEnginePrivate *d, else if (err != KErrNotFound) qWarning("Received error %d from glyph cache", err); #else - QVGFontGlyphCache::cacheGlyphs(d, ti, glyphs); + QVGFontGlyphCache::cacheGlyphs(d, fontEngine, g, count); #endif } diff --git a/src/openvg/qvgfontglyphcache_p.h b/src/openvg/qvgfontglyphcache_p.h index 2bf79aa..b32a873 100644 --- a/src/openvg/qvgfontglyphcache_p.h +++ b/src/openvg/qvgfontglyphcache_p.h @@ -85,8 +85,8 @@ class QSymbianVGFontGlyphCache : public QVGFontGlyphCache public: QSymbianVGFontGlyphCache(); void cacheGlyphs(QVGPaintEnginePrivate *d, - const QTextItemInt &ti, - const QVarLengthArray &glyphs); + QFontEngine *fontEngine, + const glyph_t *g, int count); }; #endif -- cgit v0.12 From 0113025720a1a07ac6a40b1f9c95746a904fdf4e Mon Sep 17 00:00:00 2001 From: Jason Barron Date: Mon, 5 Jul 2010 16:38:57 +0200 Subject: Minor modifications and optimizations to the Symbian HW glyph cache. After the latest round of API reviews, the Symbian glyph cache has now been moved from GDI to FBS and this required some changes in Qt's implementation. Also incorporate an optimization where we first iterate over the glyph vector to eliminate glyphs that are already cached in Qt's glyph cache. This way we only open the glyph iterator on glyphs that we need. Reviewed-by: Alessandro Portale --- src/openvg/qvg_symbian.cpp | 109 +++++++++++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 49 deletions(-) diff --git a/src/openvg/qvg_symbian.cpp b/src/openvg/qvg_symbian.cpp index 9bcb6f5..0e6e773 100644 --- a/src/openvg/qvg_symbian.cpp +++ b/src/openvg/qvg_symbian.cpp @@ -41,15 +41,16 @@ #include "qpixmapdata_vg_p.h" #include "qvgfontglyphcache_p.h" +#include + +#include +#include #ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE -# include -# include -# include # include -# ifdef SYMBIAN_GDI_GLYPHDATA // defined in gdi.h +# ifdef SYMBIAN_FBSERV_GLYPHDATA // defined in fbs.h # define QT_SYMBIAN_HARDWARE_GLYPH_CACHE -# include +# include # include # endif #endif @@ -101,6 +102,7 @@ static CFbsBitmap* createBlitCopy(CFbsBitmap* bitmap) return copy; } +#ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE static VGImage sgImageToVGImage(QEglContext *context, const RSgImage &sgImage) { // when "0" used as argument then @@ -155,6 +157,7 @@ static VGImage sgImageToVGImage(QEglContext *context, const RSgImage &sgImage) driver.Close(); return vgImage; } +#endif void QVGPixmapData::cleanup() { @@ -329,56 +332,64 @@ void QSymbianVGFontGlyphCache::cacheGlyphs(QVGPaintEnginePrivate *d, const glyph_t *g, int count) { #ifdef QT_SYMBIAN_HARDWARE_GLYPH_CACHE - QFontEngineS60 *fontEngine = static_cast(ti.fontEngine); - CFont *cfont = fontEngine->m_activeFont; - -// QVarLengthArray adjustedGlyphs(glyphs); -// for (int i = 0; i < glyphs.count(); ++i) -// adjustedGlyphs[i] |= 0x80000000; - - RGlyphDataIterator iter; - int err = iter.Open(*cfont, (const unsigned int*)glyphs.constData(), glyphs.count()); - - if (err == KErrNotSupported || err == KErrInUse) { // Fallback in possibly supported error cases - iter.Close(); - qWarning("Falling back to default QVGFontGlyphCache"); - return QVGFontGlyphCache::cacheGlyphs(d, ti, glyphs); - } + QFontEngineS60 *s60fontEngine = static_cast(fontEngine); + if (s60fontEngine->m_activeFont->TypeUid() != KCFbsFontUid) + return QVGFontGlyphCache::cacheGlyphs(d, fontEngine, g, count); - for (; err == KErrNone; err = iter.Next()) { + QVector uncachedGlyphs; + while (count-- > 0) { // Skip this glyph if we have already cached it before. - const unsigned int glyph = iter.GlyphCode(); + glyph_t glyph = *g++; if (((glyph < 256) && ((cachedGlyphsMask[glyph / 32] & (1 << (glyph % 32))) != 0)) || cachedGlyphs.contains(glyph)) - continue; - - const RSgImage& image = iter.Image(); - const TOpenFontCharMetrics& metrics = iter.Metrics(); - - TRect glyphBounds; - metrics.GetHorizBounds(glyphBounds); - VGImage vgImage = sgImageToVGImage(0, image); - VGfloat origin[2]; - VGfloat escapement[2]; - origin[0] = -glyphBounds.iTl.iX + 0.5f; - origin[1] = glyphBounds.iBr.iY + 0.5f; - escapement[0] = metrics.HorizAdvance(); - escapement[1] = 0; - vgSetGlyphToImage(font, iter.GlyphCode(), vgImage, origin, escapement); - vgDestroyImage(vgImage); - - // Add to cache - if (glyph < 256) - cachedGlyphsMask[glyph / 32] |= (1 << (glyph % 32)); - else - cachedGlyphs.insert(glyph); + continue; + if (!uncachedGlyphs.contains(glyph)) + uncachedGlyphs.append(glyph); } - iter.Close(); - if (err == KErrNoMemory || err == KErrNoGraphicsMemory) - qWarning("Not enough memory to cache glyph"); - else if (err != KErrNotFound) - qWarning("Received error %d from glyph cache", err); + if (!uncachedGlyphs.isEmpty()) { + CFbsFont *cfbsFont = static_cast(s60fontEngine->m_activeFont); + RFbsGlyphDataIterator iter; + + int err = iter.Open(*cfbsFont, (const unsigned int*)uncachedGlyphs.constData(), uncachedGlyphs.count()); + + if (err == KErrNotSupported || err == KErrInUse) { // Fallback in possibly supported error cases + iter.Close(); + qWarning("Falling back to default QVGFontGlyphCache"); + return QVGFontGlyphCache::cacheGlyphs(d, fontEngine, g, count); + } + + for (; err == KErrNone; err = iter.Next()) { + const unsigned int glyph = iter.GlyphCode(); + + const RSgImage& image = iter.Image(); + const TOpenFontCharMetrics& metrics = iter.Metrics(); + + TRect glyphBounds; + metrics.GetHorizBounds(glyphBounds); + VGImage vgImage = sgImageToVGImage(0, image); + VGfloat origin[2]; + VGfloat escapement[2]; + origin[0] = -glyphBounds.iTl.iX; + origin[1] = glyphBounds.iBr.iY; + escapement[0] = 0; + escapement[1] = 0; + vgSetGlyphToImage(font, glyph, vgImage, origin, escapement); + vgDestroyImage(vgImage); + + // Add to cache + if (glyph < 256) + cachedGlyphsMask[glyph / 32] |= (1 << (glyph % 32)); + else + cachedGlyphs.insert(glyph); + } + iter.Close(); + + if (err == KErrNoMemory || err == KErrNoGraphicsMemory) + qWarning("Not enough memory to cache glyph"); + else if (err != KErrNotFound) + qWarning("Received error %d from glyph cache", err); + } #else QVGFontGlyphCache::cacheGlyphs(d, fontEngine, g, count); #endif -- cgit v0.12