summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/text/qfontengine_s60_p.h3
-rw-r--r--src/openvg/openvg.pro9
-rw-r--r--src/openvg/qpaintengine_vg.cpp29
-rw-r--r--src/openvg/qpaintengine_vg_p.h1
-rw-r--r--src/openvg/qpixmapdata_vg.cpp259
-rw-r--r--src/openvg/qvg_symbian.cpp398
-rw-r--r--src/openvg/qvgfontglyphcache_p.h95
7 files changed, 513 insertions, 281 deletions
diff --git a/src/gui/text/qfontengine_s60_p.h b/src/gui/text/qfontengine_s60_p.h
index beeb4cc..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 <private/qfontengine_p.h>
#include "qsize.h"
#include <openfont.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 883f0f3..eb60331 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 \
@@ -33,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/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp
index 4b22d5e..4992ef5 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 <QtGui/private/qeglcontext_p.h>
#include "qwindowsurface_vgegl_p.h"
@@ -80,24 +81,6 @@ Q_DECL_IMPORT extern int qt_defaultDpiY();
class QVGPaintEnginePrivate;
-class QVGFontGlyphCache
-{
-public:
- QVGFontGlyphCache();
- ~QVGFontGlyphCache();
-
- 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<glyph_t> cachedGlyphs;
-};
-
typedef QHash<QFontEngine*, QVGFontGlyphCache*> QVGFontCache;
#endif
@@ -3289,6 +3272,7 @@ QVGFontGlyphCache::QVGFontGlyphCache()
{
font = vgCreateFont(0);
scaleX = scaleY = 0.0;
+ invertedGlyphs = false;
memset(cachedGlyphsMask, 0, sizeof(cachedGlyphsMask));
}
@@ -3423,7 +3407,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;
@@ -3443,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/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/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 <private/qt_s60_p.h>
-#include <fbs.h>
-#endif
-#ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE
-#include <sgresource/sgimage.h>
-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<RSgImage*>(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<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;
- }
-}
-
-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<void*>(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<void*>(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..0e6e773
--- /dev/null
+++ b/src/openvg/qvg_symbian.cpp
@@ -0,0 +1,398 @@
+/****************************************************************************
+**
+** 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"
+#include <private/qt_s60_p.h>
+
+#include <fbs.h>
+#include <bitdev.h>
+
+#ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE
+# include <sgresource/sgimage.h>
+# ifdef SYMBIAN_FBSERV_GLYPHDATA // defined in fbs.h
+# define QT_SYMBIAN_HARDWARE_GLYPH_CACHE
+# include <graphics/fbsglyphdataiterator.h>
+# include <private/qfontengine_s60_p.h>
+# 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)
+{
+ 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;
+}
+
+#ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE
+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;
+ }
+
+ 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 (!eglImage || eglGetError() != EGL_SUCCESS) {
+ driver.Close();
+ return vgImage;
+ }
+
+ 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
+ QEgl::eglDestroyImageKHR(QEgl::display(), eglImage);
+ driver.Close();
+ return vgImage;
+}
+#endif
+
+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<RSgImage*>(pixmap);
+ destroyImages();
+ prevSize = QSize();
+
+ 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.
+ }
+
+ is_null = (w <= 0 || h <= 0);
+ source = QImage(); // vgGetImageSubData() some day?
+ recreate = false;
+ prevSize = QSize(w, h);
+ //setSerialNumber(++qt_vg_pixmap_serial);
+#endif
+ } 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;
+ }
+}
+
+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;
+ }
+
+ 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 (!eglImage || eglGetError() != EGL_SUCCESS) {
+ sgImage->Close();
+ driver.Close();
+ return 0;
+ }
+
+ VGImage dstVgImage = QVG::vgCreateEGLImageTargetKHR(eglImage);
+ if (!dstVgImage || 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<void*>(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 = const_cast<const QImage&>(source).bits();
+ 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);
+ }
+ return 0;
+}
+
+QSymbianVGFontGlyphCache::QSymbianVGFontGlyphCache() : QVGFontGlyphCache()
+{
+#ifdef QT_SYMBIAN_HARDWARE_GLYPH_CACHE
+ invertedGlyphs = true;
+#endif
+}
+
+void QSymbianVGFontGlyphCache::cacheGlyphs(QVGPaintEnginePrivate *d,
+ QFontEngine *fontEngine,
+ const glyph_t *g, int count)
+{
+#ifdef QT_SYMBIAN_HARDWARE_GLYPH_CACHE
+ QFontEngineS60 *s60fontEngine = static_cast<QFontEngineS60*>(fontEngine);
+ if (s60fontEngine->m_activeFont->TypeUid() != KCFbsFontUid)
+ return QVGFontGlyphCache::cacheGlyphs(d, fontEngine, g, count);
+
+ QVector<glyph_t> uncachedGlyphs;
+ while (count-- > 0) {
+ // Skip this glyph if we have already cached it before.
+ glyph_t glyph = *g++;
+ if (((glyph < 256) && ((cachedGlyphsMask[glyph / 32] & (1 << (glyph % 32))) != 0))
+ || cachedGlyphs.contains(glyph))
+ continue;
+ if (!uncachedGlyphs.contains(glyph))
+ uncachedGlyphs.append(glyph);
+ }
+
+ if (!uncachedGlyphs.isEmpty()) {
+ CFbsFont *cfbsFont = static_cast<CFbsFont *>(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
+}
+
+QT_END_NAMESPACE
diff --git a/src/openvg/qvgfontglyphcache_p.h b/src/openvg/qvgfontglyphcache_p.h
new file mode 100644
index 0000000..b32a873
--- /dev/null
+++ b/src/openvg/qvgfontglyphcache_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** 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 <QtCore/qvarlengtharray.h>
+#include <QtGui/private/qfontengine_p.h>
+
+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;
+ bool invertedGlyphs;
+ uint cachedGlyphsMask[256 / 32];
+ QSet<glyph_t> cachedGlyphs;
+};
+
+#if defined(Q_OS_SYMBIAN)
+class QSymbianVGFontGlyphCache : public QVGFontGlyphCache
+{
+public:
+ QSymbianVGFontGlyphCache();
+ void cacheGlyphs(QVGPaintEnginePrivate *d,
+ QFontEngine *fontEngine,
+ const glyph_t *g, int count);
+};
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QVGFONTGLYPHCACHE_H