diff options
-rw-r--r-- | src/gui/text/qfontengine_s60_p.h | 3 | ||||
-rw-r--r-- | src/openvg/openvg.pro | 9 | ||||
-rw-r--r-- | src/openvg/qpaintengine_vg.cpp | 29 | ||||
-rw-r--r-- | src/openvg/qpaintengine_vg_p.h | 1 | ||||
-rw-r--r-- | src/openvg/qpixmapdata_vg.cpp | 259 | ||||
-rw-r--r-- | src/openvg/qvg_symbian.cpp | 398 | ||||
-rw-r--r-- | src/openvg/qvgfontglyphcache_p.h | 95 |
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 |