diff options
author | Qt Continuous Integration System <qt-info@nokia.com> | 2010-07-12 09:29:04 (GMT) |
---|---|---|
committer | Qt Continuous Integration System <qt-info@nokia.com> | 2010-07-12 09:29:04 (GMT) |
commit | 28ad5063e0fd3e268408a2483c06413a454a2a61 (patch) | |
tree | 394d21f8da7d3f932ff1c42442f67542148179e2 | |
parent | 7f3d351002d4a138860651769309e20d2b593112 (diff) | |
parent | 0113025720a1a07ac6a40b1f9c95746a904fdf4e (diff) | |
download | Qt-28ad5063e0fd3e268408a2483c06413a454a2a61.zip Qt-28ad5063e0fd3e268408a2483c06413a454a2a61.tar.gz Qt-28ad5063e0fd3e268408a2483c06413a454a2a61.tar.bz2 |
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/qt-s60-public into 4.7-integration
* '4.7' of scm.dev.nokia.troll.no:qt/qt-s60-public:
Minor modifications and optimizations to the Symbian HW glyph cache.
Convert to new EGL API.
Don't invert glyphs for the default VG font cache on Symbian.
Move QVGFontGlyphCache from source file into a separate header
Ensure glyphs are upright instead of upside-down.
Enable cross-process glyph cache for OpenVG graphics system on Symbian.
Factor out RSgImage -> VGImage conversion to separate function.
Add new file for Symbian specific VG stuff and add Symbian glyph cache.
Move QVGFontGlyphCache from source file into a separate header
Make cacheGlyphs() function (and the destructor) virtual.
-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 |