summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBradley T. Hughes <bradley.hughes@nokia.com>2009-06-23 05:53:53 (GMT)
committerBradley T. Hughes <bradley.hughes@nokia.com>2009-06-23 05:53:53 (GMT)
commitfbe44b843194f3892e163ecec1be52fb498e2ddd (patch)
tree857c749710a71e2d485bd134d6542c62ac51c4e5 /src
parent6fc3873707ae9e8c002b14800bac9fd64faca42b (diff)
parent3647de5291db9e359e7844f80202251f47e83a97 (diff)
downloadQt-fbe44b843194f3892e163ecec1be52fb498e2ddd.zip
Qt-fbe44b843194f3892e163ecec1be52fb498e2ddd.tar.gz
Qt-fbe44b843194f3892e163ecec1be52fb498e2ddd.tar.bz2
Merge branch 'master' of git@scm.dev.nokia.troll.no:qt/qt
Diffstat (limited to 'src')
-rw-r--r--src/corelib/global/qglobal.h12
-rw-r--r--src/corelib/statemachine/qstate.cpp11
-rw-r--r--src/corelib/statemachine/qstatemachine.cpp12
-rw-r--r--src/gui/egl/egl.pri28
-rw-r--r--src/gui/egl/qegl.cpp403
-rw-r--r--src/gui/egl/qegl_p.h (renamed from src/opengl/qegl_p.h)90
-rw-r--r--src/gui/egl/qegl_qws.cpp111
-rw-r--r--src/gui/egl/qegl_symbian.cpp (renamed from src/opengl/qegl_qws.cpp)76
-rw-r--r--src/gui/egl/qegl_wince.cpp (renamed from src/opengl/qegl_wince.cpp)45
-rw-r--r--src/gui/egl/qegl_x11.cpp (renamed from src/opengl/qegl_x11egl.cpp)33
-rw-r--r--src/gui/egl/qeglproperties.cpp (renamed from src/opengl/qegl.cpp)368
-rw-r--r--src/gui/egl/qeglproperties_p.h138
-rw-r--r--src/gui/gui.pro2
-rw-r--r--src/gui/kernel/qapplication_x11.cpp48
-rw-r--r--src/gui/widgets/qdockarealayout.cpp99
-rw-r--r--src/gui/widgets/qdockarealayout_p.h6
-rw-r--r--src/gui/widgets/qmainwindowlayout.cpp4
-rw-r--r--src/gui/widgets/qtoolbararealayout.cpp4
-rw-r--r--src/network/access/qnetworkdiskcache.cpp14
-rw-r--r--src/opengl/opengl.pro17
-rw-r--r--src/opengl/qgl_egl_p.h2
-rw-r--r--src/opengl/qgl_qws.cpp61
-rw-r--r--src/opengl/qgl_wince.cpp4
-rw-r--r--src/opengl/qgl_x11egl.cpp6
-rw-r--r--src/opengl/qglpixelbuffer_egl.cpp10
-rw-r--r--src/openvg/openvg.pro48
-rw-r--r--src/openvg/qpaintengine_vg.cpp3231
-rw-r--r--src/openvg/qpaintengine_vg_p.h163
-rw-r--r--src/openvg/qpixmapdata_vg.cpp344
-rw-r--r--src/openvg/qpixmapdata_vg_p.h113
-rw-r--r--src/openvg/qpixmapfilter_vg.cpp340
-rw-r--r--src/openvg/qpixmapfilter_vg_p.h108
-rw-r--r--src/openvg/qvg.h65
-rw-r--r--src/openvg/qvg_p.h110
-rw-r--r--src/openvg/qvgcompositionhelper_p.h91
-rw-r--r--src/openvg/qwindowsurface_vg.cpp120
-rw-r--r--src/openvg/qwindowsurface_vg_p.h92
-rw-r--r--src/openvg/qwindowsurface_vgegl.cpp751
-rw-r--r--src/openvg/qwindowsurface_vgegl_p.h163
-rw-r--r--src/plugins/graphicssystems/graphicssystems.pro6
-rw-r--r--src/plugins/graphicssystems/openvg/main.cpp71
-rw-r--r--src/plugins/graphicssystems/openvg/openvg.pro20
-rw-r--r--src/plugins/graphicssystems/openvg/qgraphicssystem_vg.cpp70
-rw-r--r--src/plugins/graphicssystems/openvg/qgraphicssystem_vg_p.h71
-rw-r--r--src/plugins/graphicssystems/shivavg/README8
-rw-r--r--src/plugins/graphicssystems/shivavg/main.cpp71
-rw-r--r--src/plugins/graphicssystems/shivavg/shivavg.pro16
-rw-r--r--src/plugins/graphicssystems/shivavg/shivavggraphicssystem.cpp62
-rw-r--r--src/plugins/graphicssystems/shivavg/shivavggraphicssystem.h60
-rw-r--r--src/plugins/graphicssystems/shivavg/shivavgwindowsurface.cpp370
-rw-r--r--src/plugins/graphicssystems/shivavg/shivavgwindowsurface.h76
-rw-r--r--src/src.pro4
-rw-r--r--src/svg/qsvggraphics.cpp5
-rw-r--r--src/svg/qsvggraphics_p.h5
-rw-r--r--src/svg/qsvghandler.cpp63
-rw-r--r--src/svg/qsvgstructure.cpp98
-rw-r--r--src/svg/qsvgstyle.cpp7
-rw-r--r--src/svg/qsvgstyle_p.h34
-rw-r--r--src/svg/qsvgtinydocument.cpp12
-rw-r--r--src/testlib/qtestlog.cpp2
60 files changed, 7795 insertions, 679 deletions
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 3e6771c..0721c39 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -1143,6 +1143,11 @@ class QDataStream;
# else
# define Q_OPENGL_EXPORT Q_DECL_IMPORT
# endif
+# if defined(QT_BUILD_OPENVG_LIB)
+# define Q_OPENVG_EXPORT Q_DECL_EXPORT
+# else
+# define Q_OPENVG_EXPORT Q_DECL_IMPORT
+# endif
# if defined(QT_BUILD_XML_LIB)
# define Q_XML_EXPORT Q_DECL_EXPORT
# else
@@ -1182,6 +1187,7 @@ class QDataStream;
# define Q_SVG_EXPORT Q_DECL_IMPORT
# define Q_CANVAS_EXPORT Q_DECL_IMPORT
# define Q_OPENGL_EXPORT Q_DECL_IMPORT
+# define Q_OPENVG_EXPORT Q_DECL_IMPORT
# define Q_XML_EXPORT Q_DECL_IMPORT
# define Q_XMLPATTERNS_EXPORT Q_DECL_IMPORT
# define Q_SCRIPT_EXPORT Q_DECL_IMPORT
@@ -1207,6 +1213,7 @@ class QDataStream;
# define Q_NETWORK_EXPORT Q_DECL_EXPORT
# define Q_SVG_EXPORT Q_DECL_EXPORT
# define Q_OPENGL_EXPORT Q_DECL_EXPORT
+# define Q_OPENVG_EXPORT Q_DECL_EXPORT
# define Q_XML_EXPORT Q_DECL_EXPORT
# define Q_XMLPATTERNS_EXPORT Q_DECL_EXPORT
# define Q_SCRIPT_EXPORT Q_DECL_EXPORT
@@ -2252,6 +2259,7 @@ QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPathSysconf();
#define QT_MODULE_TEST 0x04000
#define QT_MODULE_DBUS 0x08000
#define QT_MODULE_SCRIPTTOOLS 0x10000
+#define QT_MODULE_OPENVG 0x20000
/* Qt editions */
#define QT_EDITION_CONSOLE (QT_MODULE_CORE \
@@ -2271,6 +2279,7 @@ QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPathSysconf();
| QT_MODULE_GUI \
| QT_MODULE_NETWORK \
| QT_MODULE_OPENGL \
+ | QT_MODULE_OPENVG \
| QT_MODULE_SQL \
| QT_MODULE_XML \
| QT_MODULE_XMLPATTERNS \
@@ -2314,6 +2323,9 @@ QT_LICENSED_MODULE(Network)
#if (QT_EDITION & QT_MODULE_OPENGL)
QT_LICENSED_MODULE(OpenGL)
#endif
+#if (QT_EDITION & QT_MODULE_OPENVG)
+QT_LICENSED_MODULE(OpenVG)
+#endif
#if (QT_EDITION & QT_MODULE_SQL)
QT_LICENSED_MODULE(Sql)
#endif
diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp
index c42c9c9..fd7ddef 100644
--- a/src/corelib/statemachine/qstate.cpp
+++ b/src/corelib/statemachine/qstate.cpp
@@ -333,10 +333,13 @@ QSignalTransition *QState::addTransition(QObject *sender, const char *signal,
return 0;
}
int offset = (*signal == '0'+QSIGNAL_CODE) ? 1 : 0;
- if (sender->metaObject()->indexOfSignal(signal+offset) == -1) {
- qWarning("QState::addTransition: no such signal %s::%s",
- sender->metaObject()->className(), signal+offset);
- return 0;
+ const QMetaObject *meta = sender->metaObject();
+ if (meta->indexOfSignal(signal+offset) == -1) {
+ if (meta->indexOfSignal(QMetaObject::normalizedSignature(signal+offset)) == -1) {
+ qWarning("QState::addTransition: no such signal %s::%s",
+ meta->className(), signal+offset);
+ return 0;
+ }
}
QSignalTransition *trans = new QSignalTransition(sender, signal, QList<QAbstractState*>() << target);
addTransition(trans);
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp
index 758bdbe..682dd97 100644
--- a/src/corelib/statemachine/qstatemachine.cpp
+++ b/src/corelib/statemachine/qstatemachine.cpp
@@ -1316,11 +1316,15 @@ void QStateMachinePrivate::registerSignalTransition(QSignalTransition *transitio
QByteArray signal = QSignalTransitionPrivate::get(transition)->signal;
if (signal.startsWith('0'+QSIGNAL_CODE))
signal.remove(0, 1);
- int signalIndex = sender->metaObject()->indexOfSignal(signal);
+ const QMetaObject *meta = sender->metaObject();
+ int signalIndex = meta->indexOfSignal(signal);
if (signalIndex == -1) {
- qWarning("QSignalTransition: no such signal: %s::%s",
- sender->metaObject()->className(), signal.constData());
- return;
+ signalIndex = meta->indexOfSignal(QMetaObject::normalizedSignature(signal));
+ if (signalIndex == -1) {
+ qWarning("QSignalTransition: no such signal: %s::%s",
+ meta->className(), signal.constData());
+ return;
+ }
}
QVector<int> &connectedSignalIndexes = connections[sender];
if (connectedSignalIndexes.size() <= signalIndex)
diff --git a/src/gui/egl/egl.pri b/src/gui/egl/egl.pri
new file mode 100644
index 0000000..651507f
--- /dev/null
+++ b/src/gui/egl/egl.pri
@@ -0,0 +1,28 @@
+HEADERS += \
+ egl/qegl_p.h \
+ egl/qeglproperties_p.h
+
+SOURCES += \
+ egl/qegl.cpp \
+ egl/qeglproperties.cpp
+
+contains(QT_CONFIG, wince*): SOURCES += egl/qegl_wince.cpp
+
+unix {
+ embedded {
+ SOURCES += egl/qegl_qws.cpp
+ } else {
+ symbian {
+ SOURCES += egl/qegl_symbian.cpp
+ } else {
+ SOURCES += egl/qegl_x11.cpp
+ }
+ }
+}
+
+for(p, QMAKE_LIBDIR_EGL) {
+ exists($$p):LIBS += -L$$p
+}
+
+!isEmpty(QMAKE_INCDIR_EGL): INCLUDEPATH += $$QMAKE_INCDIR_EGL
+!isEmpty(QMAKE_LIBS_EGL): LIBS += $$QMAKE_LIBS_EGL
diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp
new file mode 100644
index 0000000..89d9d1b
--- /dev/null
+++ b/src/gui/egl/qegl.cpp
@@ -0,0 +1,403 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qpaintdevice.h>
+#include <QtGui/qpixmap.h>
+#include <QtGui/qwidget.h>
+#include <QtCore/qdebug.h>
+#include "qegl_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QEglContext::QEglContext()
+ : apiType(QEgl::OpenGL)
+ , dpy(EGL_NO_DISPLAY)
+ , ctx(EGL_NO_CONTEXT)
+ , surf(EGL_NO_SURFACE)
+ , cfg(0)
+ , share(false)
+ , current(false)
+ , reserved(0)
+{
+}
+
+QEglContext::~QEglContext()
+{
+ destroy();
+}
+
+bool QEglContext::isValid() const
+{
+ return (ctx != EGL_NO_CONTEXT);
+}
+
+bool QEglContext::isSharing() const
+{
+ return share;
+}
+
+bool QEglContext::isCurrent() const
+{
+ return current;
+}
+
+// Open the EGL display associated with "device".
+bool QEglContext::openDisplay(QPaintDevice *device)
+{
+ if (dpy == EGL_NO_DISPLAY)
+ dpy = defaultDisplay(device);
+ return (dpy != EGL_NO_DISPLAY);
+}
+
+// Choose a configuration that matches "properties".
+bool QEglContext::chooseConfig
+ (const QEglProperties& properties, QEgl::PixelFormatMatch match)
+{
+ QEglProperties props(properties);
+ do {
+ // Get the number of matching configurations for this set of properties.
+ EGLint matching = 0;
+ if (!eglChooseConfig(dpy, props.properties(), 0, 256, &matching) || !matching)
+ continue;
+
+ // If we want the best pixel format, then return the first
+ // matching configuration.
+ if (match == QEgl::BestPixelFormat) {
+ eglChooseConfig(dpy, props.properties(), &cfg, 1, &matching);
+ if (matching < 1)
+ continue;
+ return true;
+ }
+
+ // Fetch all of the matching configurations and find the
+ // first that matches the pixel format we wanted.
+ EGLint size = matching;
+ EGLConfig *configs = new EGLConfig [size];
+ eglChooseConfig(dpy, props.properties(), configs, size, &matching);
+ for (EGLint index = 0; index < size; ++index) {
+ EGLint red, green, blue, alpha;
+ eglGetConfigAttrib(dpy, configs[index], EGL_RED_SIZE, &red);
+ eglGetConfigAttrib(dpy, configs[index], EGL_GREEN_SIZE, &green);
+ eglGetConfigAttrib(dpy, configs[index], EGL_BLUE_SIZE, &blue);
+ eglGetConfigAttrib(dpy, configs[index], EGL_ALPHA_SIZE, &alpha);
+ if (red == props.value(EGL_RED_SIZE) &&
+ green == props.value(EGL_GREEN_SIZE) &&
+ blue == props.value(EGL_BLUE_SIZE) &&
+ (props.value(EGL_ALPHA_SIZE) == 0 ||
+ alpha == props.value(EGL_ALPHA_SIZE))) {
+ cfg = configs[index];
+ delete [] configs;
+ return true;
+ }
+ }
+ delete [] configs;
+ } while (props.reduceConfiguration());
+
+#ifdef EGL_BIND_TO_TEXTURE_RGBA
+ // Don't report an error just yet if we failed to get a pbuffer
+ // configuration with texture rendering. Only report failure if
+ // we cannot get any pbuffer configurations at all.
+ if (props.value(EGL_BIND_TO_TEXTURE_RGBA) == EGL_DONT_CARE &&
+ props.value(EGL_BIND_TO_TEXTURE_RGB) == EGL_DONT_CARE)
+#endif
+ {
+ qWarning() << "QEglContext::chooseConfig(): Could not find a suitable EGL configuration";
+ qWarning() << "Requested:" << props.toString();
+ qWarning() << "Available:";
+ dumpAllConfigs();
+ }
+ return false;
+}
+
+// Create the EGLContext.
+bool QEglContext::createContext(QEglContext *shareContext)
+{
+ // We need to select the correct API before calling eglCreateContext().
+#ifdef EGL_OPENGL_ES_API
+ if (apiType == QEgl::OpenGL)
+ eglBindAPI(EGL_OPENGL_ES_API);
+#endif
+#ifdef EGL_OPENVG_API
+ if (apiType == QEgl::OpenVG)
+ eglBindAPI(EGL_OPENVG_API);
+#endif
+
+ // Create a new context for the configuration.
+ QEglProperties contextProps;
+#if defined(QT_OPENGL_ES_2)
+ if (apiType == QEgl::OpenGL)
+ contextProps.setValue(EGL_CONTEXT_CLIENT_VERSION, 2);
+#endif
+ if (shareContext && shareContext->ctx == EGL_NO_CONTEXT)
+ shareContext = 0;
+ if (shareContext) {
+ ctx = eglCreateContext(dpy, cfg, shareContext->ctx, contextProps.properties());
+ if (ctx == EGL_NO_CONTEXT) {
+ qWarning() << "QEglContext::createContext(): Could not share context:" << errorString(eglGetError());
+ shareContext = 0;
+ }
+ }
+ if (ctx == EGL_NO_CONTEXT) {
+ ctx = eglCreateContext(dpy, cfg, 0, contextProps.properties());
+ if (ctx == EGL_NO_CONTEXT) {
+ qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << errorString(eglGetError());
+ return false;
+ }
+ }
+ share = (shareContext != 0);
+ return true;
+}
+
+// Recreate the surface for a paint device because the native id has changed.
+bool QEglContext::recreateSurface(QPaintDevice *device)
+{
+ // Bail out if the surface has not been created for the first time yet.
+ if (surf == EGL_NO_SURFACE)
+ return true;
+
+ // Destroy the old surface.
+ eglDestroySurface(dpy, surf);
+ surf = EGL_NO_SURFACE;
+
+ // Create a new one.
+ return createSurface(device);
+}
+
+// Destroy the EGL surface object.
+void QEglContext::destroySurface()
+{
+ if (surf != EGL_NO_SURFACE) {
+ eglDestroySurface(dpy, surf);
+ surf = EGL_NO_SURFACE;
+ }
+}
+
+// Destroy the context. Note: this does not destroy the surface.
+void QEglContext::destroy()
+{
+ if (ctx != EGL_NO_CONTEXT)
+ eglDestroyContext(dpy, ctx);
+ dpy = EGL_NO_DISPLAY;
+ ctx = EGL_NO_CONTEXT;
+ surf = EGL_NO_SURFACE;
+ cfg = 0;
+ share = false;
+}
+
+bool QEglContext::makeCurrent()
+{
+ if (ctx == EGL_NO_CONTEXT) {
+ qWarning() << "QEglContext::makeCurrent(): Cannot make invalid context current";
+ return false;
+ }
+
+ current = true;
+
+ bool ok = eglMakeCurrent(dpy, surf, surf, ctx);
+ if (!ok)
+ qWarning() << "QEglContext::makeCurrent():" << errorString(eglGetError());
+ return ok;
+}
+
+bool QEglContext::doneCurrent()
+{
+ // If the context is invalid, we assume that an error was reported
+ // when makeCurrent() was called.
+ if (ctx == EGL_NO_CONTEXT)
+ return false;
+
+ current = false;
+
+ // We need to select the correct API before calling eglMakeCurrent()
+ // with EGL_NO_CONTEXT because threads can have both OpenGL and OpenVG
+ // contexts active at the same time.
+#ifdef EGL_OPENGL_ES_API
+ if (apiType == QEgl::OpenGL)
+ eglBindAPI(EGL_OPENGL_ES_API);
+#endif
+#ifdef EGL_OPENVG_API
+ if (apiType == QEgl::OpenVG)
+ eglBindAPI(EGL_OPENVG_API);
+#endif
+
+ bool ok = eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ if (!ok)
+ qWarning() << "QEglContext::doneCurrent():" << errorString(eglGetError());
+ return ok;
+}
+
+bool QEglContext::swapBuffers()
+{
+ if(ctx == EGL_NO_CONTEXT)
+ return false;
+
+ bool ok = eglSwapBuffers(dpy, surf);
+ if (!ok)
+ qWarning() << "QEglContext::swapBuffers():" << errorString(eglGetError());
+ return ok;
+}
+
+// Wait for native rendering operations to complete before starting
+// to use OpenGL/OpenVG operations.
+void QEglContext::waitNative()
+{
+#ifdef EGL_CORE_NATIVE_ENGINE
+ eglWaitNative(EGL_CORE_NATIVE_ENGINE);
+#endif
+}
+
+// Wait for client OpenGL/OpenVG operations to complete before
+// using native rendering operations.
+void QEglContext::waitClient()
+{
+#ifdef EGL_OPENGL_ES_API
+ if (apiType == QEgl::OpenGL) {
+ eglBindAPI(EGL_OPENGL_ES_API);
+ eglWaitClient();
+ }
+#else
+ if (apiType == QEgl::OpenGL)
+ eglWaitGL();
+#endif
+#ifdef EGL_OPENVG_API
+ if (apiType == QEgl::OpenVG) {
+ eglBindAPI(EGL_OPENVG_API);
+ eglWaitClient();
+ }
+#endif
+}
+
+// Query the actual size of the EGL surface.
+QSize QEglContext::surfaceSize() const
+{
+ int w, h;
+ eglQuerySurface(dpy, surf, EGL_WIDTH, &w);
+ eglQuerySurface(dpy, surf, EGL_HEIGHT, &h);
+ return QSize(w, h);
+}
+
+// Query the value of a configuration attribute.
+bool QEglContext::configAttrib(int name, EGLint *value) const
+{
+ return eglGetConfigAttrib(dpy, cfg, name, value);
+}
+
+// Retrieve all of the properties on "cfg". If zero, return
+// the context's configuration.
+QEglProperties QEglContext::configProperties(EGLConfig cfg) const
+{
+ if (!cfg)
+ cfg = config();
+ QEglProperties props;
+ for (int name = 0x3020; name <= 0x304F; ++name) {
+ EGLint value;
+ if (name != EGL_NONE && eglGetConfigAttrib(dpy, cfg, name, &value))
+ props.setValue(name, value);
+ }
+ eglGetError(); // Clear the error state.
+ return props;
+}
+
+// Initialize and return the default display.
+EGLDisplay QEglContext::defaultDisplay(QPaintDevice *device)
+{
+ static EGLDisplay dpy = EGL_NO_DISPLAY;
+ if (dpy == EGL_NO_DISPLAY) {
+ dpy = getDisplay(device);
+ if (dpy == EGL_NO_DISPLAY) {
+ qWarning() << "QEglContext::defaultDisplay(): Cannot open EGL display";
+ return EGL_NO_DISPLAY;
+ }
+ if (!eglInitialize(dpy, NULL, NULL)) {
+ qWarning() << "QEglContext::defaultDisplay(): Cannot initialize EGL display:" << errorString(eglGetError());
+ return EGL_NO_DISPLAY;
+ }
+#ifdef EGL_OPENGL_ES_API
+ eglBindAPI(EGL_OPENGL_ES_API);
+#endif
+ }
+ return dpy;
+}
+
+// Return the error string associated with a specific code.
+QString QEglContext::errorString(EGLint code)
+{
+ static const char * const errors[] = {
+ "Success (0x3000)", // No tr
+ "Not initialized (0x3001)", // No tr
+ "Bad access (0x3002)", // No tr
+ "Bad alloc (0x3003)", // No tr
+ "Bad attribute (0x3004)", // No tr
+ "Bad config (0x3005)", // No tr
+ "Bad context (0x3006)", // No tr
+ "Bad current surface (0x3007)", // No tr
+ "Bad display (0x3008)", // No tr
+ "Bad match (0x3009)", // No tr
+ "Bad native pixmap (0x300A)", // No tr
+ "Bad native window (0x300B)", // No tr
+ "Bad parameter (0x300C)", // No tr
+ "Bad surface (0x300D)", // No tr
+ "Context lost (0x300E)" // No tr
+ };
+ if (code >= 0x3000 && code <= 0x300E) {
+ return QString::fromLatin1(errors[code - 0x3000]);
+ } else {
+ return QLatin1String("0x") + QString::number(int(code), 16);
+ }
+}
+
+// Dump all of the EGL configurations supported by the system.
+void QEglContext::dumpAllConfigs()
+{
+ QEglProperties props;
+ EGLint count = 0;
+ if (!eglGetConfigs(dpy, 0, 0, &count) || count < 1)
+ return;
+ EGLConfig *configs = new EGLConfig [count];
+ eglGetConfigs(dpy, configs, count, &count);
+ for (EGLint index = 0; index < count; ++index) {
+ props = configProperties(configs[index]);
+ qWarning() << props.toString();
+ }
+ delete [] configs;
+}
+
+QT_END_NAMESPACE
diff --git a/src/opengl/qegl_p.h b/src/gui/egl/qegl_p.h
index 4e46965..89949e2 100644
--- a/src/opengl/qegl_p.h
+++ b/src/gui/egl/qegl_p.h
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
**
-** This file is part of the QtOpenGL module of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
@@ -46,25 +46,20 @@
// W A R N I N G
// -------------
//
-// This file is not part of the Qt API. It exists for the convenience
-// of the QGLWidget class. This header file may change from
+// This file is not part of the Qt API. It exists for the convenience of
+// the QGLWidget and QVGWidget classes. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
-#include "QtCore/qvarlengtharray.h"
-#include "QtCore/qsize.h"
-#include "QtGui/qimage.h"
+#include <QtCore/qsize.h>
+#include <QtGui/qimage.h>
-#if defined(QT_OPENGL_ES) || defined(QT_OPENVG)
+#include "qeglproperties_p.h"
QT_BEGIN_INCLUDE_NAMESPACE
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENVG)
-#include <EGL/egl.h>
-#else
-#include <GLES/egl.h>
-#endif
+
#if !defined(EGL_VERSION_1_3) && !defined(QEGL_NATIVE_TYPES_DEFINED)
#undef EGLNativeWindowType
#undef EGLNativePixmapType
@@ -76,69 +71,27 @@ typedef NativeDisplayType EGLNativeDisplayType;
#endif
QT_END_INCLUDE_NAMESPACE
-class QX11Info;
-class QPaintDevice;
-class QImage;
-class QPixmap;
-class QWidget;
-
QT_BEGIN_NAMESPACE
-class Q_OPENGL_EXPORT QEglProperties
-{
-public:
- QEglProperties();
- QEglProperties(const QEglProperties& other) : props(other.props) {}
- ~QEglProperties() {}
-
- int value(int name) const;
- void setValue(int name, int value);
- bool removeValue(int name);
-
- const int *properties() const { return props.constData(); }
-
- void setPixelFormat(QImage::Format pixelFormat);
-#ifdef Q_WS_X11
- void setVisualFormat(const QX11Info *xinfo);
-#endif
- void setRenderableType(int api);
-
- bool reduceConfiguration();
-
- QString toString() const;
-
-private:
- QVarLengthArray<int> props;
-};
-
-class Q_OPENGL_EXPORT QEglContext
+class Q_GUI_EXPORT QEglContext
{
public:
QEglContext();
~QEglContext();
- enum API
- {
- OpenGL,
- OpenVG
- };
-
- enum PixelFormatMatch
- {
- ExactPixelFormat,
- BestPixelFormat
- };
-
bool isValid() const;
bool isSharing() const;
+ bool isCurrent() const;
+
+ QEgl::API api() const { return apiType; }
+ void setApi(QEgl::API api) { apiType = api; }
- void setApi(QEglContext::API api) { apiType = api; }
bool openDisplay(QPaintDevice *device);
- bool chooseConfig(const QEglProperties& properties, PixelFormatMatch match = ExactPixelFormat);
+ bool chooseConfig(const QEglProperties& properties, QEgl::PixelFormatMatch match = QEgl::ExactPixelFormat);
bool createContext(QEglContext *shareContext = 0);
- bool createSurface(QPaintDevice *device);
+ bool createSurface(QPaintDevice *device, const QEglProperties *properties = 0);
bool recreateSurface(QPaintDevice *device);
- void setSurface(EGLSurface surface) { surf = surface; }
+ void destroySurface();
void destroy();
@@ -153,29 +106,30 @@ public:
bool configAttrib(int name, EGLint *value) const;
- void clearError() const { eglGetError(); }
-
- QEglContext::API api() const { return apiType; }
+ static void clearError() { eglGetError(); }
+ static EGLint error() { return eglGetError(); }
+ static QString errorString(EGLint code);
EGLDisplay display() const { return dpy; }
EGLContext context() const { return ctx; }
EGLSurface surface() const { return surf; }
+ void setSurface(EGLSurface surface) { surf = surface; }
EGLConfig config() const { return cfg; }
QEglProperties configProperties(EGLConfig cfg = 0) const;
static EGLDisplay defaultDisplay(QPaintDevice *device);
- static QString errorString(int code);
void dumpAllConfigs();
private:
- QEglContext::API apiType;
+ QEgl::API apiType;
EGLDisplay dpy;
EGLContext ctx;
EGLSurface surf;
EGLConfig cfg;
bool share;
+ bool current;
void *reserved; // For extension data in future versions.
static EGLDisplay getDisplay(QPaintDevice *device);
@@ -183,6 +137,4 @@ private:
QT_END_NAMESPACE
-#endif // QT_OPENGL_ES || QT_OPENVG
-
#endif // QEGL_P_H
diff --git a/src/gui/egl/qegl_qws.cpp b/src/gui/egl/qegl_qws.cpp
new file mode 100644
index 0000000..69eaf1b
--- /dev/null
+++ b/src/gui/egl/qegl_qws.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qpaintdevice.h>
+#include <QtGui/qpixmap.h>
+#include <QtGui/qwidget.h>
+#include "qegl_p.h"
+
+#if !defined(QT_NO_EGL)
+
+#include <qscreen_qws.h>
+#include <qscreenproxy_qws.h>
+#include <qapplication.h>
+#include <qdesktopwidget.h>
+
+QT_BEGIN_NAMESPACE
+
+// Create the surface for a QPixmap, QImage, or QWidget.
+// We don't have QGLScreen to create EGL surfaces for us,
+// so surface creation needs to be done in QtOpenGL or
+// QtOpenVG for Qt/Embedded.
+bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties)
+{
+ Q_UNUSED(device);
+ Q_UNUSED(properties);
+ return false;
+}
+
+EGLDisplay QEglContext::getDisplay(QPaintDevice *device)
+{
+ Q_UNUSED(device);
+ return eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY));
+}
+
+static QScreen *screenForDevice(QPaintDevice *device)
+{
+ QScreen *screen = qt_screen;
+ if (!screen)
+ return 0;
+ if (screen->classId() == QScreen::MultiClass) {
+ int screenNumber;
+ if (device && device->devType() == QInternal::Widget)
+ screenNumber = qApp->desktop()->screenNumber(static_cast<QWidget *>(device));
+ else
+ screenNumber = 0;
+ screen = screen->subScreens()[screenNumber];
+ }
+ while (screen->classId() == QScreen::ProxyClass) {
+ screen = static_cast<QProxyScreen *>(screen)->screen();
+ }
+ return screen;
+}
+
+// Set pixel format and other properties based on a paint device.
+void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev)
+{
+ if (!dev)
+ return;
+
+ // Find the QGLScreen for this paint device.
+ QScreen *screen = screenForDevice(dev);
+ if (!screen)
+ return;
+ int devType = dev->devType();
+ if (devType == QInternal::Image)
+ setPixelFormat(static_cast<QImage *>(dev)->format());
+ else
+ setPixelFormat(screen->pixelFormat());
+}
+
+QT_END_NAMESPACE
+
+#endif // !QT_NO_EGL
diff --git a/src/opengl/qegl_qws.cpp b/src/gui/egl/qegl_symbian.cpp
index 89bee09..16a72a1 100644
--- a/src/opengl/qegl_qws.cpp
+++ b/src/gui/egl/qegl_symbian.cpp
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
**
-** This file is part of the QtOpenGL module of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
@@ -44,58 +44,26 @@
#include <QtGui/qwidget.h>
#include "qegl_p.h"
-#if defined(QT_OPENGL_ES) || defined(QT_OPENVG)
-
-#include <qglscreen_qws.h>
-#include <qscreenproxy_qws.h>
-#include <private/qglwindowsurface_qws_p.h>
-#include <qapplication.h>
-#include <qdesktopwidget.h>
+#include <coecntrl.h>
QT_BEGIN_NAMESPACE
-static QGLScreen *glScreenForDevice(QPaintDevice *device)
+bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties)
{
- QScreen *screen = qt_screen;
- if (screen->classId() == QScreen::MultiClass) {
- int screenNumber;
- if (device && device->devType() == QInternal::Widget)
- screenNumber = qApp->desktop()->screenNumber(static_cast<QWidget *>(device));
- else
- screenNumber = 0;
- screen = screen->subScreens()[screenNumber];
- }
- while (screen->classId() == QScreen::ProxyClass) {
- screen = static_cast<QProxyScreen *>(screen)->screen();
- }
- if (screen->classId() == QScreen::GLClass)
- return static_cast<QGLScreen *>(screen);
- else
- return 0;
-}
-
-// Create the surface for a QPixmap, QImage, or QWidget.
-bool QEglContext::createSurface(QPaintDevice *device)
-{
- // Get the screen surface functions, which are used to create native ids.
- QGLScreen *glScreen = glScreenForDevice(device);
- if (!glScreen)
- return false;
- QGLScreenSurfaceFunctions *funcs = glScreen->surfaceFunctions();
- if (!funcs)
- return false;
-
// Create the native drawable for the paint device.
int devType = device->devType();
EGLNativePixmapType pixmapDrawable = 0;
EGLNativeWindowType windowDrawable = 0;
bool ok;
if (devType == QInternal::Pixmap) {
- ok = funcs->createNativePixmap(static_cast<QPixmap *>(device), &pixmapDrawable);
- } else if (devType == QInternal::Image) {
- ok = funcs->createNativeImage(static_cast<QImage *>(device), &pixmapDrawable);
+ pixmapDrawable = 0;
+ ok = (pixmapDrawable != 0);
+ } else if (devType == QInternal::Widget) {
+ QWidget *w = static_cast<QWidget *>(device);
+ windowDrawable = (EGLNativeWindowType)(w->winId()->DrawableWindow());
+ ok = (windowDrawable != 0);
} else {
- ok = funcs->createNativeWindow(static_cast<QWidget *>(device), &windowDrawable);
+ ok = false;
}
if (!ok) {
qWarning("QEglContext::createSurface(): Cannot create the native EGL drawable");
@@ -103,6 +71,11 @@ bool QEglContext::createSurface(QPaintDevice *device)
}
// Create the EGL surface to draw into, based on the native drawable.
+ const int *props;
+ if (properties)
+ props = properties->properties();
+ else
+ props = 0;
if (devType == QInternal::Widget)
surf = eglCreateWindowSurface(dpy, cfg, windowDrawable, 0);
else
@@ -116,10 +89,21 @@ bool QEglContext::createSurface(QPaintDevice *device)
EGLDisplay QEglContext::getDisplay(QPaintDevice *device)
{
- Q_UNUSED(device);
- return eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY));
+ EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (dpy == EGL_NO_DISPLAY)
+ qWarning("QEglContext::defaultDisplay(): Falling back to EGL_DEFAULT_DISPLAY");
+ return dpy;
}
-QT_END_NAMESPACE
+// Set pixel format and other properties based on a paint device.
+void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev)
+{
+ int devType = dev->devType();
+ if (devType == QInternal::Image)
+ setPixelFormat(static_cast<QImage *>(dev)->format());
+ else
+ setPixelFormat(QImage::Format_RGB32);
+}
-#endif // QT_OPENGL_ES || QT_OPENVG
+
+QT_END_NAMESPACE
diff --git a/src/opengl/qegl_wince.cpp b/src/gui/egl/qegl_wince.cpp
index b978bc6..7bcbcf8 100644
--- a/src/opengl/qegl_wince.cpp
+++ b/src/gui/egl/qegl_wince.cpp
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
**
-** This file is part of the QtOpenGL module of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
@@ -44,14 +44,12 @@
#include <QtGui/qwidget.h>
#include "qegl_p.h"
-#if defined(QT_OPENGL_ES) || defined(QT_OPENVG)
-
#include <windows.h>
QT_BEGIN_NAMESPACE
-bool QEglContext::createSurface(QPaintDevice *device)
+bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties)
{
// Create the native drawable for the paint device.
int devType = device->devType();
@@ -73,10 +71,15 @@ bool QEglContext::createSurface(QPaintDevice *device)
}
// Create the EGL surface to draw into, based on the native drawable.
+ const int *props;
+ if (properties)
+ props = properties->properties();
+ else
+ props = 0;
if (devType == QInternal::Widget)
- surf = eglCreateWindowSurface(dpy, cfg, windowDrawable, 0);
+ surf = eglCreateWindowSurface(dpy, cfg, windowDrawable, props);
else
- surf = eglCreatePixmapSurface(dpy, cfg, pixmapDrawable, 0);
+ surf = eglCreatePixmapSurface(dpy, cfg, pixmapDrawable, props);
if (surf == EGL_NO_SURFACE) {
qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError());
return false;
@@ -87,19 +90,27 @@ bool QEglContext::createSurface(QPaintDevice *device)
EGLDisplay QEglContext::getDisplay(QPaintDevice *device)
{
EGLDisplay dpy = 0;
- HWND win = ((QWidget*)device)->winId();
- HDC myDc = GetDC(win);
- if (!myDc) {
- qWarning("QEglContext::defaultDisplay(): WinCE display is not open");
- }
- dpy = eglGetDisplay(EGLNativeDisplayType(myDc));
- if (dpy == EGL_NO_DISPLAY) {
- qWarning("QEglContext::defaultDisplay(): Falling back to EGL_DEFAULT_DISPLAY");
- dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ HWND win = (static_cast<QWidget*>(device))->winId();
+ HDC myDc = GetDC(win);
+ if (!myDc) {
+ qWarning("QEglContext::defaultDisplay(): WinCE display is not open");
+ }
+ dpy = eglGetDisplay(EGLNativeDisplayType(myDc));
+ if (dpy == EGL_NO_DISPLAY) {
+ qWarning("QEglContext::defaultDisplay(): Falling back to EGL_DEFAULT_DISPLAY");
+ dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
}
return dpy;
}
-QT_END_NAMESPACE
+// Set pixel format and other properties based on a paint device.
+void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev)
+{
+ int devType = dev->devType();
+ if (devType == QInternal::Image)
+ setPixelFormat(static_cast<QImage *>(dev)->format());
+ else
+ setPixelFormat(QImage::Format_RGB16); // XXX
+}
-#endif // QT_OPENGL_ES || QT_OPENVG
+QT_END_NAMESPACE
diff --git a/src/opengl/qegl_x11egl.cpp b/src/gui/egl/qegl_x11.cpp
index 23d1ac6..be89efe 100644
--- a/src/opengl/qegl_x11egl.cpp
+++ b/src/gui/egl/qegl_x11.cpp
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
**
-** This file is part of the QtOpenGL module of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
@@ -45,17 +45,13 @@
#include <QtCore/qdebug.h>
#include "qegl_p.h"
-#if defined(QT_OPENGL_ES) || defined(QT_OPENVG)
-
-#if defined(Q_WS_X11)
#include <QtGui/qx11info_x11.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
-#endif
QT_BEGIN_NAMESPACE
-bool QEglContext::createSurface(QPaintDevice *device)
+bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties)
{
// Create the native drawable for the paint device.
int devType = device->devType();
@@ -77,11 +73,15 @@ bool QEglContext::createSurface(QPaintDevice *device)
}
// Create the EGL surface to draw into, based on the native drawable.
+ const int *props;
+ if (properties)
+ props = properties->properties();
+ else
+ props = 0;
if (devType == QInternal::Widget)
- surf = eglCreateWindowSurface(dpy, cfg, windowDrawable, 0);
+ surf = eglCreateWindowSurface(dpy, cfg, windowDrawable, props);
else
- surf = eglCreatePixmapSurface(dpy, cfg, pixmapDrawable, 0);
-
+ surf = eglCreatePixmapSurface(dpy, cfg, pixmapDrawable, props);
if (surf == EGL_NO_SURFACE) {
qWarning() << "QEglContext::createSurface(): Unable to create EGL surface:"
<< errorString(eglGetError());
@@ -128,6 +128,17 @@ void QEglProperties::setVisualFormat(const QX11Info *xinfo)
setValue(EGL_ALPHA_SIZE, 0); // XXX
}
-QT_END_NAMESPACE
+extern const QX11Info *qt_x11Info(const QPaintDevice *pd);
+
+// Set pixel format and other properties based on a paint device.
+void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev)
+{
+ if (!dev)
+ return;
+ if (dev->devType() == QInternal::Image)
+ setPixelFormat(static_cast<QImage *>(dev)->format());
+ else
+ setVisualFormat(qt_x11Info(dev));
+}
-#endif // QT_OPENGL_ES || QT_OPENVG
+QT_END_NAMESPACE
diff --git a/src/opengl/qegl.cpp b/src/gui/egl/qeglproperties.cpp
index 61c7427..e0ae8a6 100644
--- a/src/opengl/qegl.cpp
+++ b/src/gui/egl/qeglproperties.cpp
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
**
-** This file is part of the QtOpenGL module of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
@@ -39,358 +39,12 @@
**
****************************************************************************/
-#include <QtGui/qpaintdevice.h>
-#include <QtGui/qpixmap.h>
-#include <QtGui/qwidget.h>
-#include <QtCore/qdebug.h>
-#include "qegl_p.h"
-
-#if defined(QT_OPENGL_ES) || defined(QT_OPENVG)
+#include "qeglproperties_p.h"
QT_BEGIN_NAMESPACE
-QEglContext::QEglContext()
-{
- apiType = OpenGL;
- dpy = EGL_NO_DISPLAY;
- ctx = EGL_NO_CONTEXT;
- surf = EGL_NO_SURFACE;
- cfg = 0;
- share = false;
- reserved = 0;
-}
-
-QEglContext::~QEglContext()
-{
- destroy();
-}
-
-bool QEglContext::isValid() const
-{
- return (ctx != EGL_NO_CONTEXT);
-}
-
-bool QEglContext::isSharing() const
-{
- return share;
-}
-
-// Open the EGL display associated with "device".
-bool QEglContext::openDisplay(QPaintDevice *device)
-{
- if (dpy == EGL_NO_DISPLAY)
- dpy = defaultDisplay(device);
- return (dpy != EGL_NO_DISPLAY);
-}
-
-// Choose a configuration that matches "properties".
-bool QEglContext::chooseConfig
- (const QEglProperties& properties, PixelFormatMatch match)
-{
- QEglProperties props(properties);
- EGLConfig *configs;
- EGLint matching, size;
- do {
- // Get the number of matching configurations for this set of properties.
- matching = 0;
- if (!eglChooseConfig(dpy, props.properties(), 0, 256, &matching) || !matching)
- continue;
-
- // If we want the best pixel format, then return the first
- // matching configuration.
- if (match == BestPixelFormat) {
- eglChooseConfig(dpy, props.properties(), &cfg, 1, &matching);
- if (matching < 1)
- continue;
- return true;
- }
-
- // Fetch all of the matching configurations and find the
- // first that matches the pixel format we wanted.
- size = matching;
- configs = new EGLConfig [size];
- eglChooseConfig(dpy, props.properties(), configs, size, &matching);
- for (EGLint index = 0; index < size; ++index) {
- EGLint red, green, blue, alpha;
- eglGetConfigAttrib(dpy, configs[index], EGL_RED_SIZE, &red);
- eglGetConfigAttrib(dpy, configs[index], EGL_GREEN_SIZE, &green);
- eglGetConfigAttrib(dpy, configs[index], EGL_BLUE_SIZE, &blue);
- eglGetConfigAttrib(dpy, configs[index], EGL_ALPHA_SIZE, &alpha);
- if (red == props.value(EGL_RED_SIZE) &&
- green == props.value(EGL_GREEN_SIZE) &&
- blue == props.value(EGL_BLUE_SIZE) &&
- (props.value(EGL_ALPHA_SIZE) == 0 ||
- alpha == props.value(EGL_ALPHA_SIZE))) {
- cfg = configs[index];
- delete [] configs;
- return true;
- }
- }
- delete [] configs;
- } while (props.reduceConfiguration());
-
-#ifdef EGL_BIND_TO_TEXTURE_RGBA
- // Don't report an error just yet if we failed to get a pbuffer
- // configuration with texture rendering. Only report failure if
- // we cannot get any pbuffer configurations at all.
- if (props.value(EGL_BIND_TO_TEXTURE_RGBA) == EGL_DONT_CARE &&
- props.value(EGL_BIND_TO_TEXTURE_RGB) == EGL_DONT_CARE)
-#endif
- {
- qWarning() << "QEglContext::chooseConfig(): Could not find a suitable EGL configuration";
- qWarning() << "Requested:" << props.toString();
- qWarning() << "Available:";
- dumpAllConfigs();
- }
- return false;
-}
-
-// Create the EGLContext.
-bool QEglContext::createContext(QEglContext *shareContext)
-{
- // We need to select the correct API before calling eglCreateContext().
-#ifdef EGL_OPENGL_ES_API
- if (apiType == OpenGL)
- eglBindAPI(EGL_OPENGL_ES_API);
-#endif
-#ifdef EGL_OPENVG_API
- if (apiType == OpenVG)
- eglBindAPI(EGL_OPENVG_API);
-#endif
-
- // Create a new context for the configuration.
- QEglProperties contextProps;
-#if defined(QT_OPENGL_ES_2)
- if (apiType == OpenGL)
- contextProps.setValue(EGL_CONTEXT_CLIENT_VERSION, 2);
-#endif
- if (shareContext && shareContext->ctx == EGL_NO_CONTEXT)
- shareContext = 0;
- if (shareContext) {
- ctx = eglCreateContext(dpy, cfg, shareContext->ctx, contextProps.properties());
- if (ctx == EGL_NO_CONTEXT) {
- qWarning() << "QEglContext::createContext(): Could not share context:" << errorString(eglGetError());
- shareContext = 0;
- }
- }
- if (ctx == EGL_NO_CONTEXT) {
- ctx = eglCreateContext(dpy, cfg, 0, contextProps.properties());
- if (ctx == EGL_NO_CONTEXT) {
- qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << errorString(eglGetError());
- return false;
- }
- }
- share = (shareContext != 0);
- return true;
-}
-
-// Recreate the surface for a paint device because the native id has changed.
-bool QEglContext::recreateSurface(QPaintDevice *device)
-{
- // Bail out if the surface has not been created for the first time yet.
- if (surf == EGL_NO_SURFACE)
- return true;
-
- // Destroy the old surface.
- eglDestroySurface(dpy, surf);
-
- // Create a new one.
- return createSurface(device);
-}
-
-void QEglContext::destroy()
-{
- if (ctx != EGL_NO_CONTEXT)
- eglDestroyContext(dpy, ctx);
- dpy = EGL_NO_DISPLAY;
- ctx = EGL_NO_CONTEXT;
- surf = EGL_NO_SURFACE;
- cfg = 0;
- share = false;
-}
-
-bool QEglContext::makeCurrent()
-{
- if(ctx == EGL_NO_CONTEXT) {
- qWarning() << "QEglContext::makeCurrent(): Cannot make invalid context current";
- return false;
- }
-
- bool ok = eglMakeCurrent(dpy, surf, surf, ctx);
- if (!ok) {
- EGLint err = eglGetError();
- qWarning() << "QEglContext::makeCurrent():" << errorString(err);
- }
- return ok;
-}
-
-bool QEglContext::doneCurrent()
-{
- // If the context is invalid, we assume that an error was reported
- // when makeCurrent() was called.
- if (ctx == EGL_NO_CONTEXT)
- return false;
-
- // We need to select the correct API before calling eglMakeCurrent()
- // with EGL_NO_CONTEXT because threads can have both OpenGL and OpenVG
- // contexts active at the same time.
-#ifdef EGL_OPENGL_ES_API
- if (apiType == OpenGL)
- eglBindAPI(EGL_OPENGL_ES_API);
-#endif
-#ifdef EGL_OPENVG_API
- if (apiType == OpenVG)
- eglBindAPI(EGL_OPENVG_API);
-#endif
-
- bool ok = eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- if (!ok) {
- EGLint err = eglGetError();
- qWarning() << "QEglContext::doneCurrent():" << errorString(err);
- }
- return ok;
-}
-
-bool QEglContext::swapBuffers()
-{
- if(ctx == EGL_NO_CONTEXT)
- return false;
-
- bool ok = eglSwapBuffers(dpy, surf);
- if (!ok) {
- EGLint err = eglGetError();
- qWarning() << "QEglContext::swapBuffers():" << errorString(err);
- }
- return ok;
-}
-
-// Wait for native rendering operations to complete before starting
-// to use OpenGL/OpenVG operations.
-void QEglContext::waitNative()
-{
-#ifdef EGL_CORE_NATIVE_ENGINE
- eglWaitNative(EGL_CORE_NATIVE_ENGINE);
-#endif
-}
-
-// Wait for client OpenGL/OpenVG operations to complete before
-// using native rendering operations.
-void QEglContext::waitClient()
-{
-#ifdef EGL_OPENGL_ES_API
- if (apiType == OpenGL) {
- eglBindAPI(EGL_OPENGL_ES_API);
- eglWaitClient();
- }
-#else
- if (apiType == OpenGL)
- eglWaitGL();
-#endif
-#ifdef EGL_OPENVG_API
- if (apiType == OpenVG) {
- eglBindAPI(EGL_OPENVG_API);
- eglWaitClient();
- }
-#endif
-}
-
-// Query the actual size of the EGL surface.
-QSize QEglContext::surfaceSize() const
-{
- int w, h;
- eglQuerySurface(dpy, surf, EGL_WIDTH, &w);
- eglQuerySurface(dpy, surf, EGL_HEIGHT, &h);
- return QSize(w, h);
-}
-
-// Query the value of a configuration attribute.
-bool QEglContext::configAttrib(int name, EGLint *value) const
-{
- return eglGetConfigAttrib(dpy, cfg, name, value);
-}
-
-// Retrieve all of the properties on "cfg". If zero, return
-// the context's configuration.
-QEglProperties QEglContext::configProperties(EGLConfig cfg) const
-{
- if (!cfg)
- cfg = config();
- QEglProperties props;
- for (int name = 0x3020; name <= 0x304F; ++name) {
- EGLint value;
- if (name != EGL_NONE && eglGetConfigAttrib(dpy, cfg, name, &value))
- props.setValue(name, value);
- }
- eglGetError(); // Clear the error state.
- return props;
-}
-
-// Initialize and return the default display.
-EGLDisplay QEglContext::defaultDisplay(QPaintDevice *device)
-{
- static EGLDisplay dpy = EGL_NO_DISPLAY;
- if (dpy == EGL_NO_DISPLAY) {
- dpy = getDisplay(device);
- if (dpy == EGL_NO_DISPLAY) {
- qWarning() << "QEglContext::defaultDisplay(): Cannot open EGL display";
- return EGL_NO_DISPLAY;
- }
- if (!eglInitialize(dpy, NULL, NULL)) {
- EGLint err = eglGetError();
- qWarning() << "QEglContext::defaultDisplay(): Cannot initialize EGL display:" << errorString(err);
- return EGL_NO_DISPLAY;
- }
-#ifdef EGL_OPENGL_ES_API
- eglBindAPI(EGL_OPENGL_ES_API);
-#endif
- }
- return dpy;
-}
-
-// Return the error string associated with a specific code.
-QString QEglContext::errorString(int code)
-{
- static const char * const errors[] = {
- "Success (0x3000)", // No tr
- "Not initialized (0x3001)", // No tr
- "Bad access (0x3002)", // No tr
- "Bad alloc (0x3003)", // No tr
- "Bad attribute (0x3004)", // No tr
- "Bad config (0x3005)", // No tr
- "Bad context (0x3006)", // No tr
- "Bad current surface (0x3007)", // No tr
- "Bad display (0x3008)", // No tr
- "Bad match (0x3009)", // No tr
- "Bad native pixmap (0x300A)", // No tr
- "Bad native window (0x300B)", // No tr
- "Bad parameter (0x300C)", // No tr
- "Bad surface (0x300D)", // No tr
- "Context lost (0x300E)" // No tr
- };
- if (code >= 0x3000 && code <= 0x300E) {
- return QString::fromLatin1(errors[code - 0x3000]);
- } else {
- return QLatin1String("0x") + QString::number(code, 16);
- }
-}
-
-// Dump all of the EGL configurations supported by the system.
-void QEglContext::dumpAllConfigs()
-{
- QEglProperties props;
- EGLint count = 0;
- if (!eglGetConfigs(dpy, 0, 0, &count))
- return;
- if (count < 1)
- return;
- EGLConfig *configs = new EGLConfig [count];
- eglGetConfigs(dpy, configs, count, &count);
- for (EGLint index = 0; index < count; ++index) {
- props = configProperties(configs[index]);
- qWarning() << props.toString();
- }
- delete [] configs;
-}
+#include <QtCore/qdebug.h>
+#include <QtCore/qstringlist.h>
// Initialize a property block.
QEglProperties::QEglProperties()
@@ -455,10 +109,10 @@ int QEglProperties::value(int name) const
case EGL_MAX_PBUFFER_PIXELS:
case EGL_NATIVE_VISUAL_ID:
case EGL_NONE:
- qWarning("QEglProperties::value() - Attibute %d does not affect config selection", name);
+ // Attribute does not affect config selection.
return EGL_DONT_CARE;
default:
- qWarning("QEglProperties::value() - Attibute %d is unknown in EGL <=1.4", name);
+ // Attribute is unknown in EGL <= 1.4.
return EGL_DONT_CARE;
}
}
@@ -532,18 +186,18 @@ void QEglProperties::setPixelFormat(QImage::Format pixelFormat)
setValue(EGL_ALPHA_SIZE, alpha);
}
-void QEglProperties::setRenderableType(int api)
+void QEglProperties::setRenderableType(QEgl::API api)
{
#if defined(EGL_RENDERABLE_TYPE)
#if defined(QT_OPENGL_ES_2)
- if (api == QEglContext::OpenGL)
+ if (api == QEgl::OpenGL)
setValue(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT);
#elif defined(QT_OPENGL_ES)
- if (api == QEglContext::OpenGL)
+ if (api == QEgl::OpenGL)
setValue(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT);
#endif
#if defined(EGL_OPENVG_BIT)
- if (api == QEglContext::OpenVG)
+ if (api == QEgl::OpenVG)
setValue(EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT);
#endif
#else
@@ -839,4 +493,4 @@ QString QEglProperties::toString() const
QT_END_NAMESPACE
-#endif // QT_OPENGL_ES || QT_OPENVG
+
diff --git a/src/gui/egl/qeglproperties_p.h b/src/gui/egl/qeglproperties_p.h
new file mode 100644
index 0000000..3570f80
--- /dev/null
+++ b/src/gui/egl/qeglproperties_p.h
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEGLPROPERTIES_P_H
+#define QEGLPROPERTIES_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the QGLWidget class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qvarlengtharray.h>
+#include <QtGui/qimage.h>
+
+QT_BEGIN_INCLUDE_NAMESPACE
+
+#if defined(QT_GLES_EGL)
+#include <GLES/egl.h>
+#else
+#include <EGL/egl.h>
+#endif
+
+#if defined(Q_WS_X11)
+// If <EGL/egl.h> included <X11/Xlib.h>, then the global namespace
+// may have been polluted with X #define's. The following makes sure
+// the X11 headers were included properly and then cleans things up.
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#undef Bool
+#undef Status
+#undef None
+#undef KeyPress
+#undef KeyRelease
+#undef FocusIn
+#undef FocusOut
+#undef Type
+#undef FontChange
+#undef CursorShape
+#endif
+
+QT_END_INCLUDE_NAMESPACE
+
+QT_BEGIN_NAMESPACE
+
+namespace QEgl {
+ enum API
+ {
+ OpenGL,
+ OpenVG
+ };
+
+ enum PixelFormatMatch
+ {
+ ExactPixelFormat,
+ BestPixelFormat
+ };
+};
+
+class QX11Info;
+class QPaintDevice;
+
+class Q_GUI_EXPORT QEglProperties
+{
+public:
+ QEglProperties();
+ QEglProperties(const QEglProperties& other) : props(other.props) {}
+ ~QEglProperties() {}
+
+ int value(int name) const;
+ void setValue(int name, int value);
+ bool removeValue(int name);
+ bool isEmpty() const { return props[0] == EGL_NONE; }
+
+ const int *properties() const { return props.constData(); }
+
+ void setPixelFormat(QImage::Format pixelFormat);
+#ifdef Q_WS_X11
+ void setVisualFormat(const QX11Info *xinfo);
+#endif
+ void setRenderableType(QEgl::API api);
+
+ void setPaintDeviceFormat(QPaintDevice *dev);
+
+ bool reduceConfiguration();
+
+ QString toString() const;
+
+private:
+ QVarLengthArray<int> props;
+};
+
+QT_END_NAMESPACE
+
+#endif // QEGLPROPERTIES_P_H
diff --git a/src/gui/gui.pro b/src/gui/gui.pro
index 329fb01..b77bfdc 100644
--- a/src/gui/gui.pro
+++ b/src/gui/gui.pro
@@ -35,6 +35,8 @@ include(util/util.pri)
include(statemachine/statemachine.pri)
include(math3d/math3d.pri)
+contains(QT_CONFIG, egl): include(egl/egl.pri)
+
embedded: QT += network
QMAKE_LIBS += $$QMAKE_LIBS_GUI
diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp
index 19c5928..298f76b 100644
--- a/src/gui/kernel/qapplication_x11.cpp
+++ b/src/gui/kernel/qapplication_x11.cpp
@@ -1091,10 +1091,8 @@ static void qt_set_input_encoding()
}
// Reads a KDE color setting
-static QColor kdeColor(const QString &key)
+static QColor kdeColor(const QString &key, const QSettings &kdeSettings)
{
- QSettings kdeSettings(QApplicationPrivate::kdeHome() +
- QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat);
QVariant variant = kdeSettings.value(key);
if (variant.isValid()) {
QStringList values = variant.toStringList();
@@ -1313,36 +1311,40 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0,
}
if (kdeColors) {
+ const QSettings &theKdeSettings =
+ QSettings(QApplicationPrivate::kdeHome()
+ + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat);
+
// Setup KDE palette
QColor color;
- color = kdeColor(QLatin1String("buttonBackground"));
+ color = kdeColor(QLatin1String("buttonBackground"), theKdeSettings);
if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:Button/BackgroundNormal"));
+ color = kdeColor(QLatin1String("Colors:Button/BackgroundNormal"), theKdeSettings);
if (color.isValid())
btn = color;
- color = kdeColor(QLatin1String("background"));
+ color = kdeColor(QLatin1String("background"), theKdeSettings);
if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:Window/BackgroundNormal"));
+ color = kdeColor(QLatin1String("Colors:Window/BackgroundNormal"), theKdeSettings);
if (color.isValid())
bg = color;
- color = kdeColor(QLatin1String("foreground"));
+ color = kdeColor(QLatin1String("foreground"), theKdeSettings);
if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:View/ForegroundNormal"));
+ color = kdeColor(QLatin1String("Colors:View/ForegroundNormal"), theKdeSettings);
if (color.isValid()) {
fg = color;
}
- color = kdeColor(QLatin1String("windowForeground"));
+ color = kdeColor(QLatin1String("windowForeground"), theKdeSettings);
if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:Window/ForegroundNormal"));
+ color = kdeColor(QLatin1String("Colors:Window/ForegroundNormal"), theKdeSettings);
if (color.isValid())
wfg = color;
- color = kdeColor(QLatin1String("windowBackground"));
+ color = kdeColor(QLatin1String("windowBackground"), theKdeSettings);
if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:View/BackgroundNormal"));
+ color = kdeColor(QLatin1String("Colors:View/BackgroundNormal"), theKdeSettings);
if (color.isValid())
base = color;
}
@@ -1361,29 +1363,33 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0,
}
// Use KDE3 or KDE4 color settings if present
if (kdeColors) {
- QColor color = kdeColor(QLatin1String("selectBackground"));
+ const QSettings &theKdeSettings =
+ QSettings(QApplicationPrivate::kdeHome()
+ + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat);
+
+ QColor color = kdeColor(QLatin1String("selectBackground"), theKdeSettings);
if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:Selection/BackgroundNormal"));
+ color = kdeColor(QLatin1String("Colors:Selection/BackgroundNormal"), theKdeSettings);
if (color.isValid())
highlight = color;
- color = kdeColor(QLatin1String("selectForeground"));
+ color = kdeColor(QLatin1String("selectForeground"), theKdeSettings);
if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:Selection/ForegroundNormal"));
+ color = kdeColor(QLatin1String("Colors:Selection/ForegroundNormal"), theKdeSettings);
if (color.isValid())
highlightText = color;
- color = kdeColor(QLatin1String("alternateBackground"));
+ color = kdeColor(QLatin1String("alternateBackground"), theKdeSettings);
if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:View/BackgroundAlternate"));
+ color = kdeColor(QLatin1String("Colors:View/BackgroundAlternate"), theKdeSettings);
if (color.isValid())
pal.setColor(QPalette::AlternateBase, color);
else
pal.setBrush(QPalette::AlternateBase, pal.base().color().darker(110));
- color = kdeColor(QLatin1String("buttonForeground"));
+ color = kdeColor(QLatin1String("buttonForeground"), theKdeSettings);
if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:Button/ForegroundNormal"));
+ color = kdeColor(QLatin1String("Colors:Button/ForegroundNormal"), theKdeSettings);
if (color.isValid())
pal.setColor(QPalette::ButtonText, color);
}
diff --git a/src/gui/widgets/qdockarealayout.cpp b/src/gui/widgets/qdockarealayout.cpp
index 135bcda..3125304 100644
--- a/src/gui/widgets/qdockarealayout.cpp
+++ b/src/gui/widgets/qdockarealayout.cpp
@@ -155,6 +155,11 @@ QSize QDockAreaLayoutItem::maximumSize() const
return QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
}
+bool QDockAreaLayoutItem::hasFixedSize(Qt::Orientation o) const
+{
+ return perp(o, minimumSize()) == perp(o, maximumSize());
+}
+
bool QDockAreaLayoutItem::expansive(Qt::Orientation o) const
{
if ((flags & GapItem) || placeHolderItem != 0)
@@ -216,7 +221,7 @@ static quintptr tabId(const QDockAreaLayoutItem &item)
#endif
QDockAreaLayoutInfo::QDockAreaLayoutInfo()
- : sep(0), dockPos(QInternal::LeftDock), o(Qt::Horizontal), rect(0, 0, -1, -1), mainWindow(0)
+ : sep(0), dockPos(QInternal::LeftDock), o(Qt::Horizontal), mainWindow(0)
#ifndef QT_NO_TABBAR
, tabbed(false), tabBar(0), tabBarShape(QTabBar::RoundedSouth)
#endif
@@ -226,7 +231,7 @@ QDockAreaLayoutInfo::QDockAreaLayoutInfo()
QDockAreaLayoutInfo::QDockAreaLayoutInfo(int _sep, QInternal::DockPosition _dockPos,
Qt::Orientation _o, int tbshape,
QMainWindow *window)
- : sep(_sep), dockPos(_dockPos), o(_o), rect(0, 0, -1, -1), mainWindow(window)
+ : sep(_sep), dockPos(_dockPos), o(_o), mainWindow(window)
#ifndef QT_NO_TABBAR
, tabbed(false), tabBar(0), tabBarShape(static_cast<QTabBar::Shape>(tbshape))
#endif
@@ -244,7 +249,7 @@ QSize QDockAreaLayoutInfo::size() const
void QDockAreaLayoutInfo::clear()
{
item_list.clear();
- rect = QRect(0, 0, -1, -1);
+ rect = QRect();
#ifndef QT_NO_TABBAR
tabbed = false;
tabBar = 0;
@@ -388,10 +393,9 @@ QSize QDockAreaLayoutInfo::sizeHint() const
return QSize(0, 0);
int a = 0, b = 0;
- bool prev_gap = false;
- bool first = true;
int min_perp = 0;
int max_perp = QWIDGETSIZE_MAX;
+ const QDockAreaLayoutItem *previous = 0;
for (int i = 0; i < item_list.size(); ++i) {
const QDockAreaLayoutItem &item = item_list.at(i);
if (item.skip())
@@ -409,14 +413,15 @@ QSize QDockAreaLayoutInfo::sizeHint() const
} else
#endif
{
- if (!first && !gap && !prev_gap)
+ if (previous && !gap && !(previous->flags & QDockAreaLayoutItem::GapItem)
+ && !previous->hasFixedSize(o)) {
a += sep;
+ }
a += gap ? item.size : pick(o, size_hint);
}
b = qMax(b, perp(o, size_hint));
- prev_gap = gap;
- first = false;
+ previous = &item;
}
max_perp = qMax(max_perp, min_perp);
@@ -539,21 +544,20 @@ void QDockAreaLayoutInfo::fitItems()
int max_size = realMaxSize(*this);
int last_index = -1;
- bool prev_gap = false;
- bool first = true;
+ const QDockAreaLayoutItem *previous = 0;
for (int i = 0; i < item_list.size(); ++i) {
QDockAreaLayoutItem &item = item_list[i];
if (item.skip())
continue;
bool gap = item.flags & QDockAreaLayoutItem::GapItem;
- if (!first && !gap && !prev_gap) {
- QLayoutStruct &ls = layout_struct_list[j++];
- ls.init();
- ls.minimumSize = sep;
- ls.maximumSize = sep;
- ls.sizeHint = sep;
- ls.empty = false;
+ if (previous && !gap) {
+ if (!(previous->flags & QDockAreaLayoutItem::GapItem)) {
+ QLayoutStruct &ls = layout_struct_list[j++];
+ ls.init();
+ ls.minimumSize = ls.maximumSize = ls.sizeHint = previous->hasFixedSize(o) ? 0 : sep;
+ ls.empty = false;
+ }
}
if (item.flags & QDockAreaLayoutItem::KeepSize) {
@@ -592,8 +596,7 @@ void QDockAreaLayoutInfo::fitItems()
}
item.flags &= ~QDockAreaLayoutItem::KeepSize;
- prev_gap = gap;
- first = false;
+ previous = &item;
}
layout_struct_list.resize(j);
@@ -607,8 +610,8 @@ void QDockAreaLayoutInfo::fitItems()
qGeomCalc(layout_struct_list, 0, j, pick(o, rect.topLeft()), size, 0);
j = 0;
- prev_gap = false;
- first = true;
+ bool prev_gap = false;
+ bool first = true;
for (int i = 0; i < item_list.size(); ++i) {
QDockAreaLayoutItem &item = item_list[i];
if (item.skip())
@@ -1408,11 +1411,12 @@ QList<int> QDockAreaLayoutInfo::findSeparator(const QPoint &_pos) const
if (next == -1 || (item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
continue;
- int margin = (sep == 1? 2 : 0);
- if (pos >= item.pos + item.size - margin && item.pos + item.size + sep + margin > pos) {
- QList<int> result;
- result.append(i);
- return result;
+ QRect sepRect = separatorRect(i);
+ if (!sepRect.isNull() && sep == 1)
+ sepRect.adjust(-2, -2, 2, 2);
+ //we also make sure we don't find a separator that's not there
+ if (sepRect.contains(_pos) && !item.hasFixedSize(o)) {
+ return QList<int>() << i;
}
}
@@ -1478,6 +1482,12 @@ QMainWindowLayout *QDockAreaLayoutInfo::mainWindowLayout() const
return result;
}
+bool QDockAreaLayoutInfo::hasFixedSize() const
+{
+ return perp(o, minimumSize()) == perp(o, maximumSize());
+}
+
+
void QDockAreaLayoutInfo::apply(bool animate)
{
QWidgetAnimator *widgetAnimator = mainWindowLayout()->widgetAnimator;
@@ -1629,7 +1639,7 @@ void QDockAreaLayoutInfo::paintSeparators(QPainter *p, QWidget *widget,
if (next == -1)
break;
QRect r = separatorRect(i);
- if (clip.contains(r))
+ if (clip.contains(r) && !item.hasFixedSize(o))
paintSep(p, widget, r, o, r.contains(mouse));
}
}
@@ -2009,10 +2019,8 @@ bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*>
void QDockAreaLayoutInfo::updateSeparatorWidgets() const
{
- QDockAreaLayoutInfo *that = const_cast<QDockAreaLayoutInfo*>(this);
-
if (tabbed) {
- that->separatorWidgets.clear();
+ separatorWidgets.clear();
return;
}
@@ -2040,7 +2048,7 @@ void QDockAreaLayoutInfo::updateSeparatorWidgets() const
sepWidget = separatorWidgets.at(j);
} else {
sepWidget = mainWindowLayout()->getSeparatorWidget();
- that->separatorWidgets.append(sepWidget);
+ separatorWidgets.append(sepWidget);
}
j++;
@@ -2053,10 +2061,10 @@ void QDockAreaLayoutInfo::updateSeparatorWidgets() const
sepWidget->show();
}
- for (int k = j; k < that->separatorWidgets.size(); ++k) {
- that->separatorWidgets[k]->hide();
+ for (int k = j; k < separatorWidgets.size(); ++k) {
+ separatorWidgets[k]->hide();
}
- that->separatorWidgets.resize(j);
+ separatorWidgets.resize(j);
Q_ASSERT(separatorWidgets.size() == j);
}
@@ -2271,7 +2279,7 @@ QDockAreaLayout::QDockAreaLayout(QMainWindow *win)
docks[QInternal::BottomDock]
= QDockAreaLayoutInfo(sep, QInternal::BottomDock, Qt::Horizontal, tabShape, win);
centralWidgetItem = 0;
- centralWidgetRect = QRect(0, 0, -1, -1);
+
corners[Qt::TopLeftCorner] = Qt::TopDockWidgetArea;
corners[Qt::TopRightCorner] = Qt::TopDockWidgetArea;
@@ -2442,9 +2450,9 @@ QList<int> QDockAreaLayout::findSeparator(const QPoint &pos) const
if (info.isEmpty())
continue;
QRect rect = separatorRect(i);
- if (sep == 1)
+ if (!rect.isNull() && sep == 1)
rect.adjust(-2, -2, 2, 2);
- if (rect.contains(pos)) {
+ if (rect.contains(pos) && !info.hasFixedSize()) {
result << i;
break;
} else if (info.rect.contains(pos)) {
@@ -2504,9 +2512,10 @@ QRect QDockAreaLayout::itemRect(QList<int> path) const
QRect QDockAreaLayout::separatorRect(int index) const
{
- if (docks[index].isEmpty())
+ const QDockAreaLayoutInfo &dock = docks[index];
+ if (dock.isEmpty())
return QRect();
- QRect r = docks[index].rect;
+ QRect r = dock.rect;
switch (index) {
case QInternal::LeftDock:
return QRect(r.right() + 1, r.top(), sep, r.height());
@@ -2854,8 +2863,8 @@ void QDockAreaLayout::clear()
for (int i = 0; i < QInternal::DockCount; ++i)
docks[i].clear();
- rect = QRect(0, 0, -1, -1);
- centralWidgetRect = QRect(0, 0, -1, -1);
+ rect = QRect();
+ centralWidgetRect = QRect();
}
QSize QDockAreaLayout::sizeHint() const
@@ -3080,7 +3089,7 @@ void QDockAreaLayout::paintSeparators(QPainter *p, QWidget *widget,
if (dock.isEmpty())
continue;
QRect r = separatorRect(i);
- if (clip.contains(r)) {
+ if (clip.contains(r) && !dock.hasFixedSize()) {
Qt::Orientation opposite = dock.o == Qt::Horizontal
? Qt::Vertical : Qt::Horizontal;
paintSep(p, widget, r, opposite, r.contains(mouse));
@@ -3154,8 +3163,6 @@ int QDockAreaLayout::separatorMove(QList<int> separator, const QPoint &origin,
// Allocates new sepearator widgets with getSeparatorWidget
void QDockAreaLayout::updateSeparatorWidgets() const
{
- QDockAreaLayout *that = const_cast<QDockAreaLayout*>(this);
-
int j = 0;
for (int i = 0; i < QInternal::DockCount; ++i) {
@@ -3168,7 +3175,7 @@ void QDockAreaLayout::updateSeparatorWidgets() const
sepWidget = separatorWidgets.at(j);
} else {
sepWidget = qobject_cast<QMainWindowLayout*>(mainWindow->layout())->getSeparatorWidget();
- that->separatorWidgets.append(sepWidget);
+ separatorWidgets.append(sepWidget);
}
j++;
@@ -3183,7 +3190,7 @@ void QDockAreaLayout::updateSeparatorWidgets() const
for (int i = j; i < separatorWidgets.size(); ++i)
separatorWidgets.at(i)->hide();
- that->separatorWidgets.resize(j);
+ separatorWidgets.resize(j);
}
QLayoutItem *QDockAreaLayout::itemAt(int *x, int index) const
diff --git a/src/gui/widgets/qdockarealayout_p.h b/src/gui/widgets/qdockarealayout_p.h
index 0b8d832..137aeba 100644
--- a/src/gui/widgets/qdockarealayout_p.h
+++ b/src/gui/widgets/qdockarealayout_p.h
@@ -103,6 +103,7 @@ struct QDockAreaLayoutItem
QSize maximumSize() const;
QSize sizeHint() const;
bool expansive(Qt::Orientation o) const;
+ bool hasFixedSize(Qt::Orientation o) const;
QLayoutItem *widgetItem;
QDockAreaLayoutInfo *subinfo;
@@ -167,6 +168,7 @@ public:
void clear();
bool isEmpty() const;
+ bool hasFixedSize() const;
QList<int> findSeparator(const QPoint &pos) const;
int next(int idx) const;
int prev(int idx) const;
@@ -188,7 +190,7 @@ public:
QMainWindowLayout *mainWindowLayout() const;
int sep;
- QVector<QWidget*> separatorWidgets;
+ mutable QVector<QWidget*> separatorWidgets;
QInternal::DockPosition dockPos;
Qt::Orientation o;
QRect rect;
@@ -231,7 +233,7 @@ public:
QDockAreaLayout(QMainWindow *win);
QDockAreaLayoutInfo docks[4];
int sep; // separator extent
- QVector<QWidget*> separatorWidgets;
+ mutable QVector<QWidget*> separatorWidgets;
bool isValid() const;
diff --git a/src/gui/widgets/qmainwindowlayout.cpp b/src/gui/widgets/qmainwindowlayout.cpp
index 308f956..10e07d3 100644
--- a/src/gui/widgets/qmainwindowlayout.cpp
+++ b/src/gui/widgets/qmainwindowlayout.cpp
@@ -490,10 +490,10 @@ void QMainWindowLayoutState::clear()
#ifndef QT_NO_DOCKWIDGET
dockAreaLayout.clear();
#else
- centralWidgetRect = QRect(0, 0, -1, -1);
+ centralWidgetRect = QRect();
#endif
- rect = QRect(0, 0, -1, -1);
+ rect = QRect();
}
bool QMainWindowLayoutState::isValid() const
diff --git a/src/gui/widgets/qtoolbararealayout.cpp b/src/gui/widgets/qtoolbararealayout.cpp
index aaab885..8a10355 100644
--- a/src/gui/widgets/qtoolbararealayout.cpp
+++ b/src/gui/widgets/qtoolbararealayout.cpp
@@ -567,7 +567,7 @@ bool QToolBarAreaLayoutInfo::insertGap(QList<int> path, QLayoutItem *item)
void QToolBarAreaLayoutInfo::clear()
{
lines.clear();
- rect = QRect(0, 0, -1, -1);
+ rect = QRect();
}
QRect QToolBarAreaLayoutInfo::itemRect(QList<int> path) const
@@ -1101,7 +1101,7 @@ void QToolBarAreaLayout::clear()
{
for (int i = 0; i < QInternal::DockCount; ++i)
docks[i].clear();
- rect = QRect(0, 0, -1, -1);
+ rect = QRect();
}
QToolBarAreaLayoutItem &QToolBarAreaLayout::item(QList<int> path)
diff --git a/src/network/access/qnetworkdiskcache.cpp b/src/network/access/qnetworkdiskcache.cpp
index 5df6b0f..50aaa6a 100644
--- a/src/network/access/qnetworkdiskcache.cpp
+++ b/src/network/access/qnetworkdiskcache.cpp
@@ -81,6 +81,20 @@ QT_BEGIN_NAMESPACE
use on the system to 50MB.
Note you have to set the cache directory before it will work.
+
+ A network disk cache can be enabled by:
+
+ \snippet doc/src/snippets/code/src_network_access_qnetworkdiskcache.cpp 0
+
+ When sending requests, to control the preference of when to use the cache
+ and when to use the network, consider the following:
+
+ \snippet doc/src/snippets/code/src_network_access_qnetworkdiskcache.cpp 1
+
+ To check whether the response came from the cache or from the network, the
+ following can be applied:
+
+ \snippet doc/src/snippets/code/src_network_access_qnetworkdiskcache.cpp 2
*/
/*!
diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro
index 73af174..c92b8cf 100644
--- a/src/opengl/opengl.pro
+++ b/src/opengl/opengl.pro
@@ -62,12 +62,9 @@ x11 {
contains(QT_CONFIG, opengles1)|contains(QT_CONFIG, opengles1cl)|contains(QT_CONFIG, opengles2) {
SOURCES += qgl_x11egl.cpp \
qglpixelbuffer_egl.cpp \
- qgl_egl.cpp \
- qegl.cpp \
- qegl_x11egl.cpp
+ qgl_egl.cpp
- HEADERS += qegl_p.h \
- qgl_egl_p.h
+ HEADERS += qgl_egl_p.h
} else {
SOURCES += qgl_x11.cpp \
@@ -93,13 +90,10 @@ win32:!wince*: {
wince*: {
SOURCES += qgl_wince.cpp \
qglpixelbuffer_egl.cpp \
- qgl_egl.cpp \
- qegl.cpp \
- qegl_wince.cpp
+ qgl_egl.cpp
HEADERS += qgl_cl_p.h \
qgl_egl_p.h \
- qegl_p.h
}
embedded {
@@ -108,15 +102,12 @@ embedded {
qglpixelbuffer_egl.cpp \
qglscreen_qws.cpp \
qglwindowsurface_qws.cpp \
- qegl.cpp \
- qegl_qws.cpp \
qgl_egl.cpp
HEADERS += qglpaintdevice_qws_p.h \
qglscreen_qws.h \
qglwindowsurface_qws_p.h \
- qgl_egl_p.h \
- qegl_p.h
+ qgl_egl_p.h
contains(QT_CONFIG, fontconfig) {
include($$QT_SOURCE_TREE/config.tests/unix/freetype/freetype.pri)
diff --git a/src/opengl/qgl_egl_p.h b/src/opengl/qgl_egl_p.h
index 2fb2e8f..d54036d 100644
--- a/src/opengl/qgl_egl_p.h
+++ b/src/opengl/qgl_egl_p.h
@@ -53,7 +53,7 @@
// We mean it.
//
-#include "qegl_p.h"
+#include <QtGui/private/qegl_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/opengl/qgl_qws.cpp b/src/opengl/qgl_qws.cpp
index 3b6ad63..a71a734 100644
--- a/src/opengl/qgl_qws.cpp
+++ b/src/opengl/qgl_qws.cpp
@@ -116,6 +116,57 @@ void qt_egl_add_platform_config(QEglProperties& props, QPaintDevice *device)
props.setPixelFormat(glScreen->pixelFormat());
}
+static bool qt_egl_create_surface
+ (QEglContext *context, QPaintDevice *device,
+ const QEglProperties *properties = 0)
+{
+ // Get the screen surface functions, which are used to create native ids.
+ QGLScreen *glScreen = glScreenForDevice(device);
+ if (!glScreen)
+ return false;
+ QGLScreenSurfaceFunctions *funcs = glScreen->surfaceFunctions();
+ if (!funcs)
+ return false;
+
+ // Create the native drawable for the paint device.
+ int devType = device->devType();
+ EGLNativePixmapType pixmapDrawable = 0;
+ EGLNativeWindowType windowDrawable = 0;
+ bool ok;
+ if (devType == QInternal::Pixmap) {
+ ok = funcs->createNativePixmap(static_cast<QPixmap *>(device), &pixmapDrawable);
+ } else if (devType == QInternal::Image) {
+ ok = funcs->createNativeImage(static_cast<QImage *>(device), &pixmapDrawable);
+ } else {
+ ok = funcs->createNativeWindow(static_cast<QWidget *>(device), &windowDrawable);
+ }
+ if (!ok) {
+ qWarning("QEglContext::createSurface(): Cannot create the native EGL drawable");
+ return false;
+ }
+
+ // Create the EGL surface to draw into, based on the native drawable.
+ const int *props;
+ if (properties)
+ props = properties->properties();
+ else
+ props = 0;
+ EGLSurface surf;
+ if (devType == QInternal::Widget) {
+ surf = eglCreateWindowSurface
+ (context->display(), context->config(), windowDrawable, props);
+ } else {
+ surf = eglCreatePixmapSurface
+ (context->display(), context->config(), pixmapDrawable, props);
+ }
+ if (surf == EGL_NO_SURFACE) {
+ qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError());
+ return false;
+ }
+ context->setSurface(surf);
+ return true;
+}
+
bool QGLContext::chooseContext(const QGLContext* shareContext)
{
Q_D(QGLContext);
@@ -131,7 +182,7 @@ bool QGLContext::chooseContext(const QGLContext* shareContext)
// Get the display and initialize it.
d->eglContext = new QEglContext();
- d->eglContext->setApi(QEglContext::OpenGL);
+ d->eglContext->setApi(QEgl::OpenGL);
if (!d->eglContext->openDisplay(device())) {
delete d->eglContext;
d->eglContext = 0;
@@ -142,7 +193,7 @@ bool QGLContext::chooseContext(const QGLContext* shareContext)
QEglProperties configProps;
qt_egl_add_platform_config(configProps, device());
qt_egl_set_format(configProps, devType, d->glFormat);
- configProps.setRenderableType(QEglContext::OpenGL);
+ configProps.setRenderableType(QEgl::OpenGL);
// Search for a matching configuration, reducing the complexity
// each time until we get something that matches.
@@ -168,8 +219,10 @@ bool QGLContext::chooseContext(const QGLContext* shareContext)
eglSwapInterval(d->eglContext->display(), d->glFormat.swapInterval());
#endif
- // Create the EGL surface to draw into.
- if (!d->eglContext->createSurface(device())) {
+ // Create the EGL surface to draw into. We cannot use
+ // QEglContext::createSurface() because it does not have
+ // access to the QGLScreen.
+ if (!qt_egl_create_surface(d->eglContext, device())) {
delete d->eglContext;
d->eglContext = 0;
return false;
diff --git a/src/opengl/qgl_wince.cpp b/src/opengl/qgl_wince.cpp
index 47dc2d4..afe26ab 100644
--- a/src/opengl/qgl_wince.cpp
+++ b/src/opengl/qgl_wince.cpp
@@ -140,7 +140,7 @@ bool QGLContext::chooseContext(const QGLContext* shareContext)
// Get the display and initialize it.
d->eglContext = new QEglContext();
- d->eglContext->setApi(QEglContext::OpenGL);
+ d->eglContext->setApi(QEgl::OpenGL);
if (!d->eglContext->openDisplay(device())) {
delete d->eglContext;
d->eglContext = 0;
@@ -151,7 +151,7 @@ bool QGLContext::chooseContext(const QGLContext* shareContext)
QEglProperties configProps;
qt_egl_add_platform_config(configProps, device());
qt_egl_set_format(configProps, devType, d->glFormat);
- configProps.setRenderableType(QEglContext::OpenGL);
+ configProps.setRenderableType(QEgl::OpenGL);
// Search for a matching configuration, reducing the complexity
// each time until we get something that matches.
diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp
index 7fdbfbd..9db3a30 100644
--- a/src/opengl/qgl_x11egl.cpp
+++ b/src/opengl/qgl_x11egl.cpp
@@ -77,7 +77,7 @@ bool QGLContext::chooseContext(const QGLContext* shareContext)
// Get the display and initialize it.
d->eglContext = new QEglContext();
- d->eglContext->setApi(QEglContext::OpenGL);
+ d->eglContext->setApi(QEgl::OpenGL);
if (!d->eglContext->openDisplay(device())) {
delete d->eglContext;
d->eglContext = 0;
@@ -88,11 +88,11 @@ bool QGLContext::chooseContext(const QGLContext* shareContext)
QEglProperties configProps;
qt_egl_set_format(configProps, devType, d->glFormat);
qt_egl_add_platform_config(configProps, device());
- configProps.setRenderableType(QEglContext::OpenGL);
+ configProps.setRenderableType(QEgl::OpenGL);
// Search for a matching configuration, reducing the complexity
// each time until we get something that matches.
- if (!d->eglContext->chooseConfig(configProps, QEglContext::BestPixelFormat)) {
+ if (!d->eglContext->chooseConfig(configProps, QEgl::BestPixelFormat)) {
delete d->eglContext;
d->eglContext = 0;
return false;
diff --git a/src/opengl/qglpixelbuffer_egl.cpp b/src/opengl/qglpixelbuffer_egl.cpp
index fca1a31..38e4f74 100644
--- a/src/opengl/qglpixelbuffer_egl.cpp
+++ b/src/opengl/qglpixelbuffer_egl.cpp
@@ -63,7 +63,7 @@ bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidge
{
// Create the EGL context.
ctx = new QEglContext();
- ctx->setApi(QEglContext::OpenGL);
+ ctx->setApi(QEgl::OpenGL);
// Open the EGL display.
if (!ctx->openDisplay(0)) {
@@ -82,13 +82,13 @@ bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidge
#if QGL_RENDER_TEXTURE
textureFormat = EGL_TEXTURE_RGBA;
configProps.setValue(EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE);
- ok = ctx->chooseConfig(configProps, QEglContext::BestPixelFormat);
+ ok = ctx->chooseConfig(configProps, QEgl::BestPixelFormat);
if (!ok) {
// Try again with RGB texture rendering.
textureFormat = EGL_TEXTURE_RGB;
configProps.removeValue(EGL_BIND_TO_TEXTURE_RGBA);
configProps.setValue(EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE);
- ok = ctx->chooseConfig(configProps, QEglContext::BestPixelFormat);
+ ok = ctx->chooseConfig(configProps, QEgl::BestPixelFormat);
if (!ok) {
// One last try for a pbuffer with no texture rendering.
configProps.removeValue(EGL_BIND_TO_TEXTURE_RGB);
@@ -99,7 +99,7 @@ bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidge
textureFormat = EGL_NONE;
#endif
if (!ok) {
- if (!ctx->chooseConfig(configProps, QEglContext::BestPixelFormat)) {
+ if (!ctx->chooseConfig(configProps, QEgl::BestPixelFormat)) {
delete ctx;
ctx = 0;
return false;
@@ -208,7 +208,7 @@ bool QGLPixelBuffer::hasOpenGLPbuffers()
return false;
QEglProperties configProps;
qt_egl_set_format(configProps, QInternal::Pbuffer, QGLFormat::defaultFormat());
- configProps.setRenderableType(QEglContext::OpenGL);
+ configProps.setRenderableType(QEgl::OpenGL);
return ctx.chooseConfig(configProps);
}
diff --git a/src/openvg/openvg.pro b/src/openvg/openvg.pro
new file mode 100644
index 0000000..4d499ef
--- /dev/null
+++ b/src/openvg/openvg.pro
@@ -0,0 +1,48 @@
+TARGET = QtOpenVG
+QT += core \
+ gui
+
+DEFINES+=QT_BUILD_OPENVG_LIB
+
+contains(QT_CONFIG, shivavg) {
+ DEFINES += QVG_NO_DRAW_GLYPHS
+ DEFINES += QVG_NO_RENDER_TO_MASK
+ DEFINES += QVG_SCISSOR_CLIP
+}
+
+HEADERS += \
+ qvg.h \
+ qvg_p.h \
+ qpaintengine_vg_p.h \
+ qpixmapdata_vg_p.h \
+ qpixmapfilter_vg_p.h \
+ qvgcompositionhelper_p.h
+SOURCES += \
+ qpaintengine_vg.cpp \
+ qpixmapdata_vg.cpp \
+ qpixmapfilter_vg.cpp
+
+contains(QT_CONFIG, egl) {
+ HEADERS += \
+ qwindowsurface_vgegl_p.h \
+ qwindowsurface_vg_p.h
+ SOURCES += \
+ qwindowsurface_vg.cpp \
+ qwindowsurface_vgegl.cpp
+}
+
+include(../qbase.pri)
+
+unix:QMAKE_PKGCONFIG_REQUIRES = QtCore QtGui
+
+!isEmpty(QMAKE_INCDIR_OPENVG): INCLUDEPATH += $$QMAKE_INCDIR_OPENVG
+!isEmpty(QMAKE_LIBDIR_OPENVG): LIBS += -L$$QMAKE_LIBDIR_OPENVG
+!isEmpty(QMAKE_LIBS_OPENVG): LIBS += $$QMAKE_LIBS_OPENVG
+
+contains(QT_CONFIG, egl) {
+ !isEmpty(QMAKE_INCDIR_EGL): INCLUDEPATH += $$QMAKE_INCDIR_EGL
+ !isEmpty(QMAKE_LIBDIR_EGL): LIBS += -L$$QMAKE_LIBDIR_EGL
+ !isEmpty(QMAKE_LIBS_EGL): LIBS += $$QMAKE_LIBS_EGL
+}
+
+INCLUDEPATH += ../3rdparty/harfbuzz/src
diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp
new file mode 100644
index 0000000..37945bf
--- /dev/null
+++ b/src/openvg/qpaintengine_vg.cpp
@@ -0,0 +1,3231 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qpaintengine_vg_p.h"
+#include "qpixmapdata_vg_p.h"
+#include "qpixmapfilter_vg_p.h"
+#include "qvgcompositionhelper_p.h"
+#if !defined(QT_NO_EGL)
+#include <QtGui/private/qegl_p.h>
+#include "qwindowsurface_vgegl_p.h"
+#endif
+#include <QtCore/qvarlengtharray.h>
+#include <QtGui/private/qdrawhelper_p.h>
+#include <QtGui/private/qtextureglyphcache_p.h>
+#include <QtGui/private/qtextengine_p.h>
+#include <QtGui/private/qfontengine_p.h>
+#include <QDebug>
+#include <QSet>
+
+QT_BEGIN_NAMESPACE
+
+// vgDrawGlyphs() only exists in OpenVG 1.1 and higher.
+#if !defined(OPENVG_VERSION_1_1) && !defined(QVG_NO_DRAW_GLYPHS)
+#define QVG_NO_DRAW_GLYPHS 1
+#endif
+
+// vgRenderToMask() only exists in OpenVG 1.1 and higher.
+// Also, disable masking completely if we are using the scissor to clip.
+#if !defined(OPENVG_VERSION_1_1) && !defined(QVG_NO_RENDER_TO_MASK)
+#define QVG_NO_RENDER_TO_MASK 1
+#endif
+#if defined(QVG_SCISSOR_CLIP) && !defined(QVG_NO_RENDER_TO_MASK)
+#define QVG_NO_RENDER_TO_MASK 1
+#endif
+
+#if !defined(QVG_NO_DRAW_GLYPHS)
+
+extern int qt_defaultDpiX();
+extern int qt_defaultDpiY();
+
+class QVGPaintEnginePrivate;
+
+class QVGFontGlyphCache
+{
+public:
+ QVGFontGlyphCache();
+ ~QVGFontGlyphCache();
+
+ void cacheGlyphs(QVGPaintEnginePrivate *d,
+ const QTextItemInt &ti,
+ const QVarLengthArray<glyph_t> &glyphs);
+ void setScaleFromText(const QTextItemInt &ti);
+
+ VGFont font;
+ VGfloat scaleX;
+ VGfloat scaleY;
+
+ uint cachedGlyphsMask[256 / 32];
+ QSet<glyph_t> cachedGlyphs;
+};
+
+typedef QHash<QFontEngine*, QVGFontGlyphCache*> QVGFontCache;
+
+#endif
+
+class QVGFontEngineCleaner : public QObject
+{
+ Q_OBJECT
+public:
+ QVGFontEngineCleaner(QVGPaintEnginePrivate *d);
+ ~QVGFontEngineCleaner();
+
+public slots:
+ void fontEngineDestroyed();
+
+private:
+ QVGPaintEnginePrivate *d_ptr;
+};
+
+class QVGPaintEnginePrivate : public QPaintEngineExPrivate
+{
+public:
+ QVGPaintEnginePrivate();
+ ~QVGPaintEnginePrivate();
+
+ void init();
+ void initObjects();
+ void destroy();
+ void setTransform(VGMatrixMode mode, const QTransform& transform);
+ void updateTransform(QPaintDevice *pdev);
+ void draw(VGPath path, const QPen& pen, const QBrush& brush, VGint rule = VG_EVEN_ODD);
+ void stroke(VGPath path, const QPen& pen);
+ void fill(VGPath path, const QBrush& brush, VGint rule = VG_EVEN_ODD);
+ VGPath vectorPathToVGPath(const QVectorPath& path);
+ VGPath painterPathToVGPath(const QPainterPath& path);
+ VGPaintType setBrush
+ (VGPaint paint, const QBrush& brush, VGMatrixMode mode,
+ VGPaintType prevPaintType);
+ void setPenParams(const QPen& pen);
+ void setBrushTransform(const QBrush& brush, VGMatrixMode mode);
+ void setupColorRamp(const QGradient *grad, VGPaint paint);
+ void setImageOptions();
+#if !defined(QVG_SCISSOR_CLIP)
+ void ensureMask(QVGPaintEngine *engine, int width, int height);
+ void modifyMask
+ (QVGPaintEngine *engine, VGMaskOperation op, const QRegion& region);
+#endif
+
+ VGint maxScissorRects; // Maximum scissor rectangles for clipping.
+
+ VGPaint penPaint; // Paint for currently active pen.
+ VGPaint brushPaint; // Paint for currently active brush.
+ VGPaint opacityPaint; // Paint for drawing images with opacity.
+ VGPaint fillPaint; // Current fill paint that is active.
+
+ QPen currentPen; // Current pen set in "penPaint".
+ QBrush currentBrush; // Current brush set in "brushPaint".
+
+ bool forcePenChange; // Force a pen change, even if the same.
+ bool forceBrushChange; // Force a brush change, even if the same.
+
+ VGPaintType penType; // Type of the last pen that was set.
+ VGPaintType brushType; // Type of the last brush that was set.
+
+ QPointF brushOrigin; // Current brush origin.
+
+ VGint fillRule; // Last fill rule that was set.
+
+ qreal opacity; // Current drawing opacity.
+ qreal paintOpacity; // Opacity in opacityPaint.
+
+#if !defined(QVG_NO_MODIFY_PATH)
+ VGPath rectPath; // Cached path for quick drawing of rectangles.
+ VGPath linePath; // Cached path for quick drawing of lines.
+#endif
+
+ QTransform transform; // Currently active transform.
+ bool simpleTransform; // True if the transform is simple (non-projective).
+ qreal penScale; // Pen scaling factor from "transform".
+
+ QTransform pathTransform; // Calculated VG path transformation.
+ QTransform imageTransform; // Calculated VG image transformation.
+ bool pathTransformSet; // True if path transform set in the VG context.
+
+ bool maskValid; // True if vgMask() contains valid data.
+ bool maskIsSet; // True if mask would be fully set if it was valid.
+ bool rawVG; // True if processing a raw VG escape.
+
+ QRect maskRect; // Rectangle version of mask if it is simple.
+
+ QTransform penTransform; // Transform for the pen.
+ QTransform brushTransform; // Transform for the brush.
+
+ VGMatrixMode matrixMode; // Last matrix mode that was set.
+ VGImageMode imageMode; // Last image mode that was set.
+
+ QRegion scissorRegion; // Currently active scissor region.
+ bool scissorActive; // True if scissor region is active.
+
+ QPaintEngine::DirtyFlags dirty;
+
+ QColor clearColor; // Last clear color that was set.
+ VGfloat clearOpacity; // Opacity during the last clear.
+
+ VGBlendMode blendMode; // Active blend mode.
+ VGRenderingQuality renderingQuality; // Active rendering quality.
+ VGImageQuality imageQuality; // Active image quality.
+
+#if !defined(QVG_NO_DRAW_GLYPHS)
+ QVGFontCache fontCache;
+ QVGFontEngineCleaner *fontEngineCleaner;
+#endif
+
+ // Ensure that the path transform is properly set in the VG context
+ // before we perform a vgDrawPath() operation.
+ inline void ensurePathTransform()
+ {
+ if (!pathTransformSet) {
+ setTransform(VG_MATRIX_PATH_USER_TO_SURFACE, pathTransform);
+ pathTransformSet = true;
+ }
+ }
+
+ // Ensure that a specific pen has been set into penPaint.
+ inline void ensurePen(const QPen& pen) {
+ if (forcePenChange || pen != currentPen) {
+ currentPen = pen;
+ forcePenChange = false;
+ penType = setBrush
+ (penPaint, pen.brush(),
+ VG_MATRIX_STROKE_PAINT_TO_USER, penType);
+ setPenParams(pen);
+ }
+ }
+
+ // Ensure that a specific brush has been set into brushPaint.
+ inline void ensureBrush(const QBrush& brush) {
+ if (forceBrushChange || brush != currentBrush) {
+ currentBrush = brush;
+ forceBrushChange = false;
+ brushType = setBrush
+ (brushPaint, brush, VG_MATRIX_FILL_PAINT_TO_USER, brushType);
+ }
+ if (fillPaint != brushPaint) {
+ vgSetPaint(brushPaint, VG_FILL_PATH);
+ fillPaint = brushPaint;
+ }
+ }
+
+ // Set various modes, but only if different.
+ inline void setImageMode(VGImageMode mode);
+ inline void setRenderingQuality(VGRenderingQuality mode);
+ inline void setImageQuality(VGImageQuality mode);
+ inline void setBlendMode(VGBlendMode mode);
+ inline void setFillRule(VGint mode);
+
+ // Clear all lazily-set modes.
+ void clearModes();
+};
+
+inline void QVGPaintEnginePrivate::setImageMode(VGImageMode mode)
+{
+ if (imageMode != mode) {
+ imageMode = mode;
+ vgSeti(VG_IMAGE_MODE, mode);
+ }
+}
+
+inline void QVGPaintEnginePrivate::setRenderingQuality(VGRenderingQuality mode)
+{
+ if (renderingQuality != mode) {
+ vgSeti(VG_RENDERING_QUALITY, mode);
+ renderingQuality = mode;
+ }
+}
+
+inline void QVGPaintEnginePrivate::setImageQuality(VGImageQuality mode)
+{
+ if (imageQuality != mode) {
+ vgSeti(VG_IMAGE_QUALITY, mode);
+ imageQuality = mode;
+ }
+}
+
+inline void QVGPaintEnginePrivate::setBlendMode(VGBlendMode mode)
+{
+ if (blendMode != mode) {
+ vgSeti(VG_BLEND_MODE, mode);
+ blendMode = mode;
+ }
+}
+
+inline void QVGPaintEnginePrivate::setFillRule(VGint mode)
+{
+ if (fillRule != mode) {
+ fillRule = mode;
+ vgSeti(VG_FILL_RULE, mode);
+ }
+}
+
+void QVGPaintEnginePrivate::clearModes()
+{
+ matrixMode = (VGMatrixMode)0;
+ imageMode = (VGImageMode)0;
+ blendMode = (VGBlendMode)0;
+ renderingQuality = (VGRenderingQuality)0;
+ imageQuality = (VGImageQuality)0;
+}
+
+QVGPaintEnginePrivate::QVGPaintEnginePrivate()
+{
+ init();
+}
+
+void QVGPaintEnginePrivate::init()
+{
+ maxScissorRects = 0;
+
+ penPaint = 0;
+ brushPaint = 0;
+ opacityPaint = 0;
+ fillPaint = 0;
+
+ forcePenChange = true;
+ forceBrushChange = true;
+ penType = (VGPaintType)0;
+ brushType = (VGPaintType)0;
+
+ brushOrigin = QPointF(0.0f, 0.0f);
+
+ fillRule = 0;
+
+ opacity = 1.0;
+ paintOpacity = 1.0f;
+
+#if !defined(QVG_NO_MODIFY_PATH)
+ rectPath = 0;
+ linePath = 0;
+#endif
+
+ simpleTransform = true;
+ pathTransformSet = false;
+ penScale = 1.0;
+
+ maskValid = false;
+ maskIsSet = false;
+ rawVG = false;
+
+ scissorActive = false;
+
+ dirty = 0;
+
+ clearOpacity = 1.0f;
+
+#if !defined(QVG_NO_DRAW_GLYPHS)
+ fontEngineCleaner = 0;
+#endif
+
+ clearModes();
+}
+
+QVGPaintEnginePrivate::~QVGPaintEnginePrivate()
+{
+ destroy();
+}
+
+void QVGPaintEnginePrivate::initObjects()
+{
+ maxScissorRects = vgGeti(VG_MAX_SCISSOR_RECTS);
+
+ penPaint = vgCreatePaint();
+ vgSetParameteri(penPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
+ vgSetPaint(penPaint, VG_STROKE_PATH);
+
+ vgSeti(VG_MATRIX_MODE, VG_MATRIX_STROKE_PAINT_TO_USER);
+ vgLoadIdentity();
+
+ brushPaint = vgCreatePaint();
+ vgSetParameteri(brushPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
+ vgSetPaint(brushPaint, VG_FILL_PATH);
+ fillPaint = brushPaint;
+
+ vgSeti(VG_MATRIX_MODE, VG_MATRIX_FILL_PAINT_TO_USER);
+ vgLoadIdentity();
+ matrixMode = VG_MATRIX_FILL_PAINT_TO_USER;
+
+ opacityPaint = vgCreatePaint();
+ vgSetParameteri(opacityPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
+ VGfloat values[4];
+ values[0] = 1.0f;
+ values[1] = 1.0f;
+ values[2] = 1.0f;
+ values[3] = paintOpacity;
+ vgSetParameterfv(opacityPaint, VG_PAINT_COLOR, 4, values);
+
+#if !defined(QVG_NO_MODIFY_PATH)
+ // Create a dummy path for rectangle drawing, which we can
+ // modify later with vgModifyPathCoords(). This should be
+ // faster than constantly creating and destroying paths.
+ rectPath = vgCreatePath(VG_PATH_FORMAT_STANDARD,
+ VG_PATH_DATATYPE_F,
+ 1.0f, // scale
+ 0.0f, // bias
+ 5, // segmentCapacityHint
+ 8, // coordCapacityHint
+ VG_PATH_CAPABILITY_ALL);
+ static VGubyte const segments[5] = {
+ VG_MOVE_TO_ABS,
+ VG_LINE_TO_ABS,
+ VG_LINE_TO_ABS,
+ VG_LINE_TO_ABS,
+ VG_CLOSE_PATH
+ };
+ VGfloat coords[8];
+ coords[0] = 0.0f;
+ coords[1] = 0.0f;
+ coords[2] = 100.0f;
+ coords[3] = coords[1];
+ coords[4] = coords[2];
+ coords[5] = 100.0f;
+ coords[6] = coords[0];
+ coords[7] = coords[5];
+ vgAppendPathData(rectPath, 5, segments, coords);
+
+ // Create a dummy line drawing path as well.
+ linePath = vgCreatePath(VG_PATH_FORMAT_STANDARD,
+ VG_PATH_DATATYPE_F,
+ 1.0f, // scale
+ 0.0f, // bias
+ 2, // segmentCapacityHint
+ 4, // coordCapacityHint
+ VG_PATH_CAPABILITY_ALL);
+ vgAppendPathData(linePath, 2, segments, coords);
+#endif
+}
+
+void QVGPaintEnginePrivate::destroy()
+{
+ if (penPaint)
+ vgDestroyPaint(penPaint);
+ if (brushPaint)
+ vgDestroyPaint(brushPaint);
+ if (opacityPaint)
+ vgDestroyPaint(opacityPaint);
+
+#if !defined(QVG_NO_MODIFY_PATH)
+ if (rectPath)
+ vgDestroyPath(rectPath);
+ if (linePath)
+ vgDestroyPath(linePath);
+#endif
+
+#if !defined(QVG_NO_DRAW_GLYPHS)
+ QVGFontCache::Iterator it;
+ for (it = fontCache.begin(); it != fontCache.end(); ++it)
+ delete it.value();
+ fontCache.clear();
+ delete fontEngineCleaner;
+#endif
+}
+
+// Set a specific VG transformation matrix in the current VG context.
+void QVGPaintEnginePrivate::setTransform
+ (VGMatrixMode mode, const QTransform& transform)
+{
+ VGfloat mat[9];
+ if (mode != matrixMode) {
+ vgSeti(VG_MATRIX_MODE, mode);
+ matrixMode = mode;
+ }
+ mat[0] = transform.m11();
+ mat[1] = transform.m12();
+ mat[2] = transform.m13();
+ mat[3] = transform.m21();
+ mat[4] = transform.m22();
+ mat[5] = transform.m23();
+ mat[6] = transform.m31();
+ mat[7] = transform.m32();
+ mat[8] = transform.m33();
+ vgLoadMatrix(mat);
+}
+
+extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale);
+
+void QVGPaintEnginePrivate::updateTransform(QPaintDevice *pdev)
+{
+ VGfloat devh = pdev->height() - 1;
+
+ // Construct the VG transform by combining the Qt transform with
+ // the following viewport transformation:
+ // | 1 0 0 | | 1 0 0.5 | | 1 0 0.5 |
+ // | 0 -1 devh | * | 0 1 -0.5 | = | 0 -1 (0.5 + devh) |
+ // | 0 0 1 | | 0 0 1 | | 0 0 1 |
+ // The full VG transform is effectively:
+ // 1. Apply the user's transformation matrix.
+ // 2. Translate by (0.5, -0.5) to correct for Qt and VG putting
+ // the centre of the pixel at different positions.
+ // 3. Flip the co-ordinate system upside down.
+ QTransform viewport(1.0f, 0.0f, 0.0f,
+ 0.0f, -1.0f, 0.0f,
+ 0.5f, devh + 0.5f, 1.0f);
+
+ // The image transform is always the full transformation,
+ // because it can be projective.
+ imageTransform = transform * viewport;
+
+ // Determine if the transformation is projective.
+ bool projective = (imageTransform.m13() != 0.0f ||
+ imageTransform.m23() != 0.0f ||
+ imageTransform.m33() != 1.0f);
+ if (projective) {
+ // The engine cannot do projective path transforms for us,
+ // so we will have to convert the co-ordinates ourselves.
+ // Change the matrix to just the viewport transformation.
+ pathTransform = viewport;
+ simpleTransform = false;
+ } else {
+ pathTransform = imageTransform;
+ simpleTransform = true;
+ }
+ pathTransformSet = false;
+
+ // Calculate the scaling factor to use for turning cosmetic pens
+ // into ordinary non-cosmetic pens.
+ qt_scaleForTransform(transform, &penScale);
+}
+
+VGPath QVGPaintEnginePrivate::vectorPathToVGPath(const QVectorPath& path)
+{
+ int count = path.elementCount();
+ const qreal *points = path.points();
+ const QPainterPath::ElementType *elements = path.elements();
+
+ VGPath vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD,
+ VG_PATH_DATATYPE_F,
+ 1.0f, // scale
+ 0.0f, // bias
+ count + 1, // segmentCapacityHint
+ count * 2, // coordCapacityHint
+ VG_PATH_CAPABILITY_ALL);
+
+ // Size is sufficient segments for drawRoundedRect() paths.
+ QVarLengthArray<VGubyte, 20> segments;
+
+ if (sizeof(qreal) == sizeof(VGfloat) && elements && simpleTransform) {
+ // If Qt was compiled with qreal the same size as VGfloat,
+ // then convert the segment types and use the incoming
+ // points array directly.
+ for (int i = 0; i < count; ++i) {
+ switch (elements[i]) {
+
+ case QPainterPath::MoveToElement:
+ segments.append(VG_MOVE_TO_ABS); break;
+
+ case QPainterPath::LineToElement:
+ segments.append(VG_LINE_TO_ABS); break;
+
+ case QPainterPath::CurveToElement: break;
+
+ case QPainterPath::CurveToDataElement:
+ segments.append(VG_CUBIC_TO_ABS); break;
+
+ }
+ }
+ if (path.hasImplicitClose())
+ segments.append(VG_CLOSE_PATH);
+
+ vgAppendPathData(vgpath, segments.count(), segments.constData(),
+ reinterpret_cast<const VGfloat *>(points));
+
+ return vgpath;
+ }
+
+ // Sizes chosen so that drawRoundedRect() paths fit in these arrays.
+ QVarLengthArray<VGfloat, 48> coords;
+
+ int curvePos = 0;
+ QPointF temp;
+
+ if (elements && simpleTransform) {
+ // Convert the members of the element array.
+ for (int i = 0; i < count; ++i) {
+ switch (elements[i]) {
+
+ case QPainterPath::MoveToElement:
+ {
+ coords.append(points[0]);
+ coords.append(points[1]);
+ segments.append(VG_MOVE_TO_ABS);
+ }
+ break;
+
+ case QPainterPath::LineToElement:
+ {
+ coords.append(points[0]);
+ coords.append(points[1]);
+ segments.append(VG_LINE_TO_ABS);
+ }
+ break;
+
+ case QPainterPath::CurveToElement:
+ {
+ coords.append(points[0]);
+ coords.append(points[1]);
+ curvePos = 2;
+ }
+ break;
+
+ case QPainterPath::CurveToDataElement:
+ {
+ coords.append(points[0]);
+ coords.append(points[1]);
+ curvePos += 2;
+ if (curvePos == 6) {
+ curvePos = 0;
+ segments.append(VG_CUBIC_TO_ABS);
+ }
+ }
+ break;
+
+ }
+ points += 2;
+ }
+ } else if (elements && !simpleTransform) {
+ // Convert the members of the element array after applying the
+ // current transform to the path locally.
+ for (int i = 0; i < count; ++i) {
+ switch (elements[i]) {
+
+ case QPainterPath::MoveToElement:
+ {
+ temp = transform.map(QPointF(points[0], points[1]));
+ coords.append(temp.x());
+ coords.append(temp.y());
+ segments.append(VG_MOVE_TO_ABS);
+ }
+ break;
+
+ case QPainterPath::LineToElement:
+ {
+ temp = transform.map(QPointF(points[0], points[1]));
+ coords.append(temp.x());
+ coords.append(temp.y());
+ segments.append(VG_LINE_TO_ABS);
+ }
+ break;
+
+ case QPainterPath::CurveToElement:
+ {
+ temp = transform.map(QPointF(points[0], points[1]));
+ coords.append(temp.x());
+ coords.append(temp.y());
+ curvePos = 2;
+ }
+ break;
+
+ case QPainterPath::CurveToDataElement:
+ {
+ temp = transform.map(QPointF(points[0], points[1]));
+ coords.append(temp.x());
+ coords.append(temp.y());
+ curvePos += 2;
+ if (curvePos == 6) {
+ curvePos = 0;
+ segments.append(VG_CUBIC_TO_ABS);
+ }
+ }
+ break;
+
+ }
+ points += 2;
+ }
+ } else if (count > 0 && simpleTransform) {
+ // If there is no element array, then the path is assumed
+ // to be a MoveTo followed by several LineTo's.
+ coords.append(points[0]);
+ coords.append(points[1]);
+ segments.append(VG_MOVE_TO_ABS);
+ while (count > 1) {
+ points += 2;
+ coords.append(points[0]);
+ coords.append(points[1]);
+ segments.append(VG_LINE_TO_ABS);
+ --count;
+ }
+ } else if (count > 0 && !simpleTransform) {
+ // Convert a simple path, and apply the transform locally.
+ temp = transform.map(QPointF(points[0], points[1]));
+ coords.append(temp.x());
+ coords.append(temp.y());
+ segments.append(VG_MOVE_TO_ABS);
+ while (count > 1) {
+ points += 2;
+ temp = transform.map(QPointF(points[0], points[1]));
+ coords.append(temp.x());
+ coords.append(temp.y());
+ segments.append(VG_LINE_TO_ABS);
+ --count;
+ }
+ }
+
+ // Close the path if specified.
+ if (path.hasImplicitClose())
+ segments.append(VG_CLOSE_PATH);
+
+ vgAppendPathData(vgpath, segments.count(),
+ segments.constData(), coords.constData());
+
+ return vgpath;
+}
+
+VGPath QVGPaintEnginePrivate::painterPathToVGPath(const QPainterPath& path)
+{
+ int count = path.elementCount();
+
+ VGPath vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD,
+ VG_PATH_DATATYPE_F,
+ 1.0f, // scale
+ 0.0f, // bias
+ count + 1, // segmentCapacityHint
+ count * 2, // coordCapacityHint
+ VG_PATH_CAPABILITY_ALL);
+
+ if (count == 0)
+ return vgpath;
+
+ const QPainterPath::Element *elements = &(path.elementAt(0));
+
+ // Sizes chosen so that drawRoundedRect() paths fit in these arrays.
+ QVarLengthArray<VGfloat, 48> coords;
+ QVarLengthArray<VGubyte, 20> segments;
+
+ int curvePos = 0;
+ QPointF temp;
+
+ // Keep track of the start and end of each sub-path. QPainterPath
+ // does not have an "implicit close" flag like QVectorPath does.
+ // We therefore have to detect closed paths by looking for a LineTo
+ // element that connects back to the initial MoveTo element.
+ qreal startx = 0.0;
+ qreal starty = 0.0;
+ qreal endx = 0.0;
+ qreal endy = 0.0;
+ bool haveStart = false;
+ bool haveEnd = false;
+
+ if (simpleTransform) {
+ // Convert the members of the element array.
+ for (int i = 0; i < count; ++i) {
+ switch (elements[i].type) {
+
+ case QPainterPath::MoveToElement:
+ {
+ if (haveStart && haveEnd && startx == endx && starty == endy) {
+ // Implicitly close the previous sub-path.
+ segments.append(VG_CLOSE_PATH);
+ }
+ startx = elements[i].x;
+ starty = elements[i].y;
+ coords.append(startx);
+ coords.append(starty);
+ haveStart = true;
+ haveEnd = false;
+ segments.append(VG_MOVE_TO_ABS);
+ }
+ break;
+
+ case QPainterPath::LineToElement:
+ {
+ endx = elements[i].x;
+ endy = elements[i].y;
+ coords.append(endx);
+ coords.append(endy);
+ haveEnd = true;
+ segments.append(VG_LINE_TO_ABS);
+ }
+ break;
+
+ case QPainterPath::CurveToElement:
+ {
+ coords.append(elements[i].x);
+ coords.append(elements[i].y);
+ haveEnd = false;
+ curvePos = 2;
+ }
+ break;
+
+ case QPainterPath::CurveToDataElement:
+ {
+ coords.append(elements[i].x);
+ coords.append(elements[i].y);
+ haveEnd = false;
+ curvePos += 2;
+ if (curvePos == 6) {
+ curvePos = 0;
+ segments.append(VG_CUBIC_TO_ABS);
+ }
+ }
+ break;
+
+ }
+ }
+ } else {
+ // Convert the members of the element array after applying the
+ // current transform to the path locally.
+ for (int i = 0; i < count; ++i) {
+ switch (elements[i].type) {
+
+ case QPainterPath::MoveToElement:
+ {
+ if (haveStart && haveEnd && startx == endx && starty == endy) {
+ // Implicitly close the previous sub-path.
+ segments.append(VG_CLOSE_PATH);
+ }
+ temp = transform.map(QPointF(elements[i].x, elements[i].y));
+ startx = temp.x();
+ starty = temp.y();
+ coords.append(startx);
+ coords.append(starty);
+ haveStart = true;
+ haveEnd = false;
+ segments.append(VG_MOVE_TO_ABS);
+ }
+ break;
+
+ case QPainterPath::LineToElement:
+ {
+ temp = transform.map(QPointF(elements[i].x, elements[i].y));
+ endx = temp.x();
+ endy = temp.y();
+ coords.append(endx);
+ coords.append(endy);
+ haveEnd = true;
+ segments.append(VG_LINE_TO_ABS);
+ }
+ break;
+
+ case QPainterPath::CurveToElement:
+ {
+ temp = transform.map(QPointF(elements[i].x, elements[i].y));
+ coords.append(temp.x());
+ coords.append(temp.y());
+ haveEnd = false;
+ curvePos = 2;
+ }
+ break;
+
+ case QPainterPath::CurveToDataElement:
+ {
+ temp = transform.map(QPointF(elements[i].x, elements[i].y));
+ coords.append(temp.x());
+ coords.append(temp.y());
+ haveEnd = false;
+ curvePos += 2;
+ if (curvePos == 6) {
+ curvePos = 0;
+ segments.append(VG_CUBIC_TO_ABS);
+ }
+ }
+ break;
+
+ }
+ }
+ }
+
+ if (haveStart && haveEnd && startx == endx && starty == endy) {
+ // Implicitly close the last sub-path.
+ segments.append(VG_CLOSE_PATH);
+ }
+
+ vgAppendPathData(vgpath, segments.count(),
+ segments.constData(), coords.constData());
+
+ return vgpath;
+}
+
+extern QImage qt_imageForBrush(int style, bool invert);
+
+static QImage colorizeBitmap(const QImage &image, const QColor &color)
+{
+ QImage sourceImage = image.convertToFormat(QImage::Format_MonoLSB);
+ QImage dest = QImage(sourceImage.size(), QImage::Format_ARGB32_Premultiplied);
+
+ QRgb fg = PREMUL(color.rgba());
+ QRgb bg = 0;
+
+ int height = sourceImage.height();
+ int width = sourceImage.width();
+ for (int y=0; y<height; ++y) {
+ uchar *source = sourceImage.scanLine(y);
+ QRgb *target = reinterpret_cast<QRgb *>(dest.scanLine(y));
+ for (int x=0; x < width; ++x)
+ target[x] = (source[x>>3] >> (x&7)) & 1 ? fg : bg;
+ }
+ return dest;
+}
+
+static VGImage toVGImage
+ (const QImage & image, Qt::ImageConversionFlags flags = Qt::AutoColor)
+{
+ QImage img(image);
+
+ VGImageFormat format;
+ switch (img.format()) {
+ case QImage::Format_Mono:
+ img = image.convertToFormat(QImage::Format_MonoLSB, flags);
+ format = VG_BW_1;
+ break;
+ case QImage::Format_MonoLSB:
+ format = VG_BW_1;
+ break;
+ case QImage::Format_RGB32:
+ format = VG_sXRGB_8888;
+ break;
+ case QImage::Format_ARGB32:
+ format = VG_sARGB_8888;
+ break;
+ case QImage::Format_ARGB32_Premultiplied:
+ format = VG_sARGB_8888_PRE;
+ break;
+ case QImage::Format_RGB16:
+ format = VG_sRGB_565;
+ break;
+ default:
+ // Convert everything else into ARGB32_Premultiplied.
+ img = image.convertToFormat(QImage::Format_ARGB32_Premultiplied, flags);
+ format = VG_sARGB_8888_PRE;
+ break;
+ }
+
+ const uchar *pixels = img.bits();
+
+ VGImage vgImg = vgCreateImage
+ (format, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
+ vgImageSubData
+ (vgImg, pixels, img.bytesPerLine(), format, 0, 0,
+ img.width(), img.height());
+
+ return vgImg;
+}
+
+static VGImage toVGImageSubRect
+ (const QImage & image, const QRect& sr,
+ Qt::ImageConversionFlags flags = Qt::AutoColor)
+{
+ QImage img(image);
+
+ VGImageFormat format;
+ int bpp = 4;
+
+ switch (img.format()) {
+ case QImage::Format_Mono:
+ case QImage::Format_MonoLSB:
+ return VG_INVALID_HANDLE;
+ case QImage::Format_RGB32:
+ format = VG_sXRGB_8888;
+ break;
+ case QImage::Format_ARGB32:
+ format = VG_sARGB_8888;
+ break;
+ case QImage::Format_ARGB32_Premultiplied:
+ format = VG_sARGB_8888_PRE;
+ break;
+ case QImage::Format_RGB16:
+ format = VG_sRGB_565;
+ bpp = 2;
+ break;
+ default:
+ // Convert everything else into ARGB32_Premultiplied.
+ img = image.convertToFormat(QImage::Format_ARGB32_Premultiplied, flags);
+ format = VG_sARGB_8888_PRE;
+ break;
+ }
+
+ const uchar *pixels = img.bits() + bpp * sr.x() +
+ img.bytesPerLine() * sr.y();
+
+ VGImage vgImg = vgCreateImage
+ (format, sr.width(), sr.height(), VG_IMAGE_QUALITY_FASTER);
+ vgImageSubData
+ (vgImg, pixels, img.bytesPerLine(), format, 0, 0,
+ sr.width(), sr.height());
+
+ return vgImg;
+}
+
+static VGImage toVGImageWithOpacity(const QImage & image, qreal opacity)
+{
+ QImage img(image.size(), QImage::Format_ARGB32_Premultiplied);
+ img.fill(0);
+ QPainter painter;
+ painter.begin(&img);
+ painter.setOpacity(opacity);
+ painter.drawImage(0, 0, image);
+ painter.end();
+
+ const uchar *pixels = img.bits();
+
+ VGImage vgImg = vgCreateImage
+ (VG_sARGB_8888_PRE, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
+ vgImageSubData
+ (vgImg, pixels, img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0,
+ img.width(), img.height());
+
+ return vgImg;
+}
+
+static VGImage toVGImageWithOpacitySubRect
+ (const QImage & image, qreal opacity, const QRect& sr)
+{
+ QImage img(sr.size(), QImage::Format_ARGB32_Premultiplied);
+ img.fill(0);
+ QPainter painter;
+ painter.begin(&img);
+ painter.setOpacity(opacity);
+ painter.drawImage(QPoint(0, 0), image, sr);
+ painter.end();
+
+ const uchar *pixels = img.bits();
+
+ VGImage vgImg = vgCreateImage
+ (VG_sARGB_8888_PRE, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
+ vgImageSubData
+ (vgImg, pixels, img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0,
+ img.width(), img.height());
+
+ return vgImg;
+}
+
+VGPaintType QVGPaintEnginePrivate::setBrush
+ (VGPaint paint, const QBrush& brush, VGMatrixMode mode,
+ VGPaintType prevType)
+{
+ VGfloat values[5];
+ setBrushTransform(brush, mode);
+
+ // Reset the paint pattern on the brush, which will discard
+ // the previous VGImage if one was set.
+ if (prevType == VG_PAINT_TYPE_PATTERN || prevType == (VGPaintType)0)
+ vgPaintPattern(paint, VG_INVALID_HANDLE);
+
+ switch (brush.style()) {
+
+ case Qt::SolidPattern: {
+ // The brush is a solid color.
+ QColor color(brush.color());
+ values[0] = color.redF();
+ values[1] = color.greenF();
+ values[2] = color.blueF();
+ values[3] = color.alphaF() * opacity;
+ if (prevType != VG_PAINT_TYPE_COLOR)
+ vgSetParameteri(paint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
+ vgSetParameterfv(paint, VG_PAINT_COLOR, 4, values);
+ return VG_PAINT_TYPE_COLOR;
+ }
+
+ case Qt::LinearGradientPattern: {
+ // The brush is a linear gradient.
+ Q_ASSERT(brush.gradient()->type() == QGradient::LinearGradient);
+ const QLinearGradient *grad =
+ static_cast<const QLinearGradient*>(brush.gradient());
+ values[0] = grad->start().x();
+ values[1] = grad->start().y();
+ values[2] = grad->finalStop().x();
+ values[3] = grad->finalStop().y();
+ if (prevType != VG_PAINT_TYPE_LINEAR_GRADIENT)
+ vgSetParameteri(paint, VG_PAINT_TYPE, VG_PAINT_TYPE_LINEAR_GRADIENT);
+ vgSetParameterfv(paint, VG_PAINT_LINEAR_GRADIENT, 4, values);
+ setupColorRamp(grad, paint);
+ return VG_PAINT_TYPE_LINEAR_GRADIENT;
+ }
+
+ case Qt::RadialGradientPattern: {
+ // The brush is a radial gradient.
+ Q_ASSERT(brush.gradient()->type() == QGradient::RadialGradient);
+ const QRadialGradient *grad =
+ static_cast<const QRadialGradient*>(brush.gradient());
+ values[0] = grad->center().x();
+ values[1] = grad->center().y();
+ values[2] = grad->focalPoint().x();
+ values[3] = grad->focalPoint().y();
+ values[4] = grad->radius();
+ if (prevType != VG_PAINT_TYPE_RADIAL_GRADIENT)
+ vgSetParameteri(paint, VG_PAINT_TYPE, VG_PAINT_TYPE_RADIAL_GRADIENT);
+ vgSetParameterfv(paint, VG_PAINT_RADIAL_GRADIENT, 5, values);
+ setupColorRamp(grad, paint);
+ return VG_PAINT_TYPE_RADIAL_GRADIENT;
+ }
+
+ case Qt::TexturePattern: {
+ // The brush is a texture specified by a QPixmap/QImage.
+ QPixmapData *pd = brush.texture().pixmapData();
+ VGImage vgImg;
+ if (pd->pixelType() == QPixmapData::BitmapType) {
+ // Colorize bitmaps using the brush color and opacity.
+ QColor color = brush.color();
+ if (opacity != 1.0)
+ color.setAlphaF(color.alphaF() * opacity);
+ QImage image = colorizeBitmap(*(pd->buffer()), color);
+ vgImg = toVGImage(image);
+ } else if (opacity == 1.0) {
+ if (pd->classId() == QPixmapData::OpenVGClass) {
+ QVGPixmapData *vgpd = static_cast<QVGPixmapData *>(pd);
+ vgImg = vgpd->toVGImage();
+ } else {
+ vgImg = toVGImage(*(pd->buffer()));
+ }
+ } else {
+ vgImg = toVGImageWithOpacity(*(pd->buffer()), opacity);
+ }
+ if (vgImg == VG_INVALID_HANDLE)
+ break;
+ if (prevType != VG_PAINT_TYPE_PATTERN)
+ vgSetParameteri(paint, VG_PAINT_TYPE, VG_PAINT_TYPE_PATTERN);
+ vgSetParameteri(paint, VG_PAINT_PATTERN_TILING_MODE, VG_TILE_REPEAT);
+ vgPaintPattern(paint, vgImg);
+ vgDestroyImage(vgImg); // Will stay valid until pattern is destroyed.
+ return VG_PAINT_TYPE_PATTERN;
+ }
+
+ case Qt::ConicalGradientPattern: {
+ // Convert conical gradients into the first stop color.
+ qWarning() << "QVGPaintEnginePrivate::setBrush: conical gradients are not supported by OpenVG";
+ Q_ASSERT(brush.gradient()->type() == QGradient::ConicalGradient);
+ const QConicalGradient *grad =
+ static_cast<const QConicalGradient*>(brush.gradient());
+ const QGradientStops stops = grad->stops();
+ QColor color;
+ if (stops.size() > 0)
+ color = stops[0].second;
+ values[0] = color.redF();
+ values[1] = color.greenF();
+ values[2] = color.blueF();
+ values[3] = color.alphaF() * opacity;
+ if (prevType != VG_PAINT_TYPE_COLOR)
+ vgSetParameteri(paint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
+ vgSetParameterfv(paint, VG_PAINT_COLOR, 4, values);
+ return VG_PAINT_TYPE_COLOR;
+ }
+
+ case Qt::Dense1Pattern:
+ case Qt::Dense2Pattern:
+ case Qt::Dense3Pattern:
+ case Qt::Dense4Pattern:
+ case Qt::Dense5Pattern:
+ case Qt::Dense6Pattern:
+ case Qt::Dense7Pattern:
+ case Qt::HorPattern:
+ case Qt::VerPattern:
+ case Qt::CrossPattern:
+ case Qt::BDiagPattern:
+ case Qt::FDiagPattern:
+ case Qt::DiagCrossPattern: {
+ // The brush is a traditional dotted or cross-hatched pattern brush.
+ QColor color = brush.color();
+ if (opacity != 1.0)
+ color.setAlphaF(color.alphaF() * opacity);
+ QImage image = colorizeBitmap
+ (qt_imageForBrush(brush.style(), true), color);
+ VGImage vgImg = toVGImage(image);
+ if (prevType != VG_PAINT_TYPE_PATTERN)
+ vgSetParameteri(paint, VG_PAINT_TYPE, VG_PAINT_TYPE_PATTERN);
+ vgSetParameteri(paint, VG_PAINT_PATTERN_TILING_MODE, VG_TILE_REPEAT);
+ vgPaintPattern(paint, vgImg);
+ vgDestroyImage(vgImg); // Will stay valid until pattern is destroyed.
+ return VG_PAINT_TYPE_PATTERN;
+ }
+
+ default: break;
+ }
+ return (VGPaintType)0;
+}
+
+void QVGPaintEnginePrivate::setPenParams(const QPen& pen)
+{
+ // Note: OpenVG does not support zero-width or cosmetic pens,
+ // so we have to simulate cosmetic pens by reversing the scale.
+ VGfloat width = pen.widthF();
+ if (width <= 0.0f)
+ width = 1.0f;
+ if (pen.isCosmetic()) {
+ if (penScale != 1.0 && penScale != 0.0)
+ width /= penScale;
+ }
+ vgSetf(VG_STROKE_LINE_WIDTH, width);
+
+ if (pen.capStyle() == Qt::FlatCap)
+ vgSetf(VG_STROKE_CAP_STYLE, VG_CAP_BUTT);
+ else if (pen.capStyle() == Qt::SquareCap)
+ vgSetf(VG_STROKE_CAP_STYLE, VG_CAP_SQUARE);
+ else
+ vgSetf(VG_STROKE_CAP_STYLE, VG_CAP_ROUND);
+
+ if (pen.joinStyle() == Qt::MiterJoin) {
+ vgSetf(VG_STROKE_JOIN_STYLE, VG_JOIN_MITER);
+ vgSetf(VG_STROKE_MITER_LIMIT, pen.miterLimit());
+ } else if (pen.joinStyle() == Qt::BevelJoin) {
+ vgSetf(VG_STROKE_JOIN_STYLE, VG_JOIN_BEVEL);
+ } else {
+ vgSetf(VG_STROKE_JOIN_STYLE, VG_JOIN_ROUND);
+ }
+
+ if (pen.style() == Qt::SolidLine) {
+ vgSetfv(VG_STROKE_DASH_PATTERN, 0, NULL);
+ } else {
+ const QVector<qreal> dashPattern = pen.dashPattern();
+ QVector<VGfloat> currentDashPattern(dashPattern.count());
+ for (int i = 0; i < dashPattern.count(); ++i)
+ currentDashPattern[i] = dashPattern[i] * width;
+ vgSetfv(VG_STROKE_DASH_PATTERN, currentDashPattern.count(), currentDashPattern.data());
+ vgSetf(VG_STROKE_DASH_PHASE, pen.dashOffset());
+ vgSetf(VG_STROKE_DASH_PHASE_RESET, VG_FALSE);
+ }
+}
+
+void QVGPaintEnginePrivate::setBrushTransform
+ (const QBrush& brush, VGMatrixMode mode)
+{
+ // Compute the new brush transformation matrix.
+ QTransform transform(brush.transform());
+ if (brushOrigin.x() != 0.0f || brushOrigin.y() != 0.0f)
+ transform.translate(brushOrigin.x(), brushOrigin.y());
+
+ // Bail out if the matrix is the same as last time, to avoid
+ // updating the VG context state unless absolutely necessary.
+ // Most applications won't have a brush transformation set,
+ // which will leave the VG setting at its default of identity.
+ // Always change the transform if coming out of raw VG mode.
+ if (mode == VG_MATRIX_FILL_PAINT_TO_USER) {
+ if (!rawVG && transform == brushTransform)
+ return;
+ brushTransform = transform;
+ } else {
+ if (!rawVG && transform == penTransform)
+ return;
+ penTransform = transform;
+ }
+
+ // Set the brush transformation matrix.
+ if (mode != matrixMode) {
+ vgSeti(VG_MATRIX_MODE, mode);
+ matrixMode = mode;
+ }
+ if (transform.isIdentity()) {
+ vgLoadIdentity();
+ } else {
+ VGfloat mat[9];
+ mat[0] = transform.m11();
+ mat[1] = transform.m12();
+ mat[2] = transform.m13();
+ mat[3] = transform.m21();
+ mat[4] = transform.m22();
+ mat[5] = transform.m23();
+ mat[6] = transform.m31();
+ mat[7] = transform.m32();
+ mat[8] = transform.m33();
+ vgLoadMatrix(mat);
+ }
+}
+
+void QVGPaintEnginePrivate::setupColorRamp(const QGradient *grad, VGPaint paint)
+{
+ QGradient::Spread spread = grad->spread();
+ VGColorRampSpreadMode spreadMode;
+ if (spread == QGradient::ReflectSpread)
+ spreadMode = VG_COLOR_RAMP_SPREAD_REFLECT;
+ else if (spread == QGradient::RepeatSpread)
+ spreadMode = VG_COLOR_RAMP_SPREAD_REPEAT;
+ else
+ spreadMode = VG_COLOR_RAMP_SPREAD_PAD;
+
+ const QGradientStops stops = grad->stops();
+ int n = 5*stops.size();
+ QVector<VGfloat> fill_stops(n);
+
+ for (int i = 0; i < stops.size(); ++i ) {
+ QColor col = stops[i].second;
+ fill_stops[i*5] = stops[i].first;
+ fill_stops[i*5 + 1] = col.redF();
+ fill_stops[i*5 + 2] = col.greenF();
+ fill_stops[i*5 + 3] = col.blueF();
+ fill_stops[i*5 + 4] = col.alphaF() * opacity;
+ }
+
+ vgSetParameteri(paint, VG_PAINT_COLOR_RAMP_SPREAD_MODE, spreadMode);
+ vgSetParameteri(paint, VG_PAINT_COLOR_RAMP_PREMULTIPLIED, VG_FALSE);
+ vgSetParameterfv(paint, VG_PAINT_COLOR_RAMP_STOPS, n, fill_stops.data());
+}
+
+QVGPainterState::QVGPainterState(QVGPainterState& other)
+ : QPainterState(other),
+ isNew(true), clipRegion(other.clipRegion),
+ savedDirty(0)
+{
+}
+
+QVGPainterState::QVGPainterState()
+ : isNew(true), savedDirty(0)
+{
+}
+
+QVGPainterState::~QVGPainterState()
+{
+}
+
+QVGPaintEngine::QVGPaintEngine()
+ : QPaintEngineEx(*new QVGPaintEnginePrivate)
+{
+}
+
+QVGPaintEngine::QVGPaintEngine(QVGPaintEnginePrivate &data)
+ : QPaintEngineEx(data)
+{
+}
+
+QVGPaintEngine::~QVGPaintEngine()
+{
+}
+
+QPainterState *QVGPaintEngine::createState(QPainterState *orig) const
+{
+ if (!orig) {
+ return new QVGPainterState();
+ } else {
+ QVGPaintEnginePrivate *d =
+ static_cast<QVGPaintEnginePrivate *>(d_ptr);
+ QVGPainterState *origState = static_cast<QVGPainterState *>(orig);
+ origState->savedDirty = d->dirty;
+ d->dirty = 0;
+ return new QVGPainterState(*origState);
+ }
+}
+
+void QVGPaintEnginePrivate::draw
+ (VGPath path, const QPen& pen, const QBrush& brush, VGint rule)
+{
+ VGbitfield mode = 0;
+ if (pen.style() != Qt::NoPen) {
+ ensurePen(pen);
+ mode |= VG_STROKE_PATH;
+ }
+ if (brush.style() != Qt::NoBrush) {
+ ensureBrush(brush);
+ setFillRule(rule);
+ mode |= VG_FILL_PATH;
+ }
+ if (mode != 0) {
+ ensurePathTransform();
+ vgDrawPath(path, mode);
+ }
+}
+
+void QVGPaintEnginePrivate::stroke(VGPath path, const QPen& pen)
+{
+ if (pen.style() == Qt::NoPen)
+ return;
+ ensurePen(pen);
+ ensurePathTransform();
+ vgDrawPath(path, VG_STROKE_PATH);
+}
+
+void QVGPaintEnginePrivate::fill(VGPath path, const QBrush& brush, VGint rule)
+{
+ if (brush.style() == Qt::NoBrush)
+ return;
+ ensureBrush(brush);
+ setFillRule(rule);
+ ensurePathTransform();
+ vgDrawPath(path, VG_FILL_PATH);
+}
+
+bool QVGPaintEngine::begin(QPaintDevice *pdev)
+{
+ Q_UNUSED(pdev);
+ Q_D(QVGPaintEngine);
+
+ // Initialize the VG painting objects if we haven't done it yet.
+ if (!d->penPaint)
+ d->initObjects();
+
+ // The initial clip region is the entire device area.
+ QVGPainterState *s = state();
+ s->clipRegion = defaultClipRegion();
+
+ // Initialize the VG state for this paint operation.
+ restoreState(QPaintEngine::AllDirty);
+ d->dirty = 0;
+ d->rawVG = false;
+ return true;
+}
+
+bool QVGPaintEngine::end()
+{
+ return true;
+}
+
+void QVGPaintEngine::draw(const QVectorPath &path)
+{
+ Q_D(QVGPaintEngine);
+ QVGPainterState *s = state();
+ VGPath vgpath = d->vectorPathToVGPath(path);
+ if (!path.hasWindingFill())
+ d->draw(vgpath, s->pen, s->brush, VG_EVEN_ODD);
+ else
+ d->draw(vgpath, s->pen, s->brush, VG_NON_ZERO);
+ vgDestroyPath(vgpath);
+}
+
+void QVGPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
+{
+ Q_D(QVGPaintEngine);
+ VGPath vgpath = d->vectorPathToVGPath(path);
+ if (!path.hasWindingFill())
+ d->fill(vgpath, brush, VG_EVEN_ODD);
+ else
+ d->fill(vgpath, brush, VG_NON_ZERO);
+ vgDestroyPath(vgpath);
+}
+
+void QVGPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
+{
+ Q_D(QVGPaintEngine);
+ VGPath vgpath = d->vectorPathToVGPath(path);
+ d->stroke(vgpath, pen);
+ vgDestroyPath(vgpath);
+}
+
+// Determine if a co-ordinate transform is simple enough to allow
+// rectangle-based clipping with vgMask(). Simple transforms most
+// often result from origin translations.
+static inline bool clipTransformIsSimple(const QTransform& transform)
+{
+ QTransform::TransformationType type = transform.type();
+ return (type == QTransform::TxNone || type == QTransform::TxTranslate);
+}
+
+#if defined(QVG_SCISSOR_CLIP)
+
+void QVGPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
+{
+ Q_D(QVGPaintEngine);
+ QVGPainterState *s = state();
+
+ d->dirty |= QPaintEngine::DirtyClipRegion;
+
+ if (op == Qt::NoClip) {
+ s->clipRegion = defaultClipRegion();
+ updateScissor();
+ return;
+ }
+
+ // We aren't using masking, so handle simple QRectF's only.
+ if (path.shape() == QVectorPath::RectangleHint &&
+ path.elementCount() == 4 && clipTransformIsSimple(d->transform)) {
+ // Clipping region that resulted from QPainter::setClipRect(QRectF).
+ // Convert it into a QRect and apply.
+ const qreal *points = path.points();
+ QRectF rect(points[0], points[1], points[2] - points[0],
+ points[5] - points[1]);
+ clip(rect.toRect(), op);
+ }
+}
+
+void QVGPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
+{
+ Q_D(QVGPaintEngine);
+ QVGPainterState *s = state();
+
+ d->dirty |= QPaintEngine::DirtyClipRegion;
+
+ // If we have a non-simple transform, then use path-based clipping.
+ if (op != Qt::NoClip && !clipTransformIsSimple(d->transform)) {
+ QPaintEngineEx::clip(rect, op);
+ return;
+ }
+
+ switch (op) {
+ case Qt::NoClip:
+ {
+ s->clipRegion = defaultClipRegion();
+ }
+ break;
+
+ case Qt::ReplaceClip:
+ {
+ s->clipRegion = d->transform.map(QRegion(rect));
+ }
+ break;
+
+ case Qt::IntersectClip:
+ {
+ s->clipRegion = s->clipRegion.intersect(d->transform.map(QRegion(rect)));
+ }
+ break;
+
+ case Qt::UniteClip:
+ {
+ s->clipRegion = s->clipRegion.unite(d->transform.map(QRegion(rect)));
+ }
+ break;
+ }
+
+ updateScissor();
+}
+
+void QVGPaintEngine::clip(const QRegion &region, Qt::ClipOperation op)
+{
+ Q_D(QVGPaintEngine);
+ QVGPainterState *s = state();
+
+ d->dirty |= QPaintEngine::DirtyClipRegion;
+
+ // If we have a non-simple transform, then use path-based clipping.
+ if (op != Qt::NoClip && !clipTransformIsSimple(d->transform)) {
+ QPaintEngineEx::clip(region, op);
+ return;
+ }
+
+ switch (op) {
+ case Qt::NoClip:
+ {
+ s->clipRegion = defaultClipRegion();
+ }
+ break;
+
+ case Qt::ReplaceClip:
+ {
+ s->clipRegion = d->transform.map(region);
+ }
+ break;
+
+ case Qt::IntersectClip:
+ {
+ s->clipRegion = s->clipRegion.intersect(d->transform.map(region));
+ }
+ break;
+
+ case Qt::UniteClip:
+ {
+ s->clipRegion = s->clipRegion.unite(d->transform.map(region));
+ }
+ break;
+ }
+
+ updateScissor();
+}
+
+void QVGPaintEngine::clip(const QPainterPath &path, Qt::ClipOperation op)
+{
+ QPaintEngineEx::clip(path, op);
+}
+
+#else // !QVG_SCISSOR_CLIP
+
+void QVGPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
+{
+ Q_D(QVGPaintEngine);
+
+ d->dirty |= QPaintEngine::DirtyClipRegion;
+
+ if (op == Qt::NoClip) {
+ d->maskValid = false;
+ d->maskIsSet = true;
+ d->maskRect = QRect();
+ vgSeti(VG_MASKING, VG_FALSE);
+ return;
+ }
+
+#if defined(QVG_NO_RENDER_TO_MASK)
+ // We don't have vgRenderToMask(), so handle simple QRectF's only.
+ if (path.shape() == QVectorPath::RectangleHint &&
+ path.elementCount() == 4 && clipTransformIsSimple(d->transform)) {
+ // Clipping region that resulted from QPainter::setClipRect(QRectF).
+ // Convert it into a QRect and apply.
+ const qreal *points = path.points();
+ QRectF rect(points[0], points[1], points[2] - points[0],
+ points[5] - points[1]);
+ clip(rect.toRect(), op);
+ }
+#else
+ QPaintDevice *pdev = paintDevice();
+ int width = pdev->width();
+ int height = pdev->height();
+
+ if (op == Qt::ReplaceClip) {
+ vgMask(VG_INVALID_HANDLE, VG_CLEAR_MASK, 0, 0, width, height);
+ d->maskRect = QRect();
+ } else if (!d->maskValid) {
+ d->ensureMask(this, width, height);
+ }
+
+ d->ensurePathTransform();
+ VGPath vgpath = d->vectorPathToVGPath(path);
+ switch (op) {
+ case Qt::ReplaceClip:
+ case Qt::UniteClip:
+ vgRenderToMask(vgpath, VG_FILL_PATH, VG_UNION_MASK);
+ break;
+
+ case Qt::IntersectClip:
+ vgRenderToMask(vgpath, VG_FILL_PATH, VG_INTERSECT_MASK);
+ break;
+
+ default: break;
+ }
+ vgDestroyPath(vgpath);
+
+ vgSeti(VG_MASKING, VG_TRUE);
+ d->maskValid = true;
+ d->maskIsSet = false;
+#endif
+}
+
+void QVGPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
+{
+ clip(QRegion(rect), op);
+}
+
+void QVGPaintEngine::clip(const QRegion &region, Qt::ClipOperation op)
+{
+ Q_D(QVGPaintEngine);
+
+ d->dirty |= QPaintEngine::DirtyClipRegion;
+
+ // If we have a non-simple transform, then use path-based clipping.
+ if (op != Qt::NoClip && !clipTransformIsSimple(d->transform)) {
+ QPaintEngineEx::clip(region, op);
+ return;
+ }
+
+ switch (op) {
+ case Qt::NoClip:
+ {
+ d->maskValid = false;
+ d->maskIsSet = true;
+ d->maskRect = QRect();
+ vgSeti(VG_MASKING, VG_FALSE);
+ }
+ break;
+
+ case Qt::ReplaceClip:
+ {
+ QRegion r = d->transform.map(region);
+ if (isDefaultClipRegion(r)) {
+ // Replacing the clip with a full-window region is the
+ // same as turning off clipping.
+ if (d->maskValid)
+ vgSeti(VG_MASKING, VG_FALSE);
+ d->maskValid = false;
+ d->maskIsSet = true;
+ d->maskRect = QRect();
+ } else {
+ // Special case: if the intersection of the system
+ // clip and the region is a single rectangle, then
+ // use the scissor for clipping.
+ QRegion clip = d->systemClip;
+ if (clip.isEmpty())
+ clip = r;
+ else
+ clip = clip.intersect(r);
+ if (r.numRects() == 1) {
+ d->maskValid = false;
+ d->maskIsSet = false;
+ d->maskRect = r.boundingRect();
+ vgSeti(VG_MASKING, VG_FALSE);
+ updateScissor();
+ } else {
+ d->maskValid = false;
+ d->maskIsSet = false;
+ d->maskRect = QRect();
+ d->modifyMask(this, VG_FILL_MASK, r);
+ }
+ }
+ }
+ break;
+
+ case Qt::IntersectClip:
+ {
+ if (region.numRects() != 1) {
+ // If there is more than one rectangle, then intersecting
+ // the rectangles one by one in modifyMask() will not give
+ // the desired result. So fall back to path-based clipping.
+ QPaintEngineEx::clip(region, op);
+ return;
+ }
+ QRegion r = d->transform.map(region);
+ if (d->maskIsSet && isDefaultClipRegion(r)) {
+ // Intersecting a full-window clip with a full-window
+ // region is the same as turning off clipping.
+ if (d->maskValid)
+ vgSeti(VG_MASKING, VG_FALSE);
+ d->maskValid = false;
+ d->maskIsSet = true;
+ d->maskRect = QRect();
+ } else {
+ d->modifyMask(this, VG_INTERSECT_MASK, r);
+ }
+ }
+ break;
+
+ case Qt::UniteClip:
+ {
+ // If we already have a full-window clip, then uniting a
+ // region with it will do nothing. Otherwise union.
+ if (!(d->maskIsSet))
+ d->modifyMask(this, VG_UNION_MASK, d->transform.map(region));
+ }
+ break;
+ }
+}
+
+void QVGPaintEngine::clip(const QPainterPath &path, Qt::ClipOperation op)
+{
+#if !defined(QVG_NO_RENDER_TO_MASK)
+ Q_D(QVGPaintEngine);
+
+ d->dirty |= QPaintEngine::DirtyClipRegion;
+
+ if (op == Qt::NoClip) {
+ d->maskValid = false;
+ d->maskIsSet = true;
+ d->maskRect = QRect();
+ vgSeti(VG_MASKING, VG_FALSE);
+ return;
+ }
+
+ QPaintDevice *pdev = paintDevice();
+ int width = pdev->width();
+ int height = pdev->height();
+
+ if (op == Qt::ReplaceClip) {
+ vgMask(VG_INVALID_HANDLE, VG_CLEAR_MASK, 0, 0, width, height);
+ d->maskRect = QRect();
+ } else if (!d->maskValid) {
+ d->ensureMask(this, width, height);
+ }
+
+ d->ensurePathTransform();
+ VGPath vgpath = d->painterPathToVGPath(path);
+ switch (op) {
+ case Qt::ReplaceClip:
+ case Qt::UniteClip:
+ vgRenderToMask(vgpath, VG_FILL_PATH, VG_UNION_MASK);
+ break;
+
+ case Qt::IntersectClip:
+ vgRenderToMask(vgpath, VG_FILL_PATH, VG_INTERSECT_MASK);
+ break;
+
+ default: break;
+ }
+ vgDestroyPath(vgpath);
+
+ vgSeti(VG_MASKING, VG_TRUE);
+ d->maskValid = true;
+ d->maskIsSet = false;
+#else
+ QPaintEngineEx::clip(path, op);
+#endif
+}
+
+void QVGPaintEnginePrivate::ensureMask
+ (QVGPaintEngine *engine, int width, int height)
+{
+ if (maskIsSet) {
+ vgMask(VG_INVALID_HANDLE, VG_FILL_MASK, 0, 0, width, height);
+ maskRect = QRect();
+ } else {
+ vgMask(VG_INVALID_HANDLE, VG_CLEAR_MASK, 0, 0, width, height);
+ if (!maskRect.isNull()) {
+ vgMask(VG_INVALID_HANDLE, VG_FILL_MASK,
+ maskRect.x(), height - maskRect.y() - maskRect.height(),
+ maskRect.width(), maskRect.height());
+ maskRect = QRect();
+ engine->updateScissor();
+ }
+ }
+}
+
+void QVGPaintEnginePrivate::modifyMask
+ (QVGPaintEngine *engine, VGMaskOperation op, const QRegion& region)
+{
+ QPaintDevice *pdev = engine->paintDevice();
+ int width = pdev->width();
+ int height = pdev->height();
+
+ if (!maskValid)
+ ensureMask(engine, width, height);
+
+ QVector<QRect> rects = region.rects();
+ for (int i = 0; i < rects.size(); ++i) {
+ vgMask(VG_INVALID_HANDLE, op,
+ rects[i].x(), height - rects[i].y() - rects[i].height(),
+ rects[i].width(), rects[i].height());
+ }
+
+ vgSeti(VG_MASKING, VG_TRUE);
+ maskValid = true;
+ maskIsSet = false;
+}
+
+#endif // !QVG_SCISSOR_CLIP
+
+void QVGPaintEngine::updateScissor()
+{
+ Q_D(QVGPaintEngine);
+
+ QRegion region = d->systemClip;
+
+#if defined(QVG_SCISSOR_CLIP)
+ // Using the scissor to do clipping, so combine the systemClip
+ // with the current painting clipRegion.
+ QVGPainterState *s = state();
+ if (s->clipEnabled) {
+ if (region.isEmpty())
+ region = s->clipRegion;
+ else
+ region = region.intersect(s->clipRegion);
+ if (isDefaultClipRegion(region)) {
+ // The scissor region is the entire drawing surface,
+ // so there is no point doing any scissoring.
+ vgSeti(VG_SCISSORING, VG_FALSE);
+ d->scissorActive = false;
+ return;
+ }
+ } else
+#endif
+ {
+#if !defined(QVG_SCISSOR_CLIP)
+ // Combine the system clip with the simple mask rectangle.
+ if (!d->maskRect.isNull()) {
+ if (region.isEmpty())
+ region = d->maskRect;
+ else
+ region.intersect(d->maskRect);
+ if (isDefaultClipRegion(region)) {
+ // The scissor region is the entire drawing surface,
+ // so there is no point doing any scissoring.
+ vgSeti(VG_SCISSORING, VG_FALSE);
+ d->scissorActive = false;
+ return;
+ }
+ } else
+#endif
+
+ // Disable the scissor completely if the system clip is empty.
+ if (region.isEmpty()) {
+ vgSeti(VG_SCISSORING, VG_FALSE);
+ d->scissorActive = false;
+ return;
+ }
+ }
+
+ if (d->scissorActive && region == d->scissorRegion)
+ return;
+
+ QVector<QRect> rects = region.rects();
+ int count = rects.count();
+ if (count > d->maxScissorRects)
+ count = d->maxScissorRects;
+ QVarLengthArray<VGint> params(count * 4);
+ int height = paintDevice()->height();
+ for (int i = 0; i < count; ++i) {
+ params[i * 4 + 0] = rects[i].x();
+ params[i * 4 + 1] = height - rects[i].y() - rects[i].height();
+ params[i * 4 + 2] = rects[i].width();
+ params[i * 4 + 3] = rects[i].height();
+ }
+
+ vgSetiv(VG_SCISSOR_RECTS, count * 4, params.data());
+ vgSeti(VG_SCISSORING, VG_TRUE);
+ d->scissorActive = true;
+ d->scissorRegion = region;
+}
+
+QRegion QVGPaintEngine::defaultClipRegion()
+{
+ // The default clip region for a paint device is the whole drawing area.
+ QPaintDevice *pdev = paintDevice();
+ return QRegion(0, 0, pdev->width(), pdev->height());
+}
+
+bool QVGPaintEngine::isDefaultClipRegion(const QRegion& region)
+{
+ if (region.numRects() != 1)
+ return false;
+
+ QPaintDevice *pdev = paintDevice();
+ int width = pdev->width();
+ int height = pdev->height();
+
+ QRect rect = region.boundingRect();
+ return (rect.x() == 0 && rect.y() == 0 &&
+ rect.width() == width && rect.height() == height);
+}
+
+void QVGPaintEngine::clipEnabledChanged()
+{
+#if defined(QVG_SCISSOR_CLIP)
+ updateScissor();
+#else
+ Q_D(QVGPaintEngine);
+ QVGPainterState *s = state();
+ d->dirty |= QPaintEngine::DirtyClipEnabled;
+ if (s->clipEnabled && s->clipOperation != Qt::NoClip) {
+ // Replay the entire clip stack to put the mask into the right state.
+ d->maskValid = false;
+ d->maskIsSet = true;
+ d->maskRect = QRect();
+ s->clipRegion = defaultClipRegion();
+ d->replayClipOperations();
+ d->transform = s->transform();
+ d->updateTransform(paintDevice());
+ } else {
+ vgSeti(VG_MASKING, VG_FALSE);
+ d->maskValid = false;
+ d->maskIsSet = false;
+ d->maskRect = QRect();
+ }
+#endif
+}
+
+void QVGPaintEngine::penChanged()
+{
+ Q_D(QVGPaintEngine);
+ d->dirty |= QPaintEngine::DirtyPen;
+}
+
+void QVGPaintEngine::brushChanged()
+{
+ Q_D(QVGPaintEngine);
+ d->dirty |= QPaintEngine::DirtyBrush;
+}
+
+void QVGPaintEngine::brushOriginChanged()
+{
+ Q_D(QVGPaintEngine);
+ d->dirty |= QPaintEngine::DirtyBrushOrigin;
+ d->brushOrigin = state()->brushOrigin;
+ d->forcePenChange = true;
+ d->forceBrushChange = true;
+}
+
+void QVGPaintEngine::opacityChanged()
+{
+ Q_D(QVGPaintEngine);
+ d->dirty |= QPaintEngine::DirtyOpacity;
+ d->opacity = state()->opacity;
+ d->forcePenChange = true;
+ d->forceBrushChange = true;
+}
+
+void QVGPaintEngine::compositionModeChanged()
+{
+ Q_D(QVGPaintEngine);
+ d->dirty |= QPaintEngine::DirtyCompositionMode;
+
+ VGBlendMode vgMode = VG_BLEND_SRC_OVER;
+
+ switch (state()->composition_mode) {
+ case QPainter::CompositionMode_SourceOver:
+ vgMode = VG_BLEND_SRC_OVER;
+ break;
+ case QPainter::CompositionMode_DestinationOver:
+ vgMode = VG_BLEND_DST_OVER;
+ break;
+ case QPainter::CompositionMode_Source:
+ vgMode = VG_BLEND_SRC;
+ break;
+ case QPainter::CompositionMode_SourceIn:
+ vgMode = VG_BLEND_SRC_IN;
+ break;
+ case QPainter::CompositionMode_DestinationIn:
+ vgMode = VG_BLEND_DST_IN;
+ break;
+ case QPainter::CompositionMode_Plus:
+ vgMode = VG_BLEND_ADDITIVE;
+ break;
+ case QPainter::CompositionMode_Multiply:
+ vgMode = VG_BLEND_MULTIPLY;
+ break;
+ case QPainter::CompositionMode_Screen:
+ vgMode = VG_BLEND_SCREEN;
+ break;
+ case QPainter::CompositionMode_Darken:
+ vgMode = VG_BLEND_DARKEN;
+ break;
+ case QPainter::CompositionMode_Lighten:
+ vgMode = VG_BLEND_LIGHTEN;
+ break;
+ default:
+ qWarning() << "QVGPaintEngine::compositionModeChanged unsupported mode" << state()->composition_mode;
+ break; // Fall back to VG_BLEND_SRC_OVER.
+ }
+
+ d->setBlendMode(vgMode);
+}
+
+void QVGPaintEngine::renderHintsChanged()
+{
+ Q_D(QVGPaintEngine);
+ d->dirty |= QPaintEngine::DirtyHints;
+
+ QPainter::RenderHints hints = state()->renderHints;
+
+ VGRenderingQuality rq =
+ (hints & QPainter::Antialiasing)
+ ? VG_RENDERING_QUALITY_BETTER
+ : VG_RENDERING_QUALITY_NONANTIALIASED;
+ VGImageQuality iq =
+ (hints & QPainter::SmoothPixmapTransform)
+ ? VG_IMAGE_QUALITY_BETTER
+ : VG_IMAGE_QUALITY_NONANTIALIASED;
+
+ d->setRenderingQuality(rq);
+ d->setImageQuality(iq);
+}
+
+void QVGPaintEngine::transformChanged()
+{
+ Q_D(QVGPaintEngine);
+ QVGPainterState *s = state();
+ d->dirty |= QPaintEngine::DirtyTransform;
+ d->transform = s->transform();
+ qreal oldPenScale = d->penScale;
+ d->updateTransform(paintDevice());
+ if (d->penScale != oldPenScale)
+ d->forcePenChange = true;
+}
+
+bool QVGPaintEngine::clearRect(const QRectF &rect, const QColor &color)
+{
+ Q_D(QVGPaintEngine);
+ QVGPainterState *s = state();
+ if (!s->clipEnabled || s->clipOperation == Qt::NoClip) {
+ // The transform will either be identity or a simple translation,
+ // so do a simpler version of "r = d->transform.map(rect).toRect()".
+ QRect r = QRect(qRound(rect.x() + d->transform.dx()),
+ qRound(rect.y() + d->transform.dy()),
+ qRound(rect.width()),
+ qRound(rect.height()));
+ int height = paintDevice()->height();
+ if (d->clearColor != color || d->clearOpacity != s->opacity) {
+ VGfloat values[4];
+ values[0] = color.redF();
+ values[1] = color.greenF();
+ values[2] = color.blueF();
+ values[3] = color.alphaF() * s->opacity;
+ vgSetfv(VG_CLEAR_COLOR, 4, values);
+ d->clearColor = color;
+ d->clearOpacity = s->opacity;
+ }
+ vgClear(r.x(), height - r.y() - r.height(),
+ r.width(), r.height());
+ return true;
+ }
+ return false;
+}
+
+void QVGPaintEngine::fillRect(const QRectF &rect, const QBrush &brush)
+{
+ Q_D(QVGPaintEngine);
+
+ if (brush.style() == Qt::NoBrush)
+ return;
+
+ // Check to see if we can use vgClear() for faster filling.
+ if (brush.style() == Qt::SolidPattern &&
+ clipTransformIsSimple(d->transform) && d->opacity == 1.0f &&
+ clearRect(rect, brush.color())) {
+ return;
+ }
+
+#if !defined(QVG_NO_MODIFY_PATH)
+ VGfloat coords[8];
+ if (d->simpleTransform) {
+ coords[0] = rect.x();
+ coords[1] = rect.y();
+ coords[2] = rect.x() + rect.width();
+ coords[3] = coords[1];
+ coords[4] = coords[2];
+ coords[5] = rect.y() + rect.height();
+ coords[6] = coords[0];
+ coords[7] = coords[5];
+ } else {
+ QPointF tl = d->transform.map(rect.topLeft());
+ QPointF tr = d->transform.map(rect.topRight());
+ QPointF bl = d->transform.map(rect.bottomLeft());
+ QPointF br = d->transform.map(rect.bottomRight());
+ coords[0] = tl.x();
+ coords[1] = tl.y();
+ coords[2] = tr.x();
+ coords[3] = tr.y();
+ coords[4] = br.x();
+ coords[5] = br.y();
+ coords[6] = bl.x();
+ coords[7] = bl.y();
+ }
+ vgModifyPathCoords(d->rectPath, 0, 4, coords);
+ d->fill(d->rectPath, brush);
+#else
+ QPaintEngineEx::fillRect(rect, brush);
+#endif
+}
+
+void QVGPaintEngine::fillRect(const QRectF &rect, const QColor &color)
+{
+ Q_D(QVGPaintEngine);
+
+ // Check to see if we can use vgClear() for faster filling.
+ if (clipTransformIsSimple(d->transform) && d->opacity == 1.0f &&
+ clearRect(rect, color)) {
+ return;
+ }
+
+#if !defined(QVG_NO_MODIFY_PATH)
+ VGfloat coords[8];
+ if (d->simpleTransform) {
+ coords[0] = rect.x();
+ coords[1] = rect.y();
+ coords[2] = rect.x() + rect.width();
+ coords[3] = coords[1];
+ coords[4] = coords[2];
+ coords[5] = rect.y() + rect.height();
+ coords[6] = coords[0];
+ coords[7] = coords[5];
+ } else {
+ QPointF tl = d->transform.map(rect.topLeft());
+ QPointF tr = d->transform.map(rect.topRight());
+ QPointF bl = d->transform.map(rect.bottomLeft());
+ QPointF br = d->transform.map(rect.bottomRight());
+ coords[0] = tl.x();
+ coords[1] = tl.y();
+ coords[2] = tr.x();
+ coords[3] = tr.y();
+ coords[4] = br.x();
+ coords[5] = br.y();
+ coords[6] = bl.x();
+ coords[7] = bl.y();
+ }
+ vgModifyPathCoords(d->rectPath, 0, 4, coords);
+ d->fill(d->rectPath, QBrush(color));
+#else
+ QPaintEngineEx::fillRect(rect, QBrush(color));
+#endif
+}
+
+void QVGPaintEngine::drawRects(const QRect *rects, int rectCount)
+{
+#if !defined(QVG_NO_MODIFY_PATH)
+ Q_D(QVGPaintEngine);
+ QVGPainterState *s = state();
+ for (int i = 0; i < rectCount; ++i, ++rects) {
+ VGfloat coords[8];
+ if (d->simpleTransform) {
+ coords[0] = rects->x();
+ coords[1] = rects->y();
+ coords[2] = rects->x() + rects->width();
+ coords[3] = coords[1];
+ coords[4] = coords[2];
+ coords[5] = rects->y() + rects->height();
+ coords[6] = coords[0];
+ coords[7] = coords[5];
+ } else {
+ QPointF tl = d->transform.map(QPointF(rects->x(), rects->y()));
+ QPointF tr = d->transform.map(QPointF(rects->x() + rects->width(),
+ rects->y()));
+ QPointF bl = d->transform.map(QPointF(rects->x(),
+ rects->y() + rects->height()));
+ QPointF br = d->transform.map(QPointF(rects->x() + rects->width(),
+ rects->y() + rects->height()));
+ coords[0] = tl.x();
+ coords[1] = tl.y();
+ coords[2] = tr.x();
+ coords[3] = tr.y();
+ coords[4] = br.x();
+ coords[5] = br.y();
+ coords[6] = bl.x();
+ coords[7] = bl.y();
+ }
+ vgModifyPathCoords(d->rectPath, 0, 4, coords);
+ d->draw(d->rectPath, s->pen, s->brush);
+ }
+#else
+ QPaintEngineEx::drawRects(rects, rectCount);
+#endif
+}
+
+void QVGPaintEngine::drawRects(const QRectF *rects, int rectCount)
+{
+#if !defined(QVG_NO_MODIFY_PATH)
+ Q_D(QVGPaintEngine);
+ QVGPainterState *s = state();
+ for (int i = 0; i < rectCount; ++i, ++rects) {
+ VGfloat coords[8];
+ if (d->simpleTransform) {
+ coords[0] = rects->x();
+ coords[1] = rects->y();
+ coords[2] = rects->x() + rects->width();
+ coords[3] = coords[1];
+ coords[4] = coords[2];
+ coords[5] = rects->y() + rects->height();
+ coords[6] = coords[0];
+ coords[7] = coords[5];
+ } else {
+ QPointF tl = d->transform.map(rects->topLeft());
+ QPointF tr = d->transform.map(rects->topRight());
+ QPointF bl = d->transform.map(rects->bottomLeft());
+ QPointF br = d->transform.map(rects->bottomRight());
+ coords[0] = tl.x();
+ coords[1] = tl.y();
+ coords[2] = tr.x();
+ coords[3] = tr.y();
+ coords[4] = br.x();
+ coords[5] = br.y();
+ coords[6] = bl.x();
+ coords[7] = bl.y();
+ }
+ vgModifyPathCoords(d->rectPath, 0, 4, coords);
+ d->draw(d->rectPath, s->pen, s->brush);
+ }
+#else
+ QPaintEngineEx::drawRects(rects, rectCount);
+#endif
+}
+
+void QVGPaintEngine::drawLines(const QLine *lines, int lineCount)
+{
+#if !defined(QVG_NO_MODIFY_PATH)
+ Q_D(QVGPaintEngine);
+ QVGPainterState *s = state();
+ for (int i = 0; i < lineCount; ++i, ++lines) {
+ VGfloat coords[4];
+ if (d->simpleTransform) {
+ coords[0] = lines->x1();
+ coords[1] = lines->y1();
+ coords[2] = lines->x2();
+ coords[3] = lines->y2();
+ } else {
+ QPointF p1 = d->transform.map(QPointF(lines->x1(), lines->y1()));
+ QPointF p2 = d->transform.map(QPointF(lines->x2(), lines->y2()));
+ coords[0] = p1.x();
+ coords[1] = p1.y();
+ coords[2] = p2.x();
+ coords[3] = p2.y();
+ }
+ vgModifyPathCoords(d->linePath, 0, 2, coords);
+ d->stroke(d->linePath, s->pen);
+ }
+#else
+ QPaintEngineEx::drawLines(lines, lineCount);
+#endif
+}
+
+void QVGPaintEngine::drawLines(const QLineF *lines, int lineCount)
+{
+#if !defined(QVG_NO_MODIFY_PATH)
+ Q_D(QVGPaintEngine);
+ QVGPainterState *s = state();
+ for (int i = 0; i < lineCount; ++i, ++lines) {
+ VGfloat coords[4];
+ if (d->simpleTransform) {
+ coords[0] = lines->x1();
+ coords[1] = lines->y1();
+ coords[2] = lines->x2();
+ coords[3] = lines->y2();
+ } else {
+ QPointF p1 = d->transform.map(lines->p1());
+ QPointF p2 = d->transform.map(lines->p2());
+ coords[0] = p1.x();
+ coords[1] = p1.y();
+ coords[2] = p2.x();
+ coords[3] = p2.y();
+ }
+ vgModifyPathCoords(d->linePath, 0, 2, coords);
+ d->stroke(d->linePath, s->pen);
+ }
+#else
+ QPaintEngineEx::drawLines(lines, lineCount);
+#endif
+}
+
+void QVGPaintEngine::drawEllipse(const QRectF &r)
+{
+ // Based on the description of vguEllipse() in the OpenVG specification.
+ // We don't use vguEllipse(), to avoid unnecessary library dependencies.
+ Q_D(QVGPaintEngine);
+ if (d->simpleTransform) {
+ QVGPainterState *s = state();
+ VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD,
+ VG_PATH_DATATYPE_F,
+ 1.0f, // scale
+ 0.0f, // bias
+ 4, // segmentCapacityHint
+ 12, // coordCapacityHint
+ VG_PATH_CAPABILITY_ALL);
+ static VGubyte segments[4] = {
+ VG_MOVE_TO_ABS,
+ VG_SCCWARC_TO_REL,
+ VG_SCCWARC_TO_REL,
+ VG_CLOSE_PATH
+ };
+ VGfloat coords[12];
+ VGfloat halfwid = r.width() / 2;
+ VGfloat halfht = r.height() / 2;
+ coords[0] = r.x() + r.width();
+ coords[1] = r.y() + halfht;
+ coords[2] = halfwid;
+ coords[3] = halfht;
+ coords[4] = 0.0f;
+ coords[5] = -r.width();
+ coords[6] = 0.0f;
+ coords[7] = halfwid;
+ coords[8] = halfht;
+ coords[9] = 0.0f;
+ coords[10] = r.width();
+ coords[11] = 0.0f;
+ vgAppendPathData(path, 4, segments, coords);
+ d->draw(path, s->pen, s->brush);
+ vgDestroyPath(path);
+ } else {
+ // The projective transform version of an ellipse is difficult.
+ // Generate a QVectorPath containing cubic curves and transform that.
+ QPaintEngineEx::drawEllipse(r);
+ }
+}
+
+void QVGPaintEngine::drawEllipse(const QRect &r)
+{
+ drawEllipse(QRectF(r));
+}
+
+void QVGPaintEngine::drawPath(const QPainterPath &path)
+{
+ // Shortcut past the QPainterPath -> QVectorPath conversion,
+ // converting the QPainterPath directly into a VGPath.
+ Q_D(QVGPaintEngine);
+ QVGPainterState *s = state();
+ VGPath vgpath = d->painterPathToVGPath(path);
+ if (path.fillRule() == Qt::OddEvenFill)
+ d->draw(vgpath, s->pen, s->brush, VG_EVEN_ODD);
+ else
+ d->draw(vgpath, s->pen, s->brush, VG_NON_ZERO);
+ vgDestroyPath(vgpath);
+}
+
+void QVGPaintEngine::drawPoints(const QPointF *points, int pointCount)
+{
+#if !defined(QVG_NO_MODIFY_PATH)
+ Q_D(QVGPaintEngine);
+
+ // Set up a new pen if necessary.
+ QPen pen = state()->pen;
+ if (pen.style() == Qt::NoPen)
+ return;
+ if (pen.capStyle() == Qt::FlatCap)
+ pen.setCapStyle(Qt::SquareCap);
+
+ for (int i = 0; i < pointCount; ++i, ++points) {
+ VGfloat coords[4];
+ if (d->simpleTransform) {
+ coords[0] = points->x();
+ coords[1] = points->y();
+ coords[2] = coords[0];
+ coords[3] = coords[1];
+ } else {
+ QPointF p = d->transform.map(*points);
+ coords[0] = p.x();
+ coords[1] = p.y();
+ coords[2] = coords[0];
+ coords[3] = coords[1];
+ }
+ vgModifyPathCoords(d->linePath, 0, 2, coords);
+ d->stroke(d->linePath, pen);
+ }
+#else
+ QPaintEngineEx::drawPoints(points, pointCount);
+#endif
+}
+
+void QVGPaintEngine::drawPoints(const QPoint *points, int pointCount)
+{
+#if !defined(QVG_NO_MODIFY_PATH)
+ Q_D(QVGPaintEngine);
+
+ // Set up a new pen if necessary.
+ QPen pen = state()->pen;
+ if (pen.style() == Qt::NoPen)
+ return;
+ if (pen.capStyle() == Qt::FlatCap)
+ pen.setCapStyle(Qt::SquareCap);
+
+ for (int i = 0; i < pointCount; ++i, ++points) {
+ VGfloat coords[4];
+ if (d->simpleTransform) {
+ coords[0] = points->x();
+ coords[1] = points->y();
+ coords[2] = coords[0];
+ coords[3] = coords[1];
+ } else {
+ QPointF p = d->transform.map(QPointF(*points));
+ coords[0] = p.x();
+ coords[1] = p.y();
+ coords[2] = coords[0];
+ coords[3] = coords[1];
+ }
+ vgModifyPathCoords(d->linePath, 0, 2, coords);
+ d->stroke(d->linePath, pen);
+ }
+#else
+ QPaintEngineEx::drawPoints(points, pointCount);
+#endif
+}
+
+void QVGPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
+{
+ Q_D(QVGPaintEngine);
+ QVGPainterState *s = state();
+ VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD,
+ VG_PATH_DATATYPE_F,
+ 1.0f, // scale
+ 0.0f, // bias
+ pointCount + 1, // segmentCapacityHint
+ pointCount * 2, // coordCapacityHint
+ VG_PATH_CAPABILITY_ALL);
+ QVarLengthArray<VGfloat, 16> coords;
+ QVarLengthArray<VGubyte, 10> segments;
+ for (int i = 0; i < pointCount; ++i, ++points) {
+ if (d->simpleTransform) {
+ coords.append(points->x());
+ coords.append(points->y());
+ } else {
+ QPointF temp = d->transform.map(*points);
+ coords.append(temp.x());
+ coords.append(temp.y());
+ }
+ if (i == 0)
+ segments.append(VG_MOVE_TO_ABS);
+ else
+ segments.append(VG_LINE_TO_ABS);
+ }
+ if (mode != QPaintEngine::PolylineMode)
+ segments.append(VG_CLOSE_PATH);
+ vgAppendPathData(path, segments.count(),
+ segments.constData(), coords.constData());
+ switch (mode) {
+ case QPaintEngine::WindingMode:
+ d->draw(path, s->pen, s->brush, VG_NON_ZERO);
+ break;
+
+ case QPaintEngine::PolylineMode:
+ d->stroke(path, s->pen);
+ break;
+
+ default:
+ d->draw(path, s->pen, s->brush, VG_EVEN_ODD);
+ break;
+ }
+ vgDestroyPath(path);
+}
+
+void QVGPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode)
+{
+ Q_D(QVGPaintEngine);
+ QVGPainterState *s = state();
+ VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD,
+ VG_PATH_DATATYPE_F,
+ 1.0f, // scale
+ 0.0f, // bias
+ pointCount + 1, // segmentCapacityHint
+ pointCount * 2, // coordCapacityHint
+ VG_PATH_CAPABILITY_ALL);
+ QVarLengthArray<VGfloat, 16> coords;
+ QVarLengthArray<VGubyte, 10> segments;
+ for (int i = 0; i < pointCount; ++i, ++points) {
+ if (d->simpleTransform) {
+ coords.append(points->x());
+ coords.append(points->y());
+ } else {
+ QPointF temp = d->transform.map(QPointF(*points));
+ coords.append(temp.x());
+ coords.append(temp.y());
+ }
+ if (i == 0)
+ segments.append(VG_MOVE_TO_ABS);
+ else
+ segments.append(VG_LINE_TO_ABS);
+ }
+ if (mode != QPaintEngine::PolylineMode)
+ segments.append(VG_CLOSE_PATH);
+ vgAppendPathData(path, segments.count(),
+ segments.constData(), coords.constData());
+ switch (mode) {
+ case QPaintEngine::WindingMode:
+ d->draw(path, s->pen, s->brush, VG_NON_ZERO);
+ break;
+
+ case QPaintEngine::PolylineMode:
+ d->stroke(path, s->pen);
+ break;
+
+ default:
+ d->draw(path, s->pen, s->brush, VG_EVEN_ODD);
+ break;
+ }
+ vgDestroyPath(path);
+}
+
+void QVGPaintEnginePrivate::setImageOptions()
+{
+ if (opacity != 1.0f && simpleTransform) {
+ if (opacity != paintOpacity) {
+ VGfloat values[4];
+ values[0] = 1.0f;
+ values[1] = 1.0f;
+ values[2] = 1.0f;
+ values[3] = opacity;
+ vgSetParameterfv(opacityPaint, VG_PAINT_COLOR, 4, values);
+ paintOpacity = opacity;
+ }
+ if (fillPaint != opacityPaint) {
+ vgSetPaint(opacityPaint, VG_FILL_PATH);
+ fillPaint = opacityPaint;
+ }
+ setImageMode(VG_DRAW_IMAGE_MULTIPLY);
+ } else {
+ setImageMode(VG_DRAW_IMAGE_NORMAL);
+ }
+}
+
+static void drawVGImage(QVGPaintEnginePrivate *d,
+ const QRectF& r, VGImage vgImg,
+ const QSize& imageSize, const QRectF& sr)
+{
+ if (vgImg == VG_INVALID_HANDLE)
+ return;
+ VGImage child = VG_INVALID_HANDLE;
+
+ if (sr.topLeft().isNull() && sr.size() == imageSize) {
+ child = vgImg;
+ } else {
+ QRect src = sr.toRect();
+#if !defined(QT_SHIVAVG)
+ child = vgChildImage(vgImg, src.x(), src.y(), src.width(), src.height());
+#else
+ child = vgImg; // XXX: ShivaVG doesn't have vgChildImage().
+#endif
+ }
+
+ QTransform transform(d->imageTransform);
+ VGfloat scaleX = sr.width() == 0.0f ? 0.0f : r.width() / sr.width();
+ VGfloat scaleY = sr.height() == 0.0f ? 0.0f : r.height() / sr.height();
+ transform.translate(r.x(), r.y());
+ transform.scale(scaleX, scaleY);
+ d->setTransform(VG_MATRIX_IMAGE_USER_TO_SURFACE, transform);
+
+ d->setImageOptions();
+ vgDrawImage(child);
+
+ if(child != vgImg)
+ vgDestroyImage(child);
+}
+
+static void drawVGImage(QVGPaintEnginePrivate *d,
+ const QPointF& pos, VGImage vgImg)
+{
+ if (vgImg == VG_INVALID_HANDLE)
+ return;
+
+ QTransform transform(d->imageTransform);
+ transform.translate(pos.x(), pos.y());
+ d->setTransform(VG_MATRIX_IMAGE_USER_TO_SURFACE, transform);
+
+ d->setImageOptions();
+ vgDrawImage(vgImg);
+}
+
+// Used by qpixmapfilter_vg.cpp to draw filtered VGImage's.
+void qt_vg_drawVGImage(QPainter *painter, const QPointF& pos, VGImage vgImg)
+{
+ QVGPaintEngine *engine =
+ static_cast<QVGPaintEngine *>(painter->paintEngine());
+ drawVGImage(engine->vgPrivate(), pos, vgImg);
+}
+
+void QVGPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
+{
+ QPixmapData *pd = pm.pixmapData();
+ if (pd->classId() == QPixmapData::OpenVGClass) {
+ Q_D(QVGPaintEngine);
+ QVGPixmapData *vgpd = static_cast<QVGPixmapData *>(pd);
+ if (!vgpd->isValid())
+ return;
+ if (d->simpleTransform)
+ drawVGImage(d, r, vgpd->toVGImage(), vgpd->size(), sr);
+ else
+ drawVGImage(d, r, vgpd->toVGImage(d->opacity), vgpd->size(), sr);
+ } else {
+ drawImage(r, *(pd->buffer()), sr, Qt::AutoColor);
+ }
+}
+
+void QVGPaintEngine::drawPixmap(const QPointF &pos, const QPixmap &pm)
+{
+ QPixmapData *pd = pm.pixmapData();
+ if (pd->classId() == QPixmapData::OpenVGClass) {
+ Q_D(QVGPaintEngine);
+ QVGPixmapData *vgpd = static_cast<QVGPixmapData *>(pd);
+ if (!vgpd->isValid())
+ return;
+ if (d->simpleTransform)
+ drawVGImage(d, pos, vgpd->toVGImage());
+ else
+ drawVGImage(d, pos, vgpd->toVGImage(d->opacity));
+ } else {
+ drawImage(pos, *(pd->buffer()));
+ }
+}
+
+void QVGPaintEngine::drawImage
+ (const QRectF &r, const QImage &image, const QRectF &sr,
+ Qt::ImageConversionFlags flags)
+{
+ Q_D(QVGPaintEngine);
+ VGImage vgImg;
+ if (d->simpleTransform || d->opacity == 1.0f)
+ vgImg = toVGImageSubRect(image, sr.toRect(), flags);
+ else
+ vgImg = toVGImageWithOpacitySubRect(image, d->opacity, sr.toRect());
+ if (vgImg != VG_INVALID_HANDLE) {
+ if (r.size() == sr.size()) {
+ drawVGImage(d, r.topLeft(), vgImg);
+ } else {
+ drawVGImage(d, r, vgImg, sr.size().toSize(),
+ QRectF(QPointF(0, 0), sr.size()));
+ }
+ } else {
+ // Monochrome images need to use the vgChildImage() path.
+ vgImg = toVGImage(image, flags);
+ drawVGImage(d, r, vgImg, image.size(), sr);
+ }
+ vgDestroyImage(vgImg);
+}
+
+void QVGPaintEngine::drawImage(const QPointF &pos, const QImage &image)
+{
+ Q_D(QVGPaintEngine);
+ VGImage vgImg;
+ if (d->simpleTransform || d->opacity == 1.0f)
+ vgImg = toVGImage(image);
+ else
+ vgImg = toVGImageWithOpacity(image, d->opacity);
+ drawVGImage(d, pos, vgImg);
+ vgDestroyImage(vgImg);
+}
+
+void QVGPaintEngine::drawTiledPixmap
+ (const QRectF &r, const QPixmap &pixmap, const QPointF &s)
+{
+ QBrush brush(state()->pen.color(), pixmap);
+ QTransform xform;
+ xform.translate(-s.x(), -s.y());
+ brush.setTransform(xform);
+ fillRect(r, brush);
+}
+
+QVGFontEngineCleaner::QVGFontEngineCleaner(QVGPaintEnginePrivate *d)
+ : QObject(), d_ptr(d)
+{
+}
+
+QVGFontEngineCleaner::~QVGFontEngineCleaner()
+{
+}
+
+void QVGFontEngineCleaner::fontEngineDestroyed()
+{
+#if !defined(QVG_NO_DRAW_GLYPHS)
+ QFontEngine *engine = static_cast<QFontEngine *>(sender());
+ QVGFontCache::Iterator it = d_ptr->fontCache.find(engine);
+ if (it != d_ptr->fontCache.end()) {
+ delete it.value();
+ d_ptr->fontCache.erase(it);
+ }
+#endif
+}
+
+#if !defined(QVG_NO_DRAW_GLYPHS)
+
+QVGFontGlyphCache::QVGFontGlyphCache()
+{
+ font = vgCreateFont(0);
+ scaleX = scaleY = 0.0;
+ memset(cachedGlyphsMask, 0, sizeof(cachedGlyphsMask));
+}
+
+QVGFontGlyphCache::~QVGFontGlyphCache()
+{
+ if (font != VG_INVALID_HANDLE)
+ vgDestroyFont(font);
+}
+
+void QVGFontGlyphCache::setScaleFromText(const QTextItemInt &ti)
+{
+ QFontInfo fi(ti.font());
+ qreal pixelSize = fi.pixelSize();
+ qreal emSquare = ti.fontEngine->properties().emSquare.toReal();
+ scaleX = scaleY = static_cast<VGfloat>(pixelSize / emSquare);
+}
+
+void QVGFontGlyphCache::cacheGlyphs
+ (QVGPaintEnginePrivate *d, const QTextItemInt &ti,
+ const QVarLengthArray<glyph_t> &glyphs)
+{
+ VGfloat origin[2];
+ VGfloat escapement[2];
+ const glyph_t *g = glyphs.constData();
+ int count = glyphs.size();
+ glyph_metrics_t metrics;
+ // Some Qt font engines don't set yoff in getUnscaledGlyph().
+ // Zero the metric structure so that everything has a default value.
+ memset(&metrics, 0, sizeof(metrics));
+ while (count-- > 0) {
+ // Skip this glyph if we have already cached it before.
+ glyph_t glyph = *g++;
+ if (glyph < 256) {
+ if ((cachedGlyphsMask[glyph / 32] & (1 << (glyph % 32))) != 0)
+ continue;
+ cachedGlyphsMask[glyph / 32] |= (1 << (glyph % 32));
+ } else if (cachedGlyphs.contains(glyph)) {
+ continue;
+ } else {
+ cachedGlyphs.insert(glyph);
+ }
+#if !defined(QVG_NO_IMAGE_GLYPHS)
+ Q_UNUSED(d);
+ QImage scaledImage = ti.fontEngine->alphaMapForGlyph(glyph);
+ VGImage vgImage = VG_INVALID_HANDLE;
+ metrics = ti.fontEngine->boundingBox(glyph);
+ if (!scaledImage.isNull()) { // Not a space character
+ // The QPF implementation of alphaMapForGlyph() uses the color
+ // RGBA = (value, value, value, 255) instead of the color
+ // RGBA = (0, 0, 0, value) that the other font engines use.
+ // We modify the image colors to rectify this situation.
+ QFontEngine::Type type = ti.fontEngine->type();
+ if (type == QFontEngine::QPF1 || type == QFontEngine::QPF2) {
+ if (scaledImage.format() == QImage::Format_Indexed8) {
+ for (int i = 0; i < 256; ++i)
+ scaledImage.setColor(i, qRgba(0, 0, 0, i));
+ } else if (scaledImage.format() == QImage::Format_Mono) {
+ scaledImage.setColor(0, qRgba(0, 0, 0, 0));
+ scaledImage.setColor(1, qRgba(0, 0, 0, 255));
+ }
+ }
+ if (scaledImage.format() == QImage::Format_Indexed8) {
+ vgImage = vgCreateImage(VG_A_8, scaledImage.width(), scaledImage.height(), VG_IMAGE_QUALITY_FASTER);
+ vgImageSubData(vgImage, scaledImage.bits(), scaledImage.bytesPerLine(), VG_A_8, 0, 0, scaledImage.width(), scaledImage.height());
+ } else if (scaledImage.format() == QImage::Format_Mono) {
+ QImage img = scaledImage.convertToFormat(QImage::Format_Indexed8);
+ vgImage = vgCreateImage(VG_A_8, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
+ vgImageSubData(vgImage, img.bits(), img.bytesPerLine(), VG_A_8, 0, 0, img.width(), img.height());
+ } else {
+ QImage img = scaledImage.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ vgImage = vgCreateImage(VG_sARGB_8888_PRE, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
+ vgImageSubData(vgImage, img.bits(), img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0, img.width(), img.height());
+ }
+ }
+ origin[0] = -metrics.x.toReal() + 0.5f;
+ origin[1] = -metrics.y.toReal() + 0.5f;
+ escapement[0] = metrics.xoff.toReal();
+ escapement[1] = metrics.yoff.toReal();
+ vgSetGlyphToImage(font, glyph, vgImage, origin, escapement);
+ vgDestroyImage(vgImage); // Reduce reference count.
+#else
+ // Calculate the path for the glyph and cache it.
+ QPainterPath path;
+ ti.fontEngine->getUnscaledGlyph(glyph, &path, &metrics);
+ VGPath vgPath;
+ if (!path.isEmpty()) {
+ vgPath = d->painterPathToVGPath(path);
+ } else {
+ // Probably a "space" character with no visible outline.
+ vgPath = VG_INVALID_HANDLE;
+ }
+ origin[0] = 0;
+ origin[1] = 0;
+ escapement[0] = metrics.xoff.toReal();
+ escapement[1] = metrics.yoff.toReal();
+ vgSetGlyphToPath(font, glyph, vgPath, VG_FALSE, origin, escapement);
+ vgDestroyPath(vgPath); // Reduce reference count.
+#endif // !defined(QVG_NO_IMAGE_GLYPHS)
+ }
+}
+
+#endif // !defined(QVG_NO_DRAW_GLYPHS)
+
+void QVGPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
+{
+#if !defined(QVG_NO_DRAW_GLYPHS)
+ Q_D(QVGPaintEngine);
+ const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
+
+ // If we are not using a simple transform, then fall back
+ // to the default Qt path stroking algorithm.
+ if (!d->simpleTransform) {
+ QPaintEngineEx::drawTextItem(p, textItem);
+ return;
+ }
+
+ // Get the glyphs and positions associated with the text item.
+ QVarLengthArray<QFixedPoint> positions;
+ QVarLengthArray<glyph_t> glyphs;
+ QTransform matrix = d->transform;
+ matrix.translate(p.x(), p.y());
+ ti.fontEngine->getGlyphPositions
+ (ti.glyphs, matrix, ti.flags, glyphs, positions);
+
+ // Find the glyph cache for this font.
+ QVGFontCache::ConstIterator it = d->fontCache.constFind(ti.fontEngine);
+ QVGFontGlyphCache *glyphCache;
+ if (it != d->fontCache.constEnd()) {
+ glyphCache = it.value();
+ } else {
+ glyphCache = new QVGFontGlyphCache();
+ if (glyphCache->font == VG_INVALID_HANDLE) {
+ qWarning("QVGPaintEngine::drawTextItem: OpenVG fonts are not supported by the OpenVG engine");
+ delete glyphCache;
+ QPaintEngineEx::drawTextItem(p, textItem);
+ return;
+ }
+ glyphCache->setScaleFromText(ti);
+ d->fontCache.insert(ti.fontEngine, glyphCache);
+ if (!d->fontEngineCleaner)
+ d->fontEngineCleaner = new QVGFontEngineCleaner(d);
+ QObject::connect(ti.fontEngine, SIGNAL(destroyed()),
+ d->fontEngineCleaner, SLOT(fontEngineDestroyed()));
+ }
+
+ // Set the transformation to use for drawing the current glyphs.
+ QTransform glyphTransform(d->pathTransform);
+ glyphTransform.translate(p.x(), p.y());
+#if defined(QVG_NO_IMAGE_GLYPHS)
+ glyphTransform.scale(glyphCache->scaleX, glyphCache->scaleY);
+#endif
+ d->setTransform(VG_MATRIX_GLYPH_USER_TO_SURFACE, glyphTransform);
+
+ // Add the glyphs from the text item into the glyph cache.
+ glyphCache->cacheGlyphs(d, ti, glyphs);
+
+ // Set the glyph drawing origin.
+ VGfloat origin[2];
+ origin[0] = 0;
+ origin[1] = 0;
+ vgSetfv(VG_GLYPH_ORIGIN, 2, origin);
+
+ // Fast anti-aliasing for paths, better for images.
+#if !defined(QVG_NO_IMAGE_GLYPHS)
+ d->setImageQuality(VG_IMAGE_QUALITY_BETTER);
+ d->setImageMode(VG_DRAW_IMAGE_STENCIL);
+#else
+ d->setRenderingQuality(VG_RENDERING_QUALITY_FASTER);
+#endif
+
+ // Draw the glyphs. We need to fill with the brush associated with
+ // the Qt pen, not the Qt brush.
+ d->ensureBrush(state()->pen.brush());
+ vgDrawGlyphs(glyphCache->font, glyphs.size(), (VGuint*)glyphs.data(),
+ NULL, NULL, VG_FILL_PATH, VG_TRUE);
+#else
+ // OpenGL 1.0 does not have support for VGFont and glyphs,
+ // so fall back to the default Qt path stroking algorithm.
+ QPaintEngineEx::drawTextItem(p, textItem);
+#endif
+}
+
+void QVGPaintEngine::setState(QPainterState *s)
+{
+ Q_D(QVGPaintEngine);
+ QPaintEngineEx::setState(s);
+ QVGPainterState *ps = static_cast<QVGPainterState *>(s);
+ if (ps->isNew) {
+ // Newly created state object. The call to setState()
+ // will either be followed by a call to begin(), or we are
+ // setting the state as part of a save().
+ ps->isNew = false;
+ } else {
+ // This state object was set as part of a restore().
+ restoreState(d->dirty);
+ d->dirty = ps->savedDirty;
+ }
+}
+
+// Called from QPaintEngine::syncState() to force a state flush.
+// This should be called before and after raw VG operations.
+void QVGPaintEngine::updateState(const QPaintEngineState &state)
+{
+ Q_UNUSED(state);
+ Q_D(QVGPaintEngine);
+
+ if (!(d->rawVG)) {
+ // About to enter raw VG mode: flush pending changes and make
+ // sure that all matrices are set to the current transformation.
+ QVGPainterState *s = this->state();
+ d->ensurePen(s->pen);
+ d->ensureBrush(s->brush);
+ d->ensurePathTransform();
+ d->setTransform(VG_MATRIX_IMAGE_USER_TO_SURFACE, d->imageTransform);
+#if !defined(QVG_NO_DRAW_GLYPHS)
+ d->setTransform(VG_MATRIX_GLYPH_USER_TO_SURFACE, d->pathTransform);
+#endif
+ d->rawVG = true;
+ } else {
+ // Exiting raw VG mode: force all state values to be
+ // explicitly set on the VG engine to undo any changes
+ // that were made by the raw VG function calls.
+ QPaintEngine::DirtyFlags dirty = d->dirty;
+ d->clearModes();
+ d->forcePenChange = true;
+ d->forceBrushChange = true;
+ d->penType = (VGPaintType)0;
+ d->brushType = (VGPaintType)0;
+ d->clearColor = QColor();
+ d->fillPaint = d->brushPaint;
+ restoreState(QPaintEngine::AllDirty);
+ d->dirty = dirty;
+ d->rawVG = false;
+ vgSetPaint(d->penPaint, VG_STROKE_PATH);
+ vgSetPaint(d->brushPaint, VG_FILL_PATH);
+ }
+}
+
+QPixmapFilter *QVGPaintEngine::createPixmapFilter(int type) const
+{
+#if !defined(QT_SHIVAVG)
+ if (type == QPixmapFilter::ConvolutionFilter)
+ return new QVGPixmapConvolutionFilter;
+ else if (type == QPixmapFilter::ColorizeFilter)
+ return new QVGPixmapColorizeFilter;
+ else if (type == QPixmapFilter::DropShadowFilter)
+ return new QVGPixmapDropShadowFilter;
+ else
+#endif
+ return QPaintEngineEx::createPixmapFilter(type);
+}
+
+void QVGPaintEngine::restoreState(QPaintEngine::DirtyFlags dirty)
+{
+ Q_D(QVGPaintEngine);
+
+ // Restore the pen, brush, and other settings.
+ if ((dirty & QPaintEngine::DirtyBrushOrigin) != 0)
+ brushOriginChanged();
+ d->fillRule = 0;
+ if ((dirty & QPaintEngine::DirtyOpacity) != 0)
+ opacityChanged();
+ if ((dirty & QPaintEngine::DirtyTransform) != 0)
+ transformChanged();
+ if ((dirty & QPaintEngine::DirtyCompositionMode) != 0)
+ compositionModeChanged();
+ if ((dirty & QPaintEngine::DirtyHints) != 0)
+ renderHintsChanged();
+ if ((dirty & (QPaintEngine::DirtyClipRegion |
+ QPaintEngine::DirtyClipPath |
+ QPaintEngine::DirtyClipEnabled)) != 0) {
+ d->maskValid = false;
+ d->maskIsSet = false;
+ d->maskRect = QRect();
+ clipEnabledChanged();
+ }
+
+#if defined(QVG_SCISSOR_CLIP)
+ if ((dirty & (QPaintEngine::DirtyClipRegion |
+ QPaintEngine::DirtyClipPath |
+ QPaintEngine::DirtyClipEnabled)) == 0) {
+ updateScissor();
+ }
+#else
+ updateScissor();
+#endif
+}
+
+#if !defined(QVG_NO_SINGLE_CONTEXT) && !defined(QT_NO_EGL)
+
+QVGCompositionHelper::QVGCompositionHelper()
+{
+ d = qt_vg_create_paint_engine()->vgPrivate();
+}
+
+QVGCompositionHelper::~QVGCompositionHelper()
+{
+}
+
+void QVGCompositionHelper::startCompositing(const QSize& screenSize)
+{
+ this->screenSize = screenSize;
+ clearScissor();
+ d->setBlendMode(VG_BLEND_SRC_OVER);
+}
+
+void QVGCompositionHelper::endCompositing()
+{
+ clearScissor();
+}
+
+void QVGCompositionHelper::blitWindow
+ (QVGEGLWindowSurfacePrivate *surface, const QRect& rect,
+ const QPoint& topLeft, int opacity)
+{
+ // Get the VGImage that is acting as a back buffer for the window.
+ VGImage image = surface->surfaceImage();
+ if (image == VG_INVALID_HANDLE)
+ return;
+ QSize imageSize = surface->surfaceSize();
+
+ // Determine which sub rectangle of the window to draw.
+ QRect sr = rect.translated(-topLeft);
+
+ if (opacity >= 255) {
+ // Fully opaque: use vgSetPixels() to directly copy the sub-region.
+ int y = screenSize.height() - (rect.bottom() + 1);
+ vgSetPixels(rect.x(), y, image, sr.x(),
+ imageSize.height() - (sr.y() + sr.height()),
+ sr.width(), sr.height());
+ } else {
+ // Extract the child image that we want to draw.
+ VGImage child;
+ if (sr.topLeft().isNull() && sr.size() == imageSize)
+ child = image;
+ else {
+ child = vgChildImage
+ (image, sr.x(), imageSize.height() - (sr.y() + sr.height()),
+ sr.width(), sr.height());
+ }
+
+ // Set the image transform.
+ QTransform transform;
+ int y = screenSize.height() - (rect.bottom() + 1);
+ transform.translate(rect.x() + 0.5f, y + 0.5f);
+ d->setTransform(VG_MATRIX_IMAGE_USER_TO_SURFACE, transform);
+
+ // Enable opacity for image drawing if necessary.
+ if (opacity < 255) {
+ if (opacity != d->paintOpacity) {
+ VGfloat values[4];
+ values[0] = 1.0f;
+ values[1] = 1.0f;
+ values[2] = 1.0f;
+ values[3] = ((VGfloat)opacity) / 255.0f;
+ vgSetParameterfv(d->opacityPaint, VG_PAINT_COLOR, 4, values);
+ d->paintOpacity = values[3];
+ }
+ if (d->fillPaint != d->opacityPaint) {
+ vgSetPaint(d->opacityPaint, VG_FILL_PATH);
+ d->fillPaint = d->opacityPaint;
+ }
+ d->setImageMode(VG_DRAW_IMAGE_MULTIPLY);
+ } else {
+ d->setImageMode(VG_DRAW_IMAGE_NORMAL);
+ }
+
+ // Draw the child image.
+ vgDrawImage(child);
+
+ // Destroy the child image.
+ if(child != image)
+ vgDestroyImage(child);
+ }
+}
+
+static void fillBackgroundRect(const QRect& rect, QVGPaintEnginePrivate *d)
+{
+ VGfloat coords[8];
+ coords[0] = rect.x();
+ coords[1] = rect.y();
+ coords[2] = rect.x() + rect.width();
+ coords[3] = coords[1];
+ coords[4] = coords[2];
+ coords[5] = rect.y() + rect.height();
+ coords[6] = coords[0];
+ coords[7] = coords[5];
+#if !defined(QVG_NO_MODIFY_PATH)
+ vgModifyPathCoords(d->rectPath, 0, 4, coords);
+ vgDrawPath(d->rectPath, VG_FILL_PATH);
+#else
+ Q_UNUSED(d);
+ VGPath rectPath = vgCreatePath
+ (VG_PATH_FORMAT_STANDARD,
+ VG_PATH_DATATYPE_F,
+ 1.0f, // scale
+ 0.0f, // bias
+ 5, // segmentCapacityHint
+ 8, // coordCapacityHint
+ VG_PATH_CAPABILITY_ALL);
+ static VGubyte const segments[5] = {
+ VG_MOVE_TO_ABS,
+ VG_LINE_TO_ABS,
+ VG_LINE_TO_ABS,
+ VG_LINE_TO_ABS,
+ VG_CLOSE_PATH
+ };
+ vgAppendPathData(rectPath, 5, segments, coords);
+ vgDrawPath(rectPath, VG_FILL_PATH);
+ vgDestroyPath(rectPath);
+#endif
+}
+
+void QVGCompositionHelper::fillBackground
+ (const QRegion& region, const QBrush& brush)
+{
+ // Set the path transform to the default viewport transformation.
+ VGfloat devh = screenSize.height() - 1;
+ QTransform viewport(1.0f, 0.0f, 0.0f,
+ 0.0f, -1.0f, 0.0f,
+ 0.5f, devh + 0.5f, 1.0f);
+ d->setTransform(VG_MATRIX_PATH_USER_TO_SURFACE, viewport);
+
+ // Set the brush to use to fill the background.
+ d->ensureBrush(brush);
+ d->setFillRule(VG_EVEN_ODD);
+
+ if (region.numRects() == 1) {
+ fillBackgroundRect(region.boundingRect(), d);
+ } else {
+ const QVector<QRect> rects = region.rects();
+ for (int i = 0; i < rects.size(); ++i)
+ fillBackgroundRect(rects.at(i), d);
+ }
+
+ // We will need to reset the path transform during the next paint.
+ d->pathTransformSet = false;
+}
+
+void QVGCompositionHelper::drawCursorImage
+ (const QImage& image, const QPoint& offset)
+{
+ QImage img = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+
+ VGImage vgImg = vgCreateImage
+ (VG_sARGB_8888_PRE, img.width(), img.height(),
+ VG_IMAGE_QUALITY_FASTER);
+ vgImageSubData
+ (vgImg, img.bits() + img.bytesPerLine() * (img.height() - 1),
+ -(img.bytesPerLine()), VG_sARGB_8888_PRE, 0, 0,
+ img.width(), img.height());
+
+ QTransform transform;
+ int y = screenSize.height() - (offset.y() + img.height());
+ transform.translate(offset.x() + 0.5f, y + 0.5f);
+ d->setTransform(VG_MATRIX_IMAGE_USER_TO_SURFACE, transform);
+
+ d->setImageMode(VG_DRAW_IMAGE_NORMAL);
+ vgDrawImage(vgImg);
+
+ vgDestroyImage(vgImg);
+}
+
+void QVGCompositionHelper::drawCursorPixmap
+ (const QPixmap& pixmap, const QPoint& offset)
+{
+ QPixmapData *pd = pixmap.pixmapData();
+ if (pd->classId() == QPixmapData::OpenVGClass) {
+ QVGPixmapData *vgpd = static_cast<QVGPixmapData *>(pd);
+ if (vgpd->isValid()) {
+ VGfloat devh = screenSize.height() - 1;
+ QTransform transform(1.0f, 0.0f, 0.0f,
+ 0.0f, -1.0f, 0.0f,
+ 0.5f, devh + 0.5f, 1.0f);
+ transform.translate(offset.x(), offset.y());
+ d->setTransform(VG_MATRIX_IMAGE_USER_TO_SURFACE, transform);
+
+ d->setImageMode(VG_DRAW_IMAGE_NORMAL);
+ vgDrawImage(vgpd->toVGImage());
+ return;
+ }
+ }
+
+ drawCursorImage(pixmap.toImage(), offset);
+}
+
+void QVGCompositionHelper::setScissor(const QRegion& region)
+{
+ QVector<QRect> rects = region.rects();
+ int count = rects.count();
+ if (count > d->maxScissorRects)
+ count = d->maxScissorRects;
+ QVarLengthArray<VGint> params(count * 4);
+ int height = screenSize.height();
+ for (int i = 0; i < count; ++i) {
+ params[i * 4 + 0] = rects[i].x();
+ params[i * 4 + 1] = height - rects[i].y() - rects[i].height();
+ params[i * 4 + 2] = rects[i].width();
+ params[i * 4 + 3] = rects[i].height();
+ }
+
+ vgSetiv(VG_SCISSOR_RECTS, count * 4, params.data());
+ vgSeti(VG_SCISSORING, VG_TRUE);
+ d->scissorActive = true;
+ d->scissorRegion = region;
+}
+
+void QVGCompositionHelper::clearScissor()
+{
+ if (d->scissorActive) {
+ vgSeti(VG_SCISSORING, VG_FALSE);
+ d->scissorActive = false;
+ }
+}
+
+#endif // !QVG_NO_SINGLE_CONTEXT && !QT_NO_EGL
+
+VGImageFormat qt_vg_image_to_vg_format(QImage::Format format)
+{
+ switch (format) {
+ case QImage::Format_MonoLSB:
+ return VG_BW_1;
+ case QImage::Format_ARGB32_Premultiplied:
+ return VG_sARGB_8888_PRE;
+ case QImage::Format_RGB32:
+ return VG_sXRGB_8888;
+ case QImage::Format_ARGB32:
+ return VG_sARGB_8888;
+ case QImage::Format_RGB16:
+ return VG_sRGB_565;
+ case QImage::Format_ARGB4444_Premultiplied:
+ return VG_sARGB_4444;
+ default: break;
+ }
+ return VG_sARGB_8888; // XXX
+}
+
+QT_END_NAMESPACE
+
+#include "qpaintengine_vg.moc"
diff --git a/src/openvg/qpaintengine_vg_p.h b/src/openvg/qpaintengine_vg_p.h
new file mode 100644
index 0000000..a390c80
--- /dev/null
+++ b/src/openvg/qpaintengine_vg_p.h
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPAINTENGINE_VG_P_H
+#define QPAINTENGINE_VG_P_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 <QtGui/private/qpaintengineex_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QVGPaintEnginePrivate;
+class QPixmapData;
+class QVGEGLWindowSurfacePrivate;
+
+class Q_OPENVG_EXPORT QVGPainterState : public QPainterState
+{
+public:
+ QVGPainterState(QVGPainterState& other);
+ QVGPainterState();
+ ~QVGPainterState();
+
+ bool isNew;
+ QRegion clipRegion;
+ QPaintEngine::DirtyFlags savedDirty;
+};
+
+class Q_OPENVG_EXPORT QVGPaintEngine : public QPaintEngineEx
+{
+ Q_DECLARE_PRIVATE(QVGPaintEngine)
+public:
+ QVGPaintEngine();
+ ~QVGPaintEngine();
+
+ Type type() const { return OpenVG; }
+
+ QPainterState *createState(QPainterState *orig) const;
+
+ bool begin(QPaintDevice *pdev);
+ bool end();
+
+ void draw(const QVectorPath &path);
+ void fill(const QVectorPath &path, const QBrush &brush);
+ void stroke(const QVectorPath &path, const QPen &pen);
+
+ void clip(const QVectorPath &path, Qt::ClipOperation op);
+ void clip(const QRect &rect, Qt::ClipOperation op);
+ void clip(const QRegion &region, Qt::ClipOperation op);
+ void clip(const QPainterPath &path, Qt::ClipOperation op);
+
+ void clipEnabledChanged();
+ void penChanged();
+ void brushChanged();
+ void brushOriginChanged();
+ void opacityChanged();
+ void compositionModeChanged();
+ void renderHintsChanged();
+ void transformChanged();
+
+ void fillRect(const QRectF &rect, const QBrush &brush);
+ void fillRect(const QRectF &rect, const QColor &color);
+
+ void drawRects(const QRect *rects, int rectCount);
+ void drawRects(const QRectF *rects, int rectCount);
+
+ void drawLines(const QLine *lines, int lineCount);
+ void drawLines(const QLineF *lines, int lineCount);
+
+ void drawEllipse(const QRectF &r);
+ void drawEllipse(const QRect &r);
+
+ void drawPath(const QPainterPath &path);
+
+ void drawPoints(const QPointF *points, int pointCount);
+ void drawPoints(const QPoint *points, int pointCount);
+
+ void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode);
+ void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode);
+
+ void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr);
+ void drawPixmap(const QPointF &pos, const QPixmap &pm);
+
+ void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr,
+ Qt::ImageConversionFlags flags = Qt::AutoColor);
+ void drawImage(const QPointF &pos, const QImage &image);
+
+ void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s);
+
+ void drawTextItem(const QPointF &p, const QTextItem &textItem);
+
+ void setState(QPainterState *s);
+ QVGPainterState *state() { return static_cast<QVGPainterState *>(QPaintEngineEx::state()); }
+ const QVGPainterState *state() const { return static_cast<const QVGPainterState *>(QPaintEngineEx::state()); }
+
+ void updateState(const QPaintEngineState &state);
+
+ QPixmapFilter *createPixmapFilter(int type) const;
+
+ QVGPaintEnginePrivate *vgPrivate() { Q_D(QVGPaintEngine); return d; }
+
+protected:
+ QVGPaintEngine(QVGPaintEnginePrivate &data);
+
+private:
+ void restoreState(QPaintEngine::DirtyFlags dirty);
+ void updateScissor();
+ QRegion defaultClipRegion();
+ bool isDefaultClipRegion(const QRegion& region);
+ 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
new file mode 100644
index 0000000..90fd9a5
--- /dev/null
+++ b/src/openvg/qpixmapdata_vg.cpp
@@ -0,0 +1,344 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qpixmapdata_vg_p.h"
+#include "qpaintengine_vg_p.h"
+#include <QtGui/private/qdrawhelper_p.h>
+#include "qvg_p.h"
+
+QT_BEGIN_NAMESPACE
+
+static int qt_vg_pixmap_serial = 0;
+
+QVGPixmapData::QVGPixmapData(PixelType type)
+ : QPixmapData(type, OpenVGClass)
+{
+ Q_ASSERT(type == QPixmapData::PixmapType);
+ vgImage = VG_INVALID_HANDLE;
+ vgImageOpacity = VG_INVALID_HANDLE;
+ cachedOpacity = 1.0f;
+ recreate = true;
+#if !defined(QT_NO_EGL)
+ context = 0;
+#endif
+ setSerialNumber(++qt_vg_pixmap_serial);
+}
+
+QVGPixmapData::~QVGPixmapData()
+{
+ if (vgImage != VG_INVALID_HANDLE) {
+ // We need to have a context current to destroy the image.
+#if !defined(QT_NO_EGL)
+ if (context->isCurrent()) {
+ vgDestroyImage(vgImage);
+ if (vgImageOpacity != VG_INVALID_HANDLE)
+ vgDestroyImage(vgImageOpacity);
+ } else {
+ // We don't currently have a widget surface active, but we
+ // need a surface to make the context current. So use the
+ // shared pbuffer surface instead.
+ qt_vg_make_current(context, qt_vg_shared_surface());
+ vgDestroyImage(vgImage);
+ if (vgImageOpacity != VG_INVALID_HANDLE)
+ vgDestroyImage(vgImageOpacity);
+ qt_vg_done_current(context);
+ context->setSurface(EGL_NO_SURFACE);
+ }
+#else
+ vgDestroyImage(vgImage);
+ if (vgImageOpacity != VG_INVALID_HANDLE)
+ vgDestroyImage(vgImageOpacity);
+ } else {
+#endif
+ }
+#if !defined(QT_NO_EGL)
+ if (context)
+ qt_vg_destroy_context(context);
+#endif
+}
+
+bool QVGPixmapData::isValid() const
+{
+ return (w > 0 && h > 0);
+}
+
+void QVGPixmapData::resize(int wid, int ht)
+{
+ if (w == wid && h == ht)
+ return;
+
+ w = wid;
+ h = ht;
+ d = 32; // We always use ARGB_Premultiplied for VG pixmaps.
+ is_null = (w <= 0 || h <= 0);
+ source = QImage();
+ recreate = true;
+
+ setSerialNumber(++qt_vg_pixmap_serial);
+}
+
+void QVGPixmapData::fromImage
+ (const QImage &image, Qt::ImageConversionFlags flags)
+{
+ if (image.size() == QSize(w, h))
+ setSerialNumber(++qt_vg_pixmap_serial);
+ else
+ resize(image.width(), image.height());
+ source = image.convertToFormat(sourceFormat(), flags);
+ recreate = true;
+}
+
+void QVGPixmapData::fill(const QColor &color)
+{
+ if (!isValid())
+ return;
+
+ if (source.isNull())
+ source = QImage(w, h, sourceFormat());
+
+ if (source.depth() == 1) {
+ // Pick the best approximate color in the image's colortable.
+ int gray = qGray(color.rgba());
+ if (qAbs(qGray(source.color(0)) - gray) < qAbs(qGray(source.color(1)) - gray))
+ source.fill(0);
+ else
+ source.fill(1);
+ } else {
+ source.fill(PREMUL(color.rgba()));
+ }
+
+ // Re-upload the image to VG the next time toVGImage() is called.
+ recreate = true;
+}
+
+bool QVGPixmapData::hasAlphaChannel() const
+{
+ if (!source.isNull())
+ return source.hasAlphaChannel();
+ else
+ return isValid();
+}
+
+void QVGPixmapData::setAlphaChannel(const QPixmap &alphaChannel)
+{
+ forceToImage();
+ source.setAlphaChannel(alphaChannel.toImage());
+}
+
+QImage QVGPixmapData::toImage() const
+{
+ if (!isValid())
+ return QImage();
+
+ if (source.isNull()) {
+ source = QImage(w, h, sourceFormat());
+ recreate = true;
+ }
+
+ return source;
+}
+
+QImage *QVGPixmapData::buffer()
+{
+ forceToImage();
+ return &source;
+}
+
+QPaintEngine* QVGPixmapData::paintEngine() const
+{
+ // If the application wants to paint into the QPixmap, we first
+ // force it to QImage format and then paint into that.
+ // This is simpler than juggling multiple VG contexts.
+ const_cast<QVGPixmapData *>(this)->forceToImage();
+ return source.paintEngine();
+}
+
+VGImage QVGPixmapData::toVGImage()
+{
+ if (!isValid())
+ return VG_INVALID_HANDLE;
+
+#if !defined(QT_NO_EGL)
+ // Increase the reference count on the shared context.
+ if (!context)
+ context = qt_vg_create_context(0);
+#endif
+
+ if (recreate) {
+ if (vgImage != VG_INVALID_HANDLE) {
+ vgDestroyImage(vgImage);
+ vgImage = VG_INVALID_HANDLE;
+ }
+ if (vgImageOpacity != VG_INVALID_HANDLE) {
+ vgDestroyImage(vgImageOpacity);
+ vgImageOpacity = VG_INVALID_HANDLE;
+ }
+ }
+
+ if (vgImage == VG_INVALID_HANDLE) {
+ vgImage = vgCreateImage
+ (VG_sARGB_8888_PRE, w, h, VG_IMAGE_QUALITY_FASTER);
+ }
+
+ if (!source.isNull() && recreate) {
+ vgImageSubData
+ (vgImage,
+ source.bits(), source.bytesPerLine(),
+ VG_sARGB_8888_PRE, 0, 0, w, h);
+ }
+
+ recreate = false;
+
+ return vgImage;
+}
+
+VGImage QVGPixmapData::toVGImage(qreal opacity)
+{
+#if !defined(QT_SHIVAVG)
+ if (!isValid())
+ return VG_INVALID_HANDLE;
+
+#if !defined(QT_NO_EGL)
+ // Increase the reference count on the shared context.
+ if (!context)
+ context = qt_vg_create_context(0);
+#endif
+
+ if (recreate) {
+ if (vgImage != VG_INVALID_HANDLE) {
+ vgDestroyImage(vgImage);
+ vgImage = VG_INVALID_HANDLE;
+ }
+ if (vgImageOpacity != VG_INVALID_HANDLE) {
+ vgDestroyImage(vgImageOpacity);
+ vgImageOpacity = VG_INVALID_HANDLE;
+ }
+ }
+
+ if (vgImage == VG_INVALID_HANDLE) {
+ vgImage = vgCreateImage
+ (VG_sARGB_8888_PRE, w, h, VG_IMAGE_QUALITY_FASTER);
+ }
+
+ if (!source.isNull() && recreate) {
+ vgImageSubData
+ (vgImage,
+ source.bits(), source.bytesPerLine(),
+ VG_sARGB_8888_PRE, 0, 0, w, h);
+ }
+
+ recreate = false;
+
+ if (opacity == 1.0f)
+ return vgImage;
+
+ if (vgImageOpacity == VG_INVALID_HANDLE || cachedOpacity != opacity) {
+ if (vgImageOpacity == VG_INVALID_HANDLE) {
+ vgImageOpacity = vgCreateImage
+ (VG_sARGB_8888_PRE, w, h, VG_IMAGE_QUALITY_FASTER);
+ }
+ VGfloat matrix[20] = {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, opacity,
+ 0.0f, 0.0f, 0.0f, 0.0f
+ };
+ vgColorMatrix(vgImageOpacity, vgImage, matrix);
+ cachedOpacity = opacity;
+ }
+
+ return vgImageOpacity;
+#else
+ // vgColorMatrix() doesn't work with ShivaVG, so ignore the opacity.
+ Q_UNUSED(opacity);
+ return toVGImage();
+#endif
+}
+
+extern int qt_defaultDpiX();
+extern int qt_defaultDpiY();
+
+int QVGPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const
+{
+ switch (metric) {
+ case QPaintDevice::PdmWidth:
+ return w;
+ case QPaintDevice::PdmHeight:
+ return h;
+ case QPaintDevice::PdmNumColors:
+ return 0;
+ case QPaintDevice::PdmDepth:
+ return d;
+ case QPaintDevice::PdmWidthMM:
+ return qRound(w * 25.4 / qt_defaultDpiX());
+ case QPaintDevice::PdmHeightMM:
+ return qRound(h * 25.4 / qt_defaultDpiY());
+ case QPaintDevice::PdmDpiX:
+ case QPaintDevice::PdmPhysicalDpiX:
+ return qt_defaultDpiX();
+ case QPaintDevice::PdmDpiY:
+ case QPaintDevice::PdmPhysicalDpiY:
+ return qt_defaultDpiY();
+ default:
+ qWarning("QVGPixmapData::metric(): Invalid metric");
+ return 0;
+ }
+}
+
+// Force the pixmap data to be in QImage format.
+void QVGPixmapData::forceToImage()
+{
+ if (!isValid())
+ return;
+
+ if (source.isNull())
+ source = QImage(w, h, sourceFormat());
+
+ recreate = true;
+}
+
+QImage::Format QVGPixmapData::sourceFormat() const
+{
+ return QImage::Format_ARGB32_Premultiplied;
+}
+
+QT_END_NAMESPACE
diff --git a/src/openvg/qpixmapdata_vg_p.h b/src/openvg/qpixmapdata_vg_p.h
new file mode 100644
index 0000000..bb019be
--- /dev/null
+++ b/src/openvg/qpixmapdata_vg_p.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPIXMAPDATA_VG_P_H
+#define QPIXMAPDATA_VG_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qpixmap_raster_p.h>
+#include "qvg_p.h"
+#if !defined(QT_NO_EGL)
+#include <QtGui/private/qegl_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QEglContext;
+
+class Q_OPENVG_EXPORT QVGPixmapData : public QPixmapData
+{
+public:
+ QVGPixmapData(PixelType type);
+ ~QVGPixmapData();
+
+ // Is this pixmap valid (i.e. non-zero in size)?
+ bool isValid() const;
+
+ void resize(int width, int height);
+ void fromImage(const QImage &image, Qt::ImageConversionFlags flags);
+
+ void fill(const QColor &color);
+ bool hasAlphaChannel() const;
+ void setAlphaChannel(const QPixmap &alphaChannel);
+ QImage toImage() const;
+ QImage *buffer();
+ QPaintEngine* paintEngine() const;
+
+ // Return the VGImage form of this pixmap, creating it if necessary.
+ // This assumes that there is a VG context current.
+ VGImage toVGImage();
+
+ // Return the VGImage form for a specific opacity setting.
+ VGImage toVGImage(qreal opacity);
+
+ QSize size() const { return QSize(w, h); }
+
+protected:
+ int metric(QPaintDevice::PaintDeviceMetric metric) const;
+
+private:
+ VGImage vgImage;
+ VGImage vgImageOpacity;
+ qreal cachedOpacity;
+ mutable QImage source;
+ mutable bool recreate;
+#if !defined(QT_NO_EGL)
+ mutable QEglContext *context;
+#endif
+
+ void forceToImage();
+ QImage::Format sourceFormat() const;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/openvg/qpixmapfilter_vg.cpp b/src/openvg/qpixmapfilter_vg.cpp
new file mode 100644
index 0000000..ff8604b
--- /dev/null
+++ b/src/openvg/qpixmapfilter_vg.cpp
@@ -0,0 +1,340 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qpixmapfilter_vg_p.h"
+#include <QtCore/qvarlengtharray.h>
+#include <QtGui/qpainter.h>
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_SHIVAVG)
+
+QVGPixmapConvolutionFilter::QVGPixmapConvolutionFilter()
+ : QPixmapConvolutionFilter()
+{
+}
+
+QVGPixmapConvolutionFilter::~QVGPixmapConvolutionFilter()
+{
+}
+
+extern void qt_vg_drawVGImage
+ (QPainter *painter, const QPointF& pos, VGImage vgImg);
+
+void QVGPixmapConvolutionFilter::draw
+ (QPainter *painter, const QPointF &dest,
+ const QPixmap &src, const QRectF &srcRect) const
+{
+ if (src.pixmapData()->classId() != QPixmapData::OpenVGClass) {
+ // The pixmap data is not an instance of QVGPixmapData, so fall
+ // back to the default convolution filter implementation.
+ QPixmapConvolutionFilter::draw(painter, dest, src, srcRect);
+ return;
+ }
+
+ QVGPixmapData *pd = static_cast<QVGPixmapData *>(src.pixmapData());
+
+ VGImage srcImage = pd->toVGImage();
+ if (srcImage == VG_INVALID_HANDLE)
+ return;
+
+ QSize size = pd->size();
+ VGImage dstImage = vgCreateImage
+ (VG_sARGB_8888_PRE, size.width(), size.height(),
+ VG_IMAGE_QUALITY_FASTER);
+ if (dstImage == VG_INVALID_HANDLE)
+ return;
+
+ int kernelWidth = rows();
+ int kernelHeight = columns();
+ const qreal *kern = convolutionKernel();
+ QVarLengthArray<VGshort> kernel;
+ for (int i = 0; i < kernelWidth; ++i) {
+ for (int j = 0; j < kernelHeight; ++j) {
+ kernel.append((VGshort)(kern[j * kernelWidth + i] * 1024.0f));
+ }
+ }
+
+ VGfloat values[4];
+ values[0] = 0.0f;
+ values[1] = 0.0f;
+ values[2] = 0.0f;
+ values[3] = 0.0f;
+ vgSetfv(VG_TILE_FILL_COLOR, 4, values);
+
+ vgConvolve(dstImage, srcImage,
+ kernelWidth, kernelHeight, 0, 0,
+ kernel.constData(), 1.0f / 1024.0f, 0.0f,
+ VG_TILE_FILL);
+
+ VGImage child = VG_INVALID_HANDLE;
+
+ if (srcRect.isNull() ||
+ (srcRect.topLeft().isNull() && srcRect.size() == size)) {
+ child = dstImage;
+ } else {
+ QRect src = srcRect.toRect();
+ child = vgChildImage(dstImage, src.x(), src.y(), src.width(), src.height());
+ }
+
+ qt_vg_drawVGImage(painter, dest, child);
+
+ if(child != dstImage)
+ vgDestroyImage(child);
+ vgDestroyImage(dstImage);
+}
+
+QVGPixmapColorizeFilter::QVGPixmapColorizeFilter()
+ : QPixmapColorizeFilter(),
+ firstTime(true)
+{
+}
+
+QVGPixmapColorizeFilter::~QVGPixmapColorizeFilter()
+{
+}
+
+void QVGPixmapColorizeFilter::draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect) const
+{
+ if (src.pixmapData()->classId() != QPixmapData::OpenVGClass) {
+ // The pixmap data is not an instance of QVGPixmapData, so fall
+ // back to the default convolution filter implementation.
+ QPixmapColorizeFilter::draw(painter, dest, src, srcRect);
+ return;
+ }
+
+ QVGPixmapData *pd = static_cast<QVGPixmapData *>(src.pixmapData());
+
+ VGImage srcImage = pd->toVGImage();
+ if (srcImage == VG_INVALID_HANDLE)
+ return;
+
+ QSize size = pd->size();
+ VGImage dstImage = vgCreateImage
+ (VG_sARGB_8888_PRE, size.width(), size.height(),
+ VG_IMAGE_QUALITY_FASTER);
+ if (dstImage == VG_INVALID_HANDLE)
+ return;
+
+ // Recompute the color matrix if the color has changed.
+ QColor c = color();
+ if (c != prevColor || firstTime) {
+ prevColor = c;
+
+ // Determine the weights for the matrix from the color.
+ VGfloat weights[3];
+ VGfloat invweights[3];
+ VGfloat alpha = c.alphaF();
+ weights[0] = c.redF() * alpha;
+ weights[1] = c.greenF() * alpha;
+ weights[2] = c.blueF() * alpha;
+ invweights[0] = 1.0f - weights[0];
+ invweights[1] = 1.0f - weights[1];
+ invweights[2] = 1.0f - weights[2];
+
+ // Grayscale weights.
+ static const VGfloat redGray = 11.0f / 32.0f;
+ static const VGfloat greenGray = 16.0f / 32.0f;
+ static const VGfloat blueGray = 1.0f - (redGray + greenGray);
+
+ matrix[0][0] = redGray * invweights[0];
+ matrix[0][1] = redGray * invweights[1];
+ matrix[0][2] = redGray * invweights[2];
+ matrix[0][3] = 0.0f;
+ matrix[1][0] = greenGray * invweights[0];
+ matrix[1][1] = greenGray * invweights[1];
+ matrix[1][2] = greenGray * invweights[2];
+ matrix[1][3] = 0.0f;
+ matrix[2][0] = blueGray * invweights[0];
+ matrix[2][1] = blueGray * invweights[1];
+ matrix[2][2] = blueGray * invweights[2];
+ matrix[2][3] = 0.0f;
+ matrix[3][0] = 0.0f;
+ matrix[3][1] = 0.0f;
+ matrix[3][2] = 0.0f;
+ matrix[3][3] = 1.0f;
+ matrix[4][0] = weights[0];
+ matrix[4][1] = weights[1];
+ matrix[4][2] = weights[2];
+ matrix[4][3] = 0.0f;
+ }
+
+ firstTime = false;
+
+ vgColorMatrix(dstImage, srcImage, matrix[0]);
+
+ VGImage child = VG_INVALID_HANDLE;
+
+ if (srcRect.isNull() ||
+ (srcRect.topLeft().isNull() && srcRect.size() == size)) {
+ child = dstImage;
+ } else {
+ QRect src = srcRect.toRect();
+ child = vgChildImage(dstImage, src.x(), src.y(), src.width(), src.height());
+ }
+
+ qt_vg_drawVGImage(painter, dest, child);
+
+ if(child != dstImage)
+ vgDestroyImage(child);
+ vgDestroyImage(dstImage);
+}
+
+QVGPixmapDropShadowFilter::QVGPixmapDropShadowFilter()
+ : QPixmapDropShadowFilter(),
+ prevRadius(0.0f),
+ kernelSize(0),
+ firstTime(true)
+{
+}
+
+QVGPixmapDropShadowFilter::~QVGPixmapDropShadowFilter()
+{
+}
+
+void QVGPixmapDropShadowFilter::draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect) const
+{
+ if (src.pixmapData()->classId() != QPixmapData::OpenVGClass) {
+ // The pixmap data is not an instance of QVGPixmapData, so fall
+ // back to the default drop shadow filter implementation.
+ QPixmapDropShadowFilter::draw(painter, dest, src, srcRect);
+ return;
+ }
+
+ QVGPixmapData *pd = static_cast<QVGPixmapData *>(src.pixmapData());
+
+ VGImage srcImage = pd->toVGImage();
+ if (srcImage == VG_INVALID_HANDLE)
+ return;
+
+ QSize size = pd->size();
+ VGImage tmpImage = vgCreateImage
+ (VG_sARGB_8888_PRE, size.width(), size.height(),
+ VG_IMAGE_QUALITY_FASTER);
+ if (tmpImage == VG_INVALID_HANDLE)
+ return;
+
+ VGImage dstImage = vgCreateImage
+ (VG_sARGB_8888_PRE, size.width(), size.height(),
+ VG_IMAGE_QUALITY_FASTER);
+ if (dstImage == VG_INVALID_HANDLE) {
+ vgDestroyImage(tmpImage);
+ return;
+ }
+
+ // Recompute the color matrix if the color has changed.
+ QColor c = color();
+ if (c != prevColor || firstTime) {
+ prevColor = c;
+
+ matrix[0][0] = 0.0f;
+ matrix[0][1] = 0.0f;
+ matrix[0][2] = 0.0f;
+ matrix[0][3] = 0.0f;
+ matrix[1][0] = 0.0f;
+ matrix[1][1] = 0.0f;
+ matrix[1][2] = 0.0f;
+ matrix[1][3] = 0.0f;
+ matrix[2][0] = 0.0f;
+ matrix[2][1] = 0.0f;
+ matrix[2][2] = 0.0f;
+ matrix[2][3] = 0.0f;
+ matrix[3][0] = c.redF();
+ matrix[3][1] = c.greenF();
+ matrix[3][2] = c.blueF();
+ matrix[3][3] = c.alphaF();
+ matrix[4][0] = 0.0f;
+ matrix[4][1] = 0.0f;
+ matrix[4][2] = 0.0f;
+ matrix[4][3] = 0.0f;
+ }
+
+ // Blacken the source image.
+ vgColorMatrix(tmpImage, srcImage, matrix[0]);
+
+ // Recompute the convolution kernel if the blur radius has changed.
+ qreal radius = blurRadius();
+ if (radius != prevRadius || firstTime) {
+ prevRadius = radius;
+ int dim = 2 * qRound(radius) + 1;
+ int size = dim * dim;
+ VGshort f = VGshort(1024.0f / size);
+ kernel.resize(size);
+ for (int i = 0; i < size; ++i)
+ kernel[i] = f;
+ kernelSize = dim;
+ }
+
+ // Apply the convolution filter using the kernel.
+ VGfloat values[4];
+ values[0] = 0.0f;
+ values[1] = 0.0f;
+ values[2] = 0.0f;
+ values[3] = 0.0f;
+ vgSetfv(VG_TILE_FILL_COLOR, 4, values);
+ vgConvolve(dstImage, tmpImage,
+ kernelSize, kernelSize, 0, 0,
+ kernel.constData(), 1.0f / 1024.0f, 0.0f,
+ VG_TILE_FILL);
+
+ firstTime = false;
+
+ VGImage child = VG_INVALID_HANDLE;
+
+ if (srcRect.isNull() ||
+ (srcRect.topLeft().isNull() && srcRect.size() == size)) {
+ child = dstImage;
+ } else {
+ QRect src = srcRect.toRect();
+ child = vgChildImage(dstImage, src.x(), src.y(), src.width(), src.height());
+ }
+
+ qt_vg_drawVGImage(painter, dest + offset(), child);
+
+ if(child != dstImage)
+ vgDestroyImage(child);
+ vgDestroyImage(tmpImage);
+ vgDestroyImage(dstImage);
+}
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/openvg/qpixmapfilter_vg_p.h b/src/openvg/qpixmapfilter_vg_p.h
new file mode 100644
index 0000000..412fb55
--- /dev/null
+++ b/src/openvg/qpixmapfilter_vg_p.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPIXMAPFILTER_VG_P_H
+#define QPIXMAPFILTER_VG_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qpixmapdata_vg_p.h"
+#include <QtGui/private/qpixmapfilter_p.h>
+#include <QtCore/qvarlengtharray.h>
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_SHIVAVG)
+
+class Q_OPENVG_EXPORT QVGPixmapConvolutionFilter : public QPixmapConvolutionFilter
+{
+public:
+ QVGPixmapConvolutionFilter();
+ ~QVGPixmapConvolutionFilter();
+
+ void draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect) const;
+};
+
+class Q_OPENVG_EXPORT QVGPixmapColorizeFilter : public QPixmapColorizeFilter
+{
+public:
+ QVGPixmapColorizeFilter();
+ ~QVGPixmapColorizeFilter();
+
+ void draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect) const;
+
+private:
+ mutable VGfloat matrix[5][4];
+ mutable QColor prevColor;
+ mutable bool firstTime;
+};
+
+class Q_OPENVG_EXPORT QVGPixmapDropShadowFilter : public QPixmapDropShadowFilter
+{
+public:
+ QVGPixmapDropShadowFilter();
+ ~QVGPixmapDropShadowFilter();
+
+ void draw(QPainter *p, const QPointF &pos, const QPixmap &px, const QRectF &src) const;
+
+private:
+ mutable VGfloat matrix[5][4];
+ mutable QColor prevColor;
+ mutable qreal prevRadius;
+ mutable int kernelSize;
+ mutable bool firstTime;
+ mutable QVarLengthArray<VGshort, 16> kernel;
+};
+
+#endif
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/openvg/qvg.h b/src/openvg/qvg.h
new file mode 100644
index 0000000..8da6159
--- /dev/null
+++ b/src/openvg/qvg.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVG_H
+#define QVG_H
+
+#include <QtCore/qglobal.h>
+
+// Include the OpenVG headers for use in applications that
+// issue raw OpenVG function calls.
+#if defined(QT_LOWER_CASE_VG_INCLUDES)
+#include <vg/openvg.h>
+#else
+#include <VG/openvg.h>
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(OpenVG)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/openvg/qvg_p.h b/src/openvg/qvg_p.h
new file mode 100644
index 0000000..7ac2430
--- /dev/null
+++ b/src/openvg/qvg_p.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVG_P_H
+#define QVG_P_H
+
+#include "qvg.h"
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/qimage.h>
+
+#if !defined(QT_NO_EGL)
+#include <QtGui/private/qegl_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QVGPaintEngine;
+
+#if !defined(QT_NO_EGL)
+
+class QEglContext;
+
+// Create an EGL context, but don't bind it to a surface. If single-context
+// mode is enabled, this will return the previously-created context.
+Q_OPENVG_EXPORT QEglContext *qt_vg_create_context(QPaintDevice *device);
+
+// Destroy an EGL context that was created by qt_vg_create_context().
+// If single-context mode is enabled, this will decrease the reference count.
+Q_OPENVG_EXPORT void qt_vg_destroy_context(QEglContext *context);
+
+// Return the shared pbuffer surface that can be made current to
+// destroy VGImage objects when there is no other surface available.
+Q_OPENVG_EXPORT EGLSurface qt_vg_shared_surface(void);
+
+// Make a context current with a specific surface.
+Q_OPENVG_EXPORT void qt_vg_make_current(QEglContext *context, EGLSurface surface);
+
+// Make a context uncurrent.
+Q_OPENVG_EXPORT void qt_vg_done_current(QEglContext *context, bool force = false);
+
+// Destroy a surface that was previously associated with a context.
+Q_OPENVG_EXPORT void qt_vg_destroy_surface(QEglContext *context, EGLSurface surface);
+
+// Convert the configuration format in a context to a VG or QImage format.
+Q_OPENVG_EXPORT VGImageFormat qt_vg_config_to_vg_format(QEglContext *context);
+Q_OPENVG_EXPORT QImage::Format qt_vg_config_to_image_format(QEglContext *context);
+
+#endif
+
+// Create a paint engine. Returns the common engine in single-context mode.
+Q_OPENVG_EXPORT QVGPaintEngine *qt_vg_create_paint_engine(void);
+
+// Destroy a paint engine. Does nothing in single-context mode.
+Q_OPENVG_EXPORT void qt_vg_destroy_paint_engine(QVGPaintEngine *engine);
+
+// Convert between QImage and VGImage format values.
+Q_OPENVG_EXPORT VGImageFormat qt_vg_image_to_vg_format(QImage::Format format);
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/openvg/qvgcompositionhelper_p.h b/src/openvg/qvgcompositionhelper_p.h
new file mode 100644
index 0000000..cdf1be9
--- /dev/null
+++ b/src/openvg/qvgcompositionhelper_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVGCOMPOSITIONHELPER_H
+#define QVGCOMPOSITIONHELPER_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 "qwindowsurface_vgegl_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QVG_NO_SINGLE_CONTEXT) && !defined(QT_NO_EGL)
+
+class QVGPaintEnginePrivate;
+class QVGEGLWindowSurfacePrivate;
+
+class Q_OPENVG_EXPORT QVGCompositionHelper
+{
+public:
+ QVGCompositionHelper();
+ virtual ~QVGCompositionHelper();
+
+ void startCompositing(const QSize& screenSize);
+ void endCompositing();
+
+ void blitWindow(QVGEGLWindowSurfacePrivate *surface, const QRect& rect,
+ const QPoint& topLeft, int opacity);
+ void fillBackground(const QRegion& region, const QBrush& brush);
+ void drawCursorImage(const QImage& image, const QPoint& offset);
+ void drawCursorPixmap(const QPixmap& pixmap, const QPoint& offset);
+ void setScissor(const QRegion& region);
+ void clearScissor();
+
+private:
+ QVGPaintEnginePrivate *d;
+ QSize screenSize;
+};
+
+#endif
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/openvg/qwindowsurface_vg.cpp b/src/openvg/qwindowsurface_vg.cpp
new file mode 100644
index 0000000..c77aa93
--- /dev/null
+++ b/src/openvg/qwindowsurface_vg.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwindowsurface_vg_p.h"
+#include "qwindowsurface_vgegl_p.h"
+#include "qpaintengine_vg_p.h"
+#include "qpixmapdata_vg_p.h"
+#include "qvg_p.h"
+
+#if !defined(QT_NO_EGL)
+
+#include <QtGui/private/qegl_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QVGWindowSurface::QVGWindowSurface(QWidget *window)
+ : QWindowSurface(window)
+{
+ d_ptr = QVGEGLWindowSurfacePrivate::create
+ (QVGEGLWindowSurfacePrivate::WindowSurface, this);
+}
+
+QVGWindowSurface::QVGWindowSurface
+ (QWidget *window, QVGEGLWindowSurfacePrivate *d)
+ : QWindowSurface(window), d_ptr(d)
+{
+}
+
+QVGWindowSurface::~QVGWindowSurface()
+{
+ delete d_ptr;
+}
+
+QPaintDevice *QVGWindowSurface::paintDevice()
+{
+ d_ptr->beginPaint(window());
+ return this;
+}
+
+void QVGWindowSurface::flush(QWidget *widget, const QRegion &region, const QPoint &offset)
+{
+ Q_UNUSED(offset);
+ QWidget *parent = widget->internalWinId() ? widget : widget->nativeParentWidget();
+ d_ptr->endPaint(parent, region);
+}
+
+void QVGWindowSurface::setGeometry(const QRect &rect)
+{
+ QWindowSurface::setGeometry(rect);
+ d_ptr->ensureContext(window());
+}
+
+bool QVGWindowSurface::scroll(const QRegion &area, int dx, int dy)
+{
+ return QWindowSurface::scroll(area, dx, dy);
+}
+
+void QVGWindowSurface::beginPaint(const QRegion &region)
+{
+ // Nothing to do here.
+ Q_UNUSED(region);
+}
+
+void QVGWindowSurface::endPaint(const QRegion &region)
+{
+ // Nothing to do here.
+ Q_UNUSED(region);
+}
+
+QPaintEngine *QVGWindowSurface::paintEngine() const
+{
+ return d_ptr->paintEngine();
+}
+
+int QVGWindowSurface::metric(PaintDeviceMetric met) const
+{
+ return window()->metric(met);
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/openvg/qwindowsurface_vg_p.h b/src/openvg/qwindowsurface_vg_p.h
new file mode 100644
index 0000000..e2ee583
--- /dev/null
+++ b/src/openvg/qwindowsurface_vg_p.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSURFACE_VG_P_H
+#define QWINDOWSURFACE_VG_P_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 <QtGui/private/qwindowsurface_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_NO_EGL)
+
+class QVGEGLWindowSurfacePrivate;
+
+class Q_OPENVG_EXPORT QVGWindowSurface : public QWindowSurface, public QPaintDevice
+{
+public:
+ QVGWindowSurface(QWidget *window);
+ QVGWindowSurface(QWidget *window, QVGEGLWindowSurfacePrivate *d);
+ ~QVGWindowSurface();
+
+ QPaintDevice *paintDevice();
+ void flush(QWidget *widget, const QRegion &region, const QPoint &offset);
+ void setGeometry(const QRect &rect);
+ bool scroll(const QRegion &area, int dx, int dy);
+
+ void beginPaint(const QRegion &region);
+ void endPaint(const QRegion &region);
+
+ QPaintEngine *paintEngine() const;
+
+protected:
+ int metric(PaintDeviceMetric metric) const;
+
+private:
+ QVGEGLWindowSurfacePrivate *d_ptr;
+};
+
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSURFACE_VG_P_H
diff --git a/src/openvg/qwindowsurface_vgegl.cpp b/src/openvg/qwindowsurface_vgegl.cpp
new file mode 100644
index 0000000..11c7021
--- /dev/null
+++ b/src/openvg/qwindowsurface_vgegl.cpp
@@ -0,0 +1,751 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwindowsurface_vgegl_p.h"
+#include "qpaintengine_vg_p.h"
+#include "qpixmapdata_vg_p.h"
+#include "qvg_p.h"
+
+#if !defined(QT_NO_EGL)
+
+QT_BEGIN_NAMESPACE
+
+// Turn off "direct to window" rendering if EGL cannot support it.
+#if !defined(EGL_RENDER_BUFFER) || !defined(EGL_SINGLE_BUFFER)
+#if defined(QVG_DIRECT_TO_WINDOW)
+#undef QVG_DIRECT_TO_WINDOW
+#endif
+#endif
+
+// Determine if preserved window contents should be used.
+#if !defined(EGL_SWAP_BEHAVIOR) || !defined(EGL_BUFFER_PRESERVED)
+#if !defined(QVG_NO_PRESERVED_SWAP)
+#define QVG_NO_PRESERVED_SWAP 1
+#endif
+#endif
+
+VGImageFormat qt_vg_config_to_vg_format(QEglContext *context)
+{
+ return qt_vg_image_to_vg_format
+ (qt_vg_config_to_image_format(context));
+}
+
+QImage::Format qt_vg_config_to_image_format(QEglContext *context)
+{
+ EGLint red = 0;
+ EGLint green = 0;
+ EGLint blue = 0;
+ EGLint alpha = 0;
+ context->configAttrib(EGL_RED_SIZE, &red);
+ context->configAttrib(EGL_GREEN_SIZE, &green);
+ context->configAttrib(EGL_BLUE_SIZE, &blue);
+ context->configAttrib(EGL_ALPHA_SIZE, &alpha);
+ QImage::Format argbFormat;
+#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
+ EGLint type = 0;
+ context->configAttrib(EGL_SURFACE_TYPE, &type);
+ if ((type & EGL_VG_ALPHA_FORMAT_PRE_BIT) != 0)
+ argbFormat = QImage::Format_ARGB32_Premultiplied;
+ else
+ argbFormat = QImage::Format_ARGB32;
+#else
+ argbFormat = QImage::Format_ARGB32;
+#endif
+ if (red == 8 && green == 8 && blue == 8 && alpha == 8)
+ return argbFormat;
+ else if (red == 8 && green == 8 && blue == 8 && alpha == 0)
+ return QImage::Format_RGB32;
+ else if (red == 5 && green == 6 && blue == 5 && alpha == 0)
+ return QImage::Format_RGB16;
+ else if (red == 4 && green == 4 && blue == 4 && alpha == 4)
+ return QImage::Format_ARGB4444_Premultiplied;
+ else
+ return argbFormat; // XXX
+}
+
+static void copySubImage(QImage *image, VGImage vgImage, const QRect& rect)
+{
+ vgGetImageSubData
+ (vgImage,
+ image->bits() + rect.bottom() * image->bytesPerLine() +
+ rect.x() * (image->depth() / 8),
+ -(image->bytesPerLine()),
+ qt_vg_image_to_vg_format(image->format()),
+ rect.x(), (image->height() - 1) - rect.bottom(),
+ rect.width(), rect.height());
+}
+
+#if !defined(QVG_NO_SINGLE_CONTEXT)
+
+class QVGSharedContext
+{
+public:
+ QVGSharedContext();
+ ~QVGSharedContext();
+
+ QEglContext *context;
+ int refCount;
+ QVGPaintEngine *engine;
+ EGLSurface surface;
+ EGLSurface lastSurface;
+};
+
+QVGSharedContext::QVGSharedContext()
+ : context(0)
+ , refCount(0)
+ , engine(0)
+ , surface(EGL_NO_SURFACE)
+ , lastSurface(EGL_NO_SURFACE)
+{
+}
+
+QVGSharedContext::~QVGSharedContext()
+{
+ if (context)
+ qt_vg_make_current(context, qt_vg_shared_surface());
+ delete engine;
+ if (context)
+ qt_vg_done_current(context, true);
+ if (surface != EGL_NO_SURFACE)
+ qt_vg_destroy_surface(context, surface);
+ delete context;
+}
+
+Q_GLOBAL_STATIC(QVGSharedContext, sharedContext);
+
+QVGPaintEngine *qt_vg_create_paint_engine(void)
+{
+ QVGSharedContext *shared = sharedContext();
+ if (!shared->engine)
+ shared->engine = new QVGPaintEngine();
+ return shared->engine;
+}
+
+void qt_vg_destroy_paint_engine(QVGPaintEngine *engine)
+{
+ Q_UNUSED(engine);
+}
+
+#else
+
+QVGPaintEngine *qt_vg_create_paint_engine(void)
+{
+ return new QVGPaintEngine();
+}
+
+void qt_vg_destroy_paint_engine(QVGPaintEngine *engine)
+{
+ delete engine;
+}
+
+#endif
+
+#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
+
+static bool isPremultipliedContext(const QEglContext *context)
+{
+ EGLint value = 0;
+ if (context->configAttrib(EGL_SURFACE_TYPE, &value))
+ return (value & EGL_VG_ALPHA_FORMAT_PRE_BIT) != 0;
+ else
+ return false;
+}
+
+#endif
+
+static QEglContext *createContext(QPaintDevice *device)
+{
+ QEglContext *context;
+
+ // Create the context object and open the display.
+ context = new QEglContext();
+ context->setApi(QEgl::OpenVG);
+ if (!context->openDisplay(device)) {
+ delete context;
+ return 0;
+ }
+
+ // Choose an appropriate configuration for rendering into the device.
+ QEglProperties configProps;
+ configProps.setPaintDeviceFormat(device);
+ int redSize = configProps.value(EGL_RED_SIZE);
+ if (redSize == EGL_DONT_CARE || redSize == 0)
+ configProps.setPixelFormat(QImage::Format_ARGB32); // XXX
+#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
+ configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT |
+ EGL_VG_ALPHA_FORMAT_PRE_BIT);
+ configProps.setRenderableType(QEgl::OpenVG);
+ if (!context->chooseConfig(configProps)) {
+ // Try again without the "pre" bit.
+ configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT);
+ if (!context->chooseConfig(configProps)) {
+ delete context;
+ return 0;
+ }
+ }
+#else
+ configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT);
+ configProps.setRenderableType(QEgl::OpenVG);
+ if (!context->chooseConfig(configProps)) {
+ delete context;
+ return 0;
+ }
+#endif
+
+ // Construct a new EGL context for the selected configuration.
+ if (!context->createContext()) {
+ delete context;
+ return 0;
+ }
+
+ return context;
+}
+
+#if !defined(QVG_NO_SINGLE_CONTEXT)
+
+QEglContext *qt_vg_create_context(QPaintDevice *device)
+{
+ QVGSharedContext *shared = sharedContext();
+ if (shared->context) {
+ ++(shared->refCount);
+ return shared->context;
+ } else {
+ shared->context = createContext(device);
+ shared->refCount = 1;
+ return shared->context;
+ }
+}
+
+void qt_vg_destroy_context(QEglContext *context)
+{
+ QVGSharedContext *shared = sharedContext();
+ if (shared->context != context) {
+ // This is not the shared context. Shouldn't happen!
+ delete context;
+ } else if (--(shared->refCount) <= 0) {
+ qt_vg_make_current(shared->context, qt_vg_shared_surface());
+ delete shared->engine;
+ shared->engine = 0;
+ qt_vg_done_current(shared->context, true);
+ if (shared->surface != EGL_NO_SURFACE) {
+ qt_vg_destroy_surface(shared->context, shared->surface);
+ shared->surface = EGL_NO_SURFACE;
+ }
+ delete shared->context;
+ shared->context = 0;
+ }
+}
+
+EGLSurface qt_vg_shared_surface(void)
+{
+ QVGSharedContext *shared = sharedContext();
+ if (shared->surface == EGL_NO_SURFACE) {
+ EGLint attribs[7];
+ attribs[0] = EGL_WIDTH;
+ attribs[1] = 16;
+ attribs[2] = EGL_HEIGHT;
+ attribs[3] = 16;
+#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
+ if (isPremultipliedContext(shared->context)) {
+ attribs[4] = EGL_VG_ALPHA_FORMAT;
+ attribs[5] = EGL_VG_ALPHA_FORMAT_PRE;
+ attribs[6] = EGL_NONE;
+ } else
+#endif
+ {
+ attribs[4] = EGL_NONE;
+ }
+ shared->surface = eglCreatePbufferSurface
+ (shared->context->display(), shared->context->config(), attribs);
+ }
+ return shared->surface;
+}
+
+void qt_vg_make_current(QEglContext *context, EGLSurface surface)
+{
+ // Bail out if the context and surface are already current.
+ if (context->isCurrent() && context->surface() == surface)
+ return;
+
+ // Are we setting the surface to the same as the last elided doneCurrent()?
+ QVGSharedContext *shared = sharedContext();
+ if (context->isCurrent() && shared->lastSurface == surface) {
+ shared->lastSurface = EGL_NO_SURFACE;
+ context->setSurface(surface);
+ return;
+ }
+
+ // Switch to the new context and surface.
+ shared->lastSurface = EGL_NO_SURFACE;
+ context->setSurface(surface);
+ context->makeCurrent();
+}
+
+void qt_vg_done_current(QEglContext *context, bool force)
+{
+ QVGSharedContext *shared = sharedContext();
+ if (force) {
+ context->doneCurrent();
+ shared->lastSurface = EGL_NO_SURFACE;
+ } else {
+ // Keep the context current for now just in case we immediately
+ // reuse the same surface for the next frame.
+ shared->lastSurface = context->surface();
+ }
+}
+
+void qt_vg_destroy_surface(QEglContext *context, EGLSurface surface)
+{
+ QVGSharedContext *shared = sharedContext();
+ if (shared->lastSurface == surface) {
+ shared->lastSurface = EGL_NO_SURFACE;
+ context->doneCurrent();
+ }
+ context->setSurface(surface);
+ context->destroySurface();
+}
+
+#else
+
+QEglContext *qt_vg_create_context(QPaintDevice *device)
+{
+ return createContext(device);
+}
+
+void qt_vg_destroy_context(QEglContext *context)
+{
+ delete context;
+}
+
+EGLSurface qt_vg_shared_surface(void)
+{
+ return EGL_NO_SURFACE;
+}
+
+void qt_vg_make_current(QEglContext *context, EGLSurface surface)
+{
+ context->setSurface(surface);
+ context->makeCurrent();
+}
+
+void qt_vg_done_current(QEglContext *context, bool force)
+{
+ Q_UNUSED(force);
+ context->doneCurrent();
+}
+
+void qt_vg_destroy_surface(QEglContext *context, EGLSurface surface)
+{
+ context->setSurface(surface);
+ context->destroySurface();
+}
+
+#endif
+
+QVGEGLWindowSurfacePrivate::QVGEGLWindowSurfacePrivate(QWindowSurface *win)
+{
+ winSurface = win;
+ engine = 0;
+}
+
+QVGEGLWindowSurfacePrivate::~QVGEGLWindowSurfacePrivate()
+{
+ // Destroy the paint engine if it hasn't been destroyed already.
+ destroyPaintEngine();
+}
+
+QVGEGLWindowSurfacePrivate *QVGEGLWindowSurfacePrivate::create
+ (SurfaceType type, QWindowSurface *win)
+{
+#if defined(QVG_VGIMAGE_BACKBUFFERS)
+ if (type == VGImageSurface)
+ return new QVGEGLWindowSurfaceVGImage(win);
+ else if (type == QImageSurface)
+ return new QVGEGLWindowSurfaceQImage(win);
+#endif
+ if (type == WindowSurface)
+ return new QVGEGLWindowSurfaceDirect(win);
+ return 0;
+}
+
+QVGPaintEngine *QVGEGLWindowSurfacePrivate::paintEngine()
+{
+ if (!engine)
+ engine = qt_vg_create_paint_engine();
+ return engine;
+}
+
+VGImage QVGEGLWindowSurfacePrivate::surfaceImage() const
+{
+ return VG_INVALID_HANDLE;
+}
+
+void QVGEGLWindowSurfacePrivate::destroyPaintEngine()
+{
+ if (engine) {
+ qt_vg_destroy_paint_engine(engine);
+ engine = 0;
+ }
+}
+
+QSize QVGEGLWindowSurfacePrivate::windowSurfaceSize(QWidget *widget) const
+{
+ Q_UNUSED(widget);
+
+ QRect rect = winSurface->geometry();
+ QSize newSize = rect.size();
+
+#if defined(Q_WS_QWS)
+ // Account for the widget mask, if any.
+ if (widget && !widget->mask().isEmpty()) {
+ const QRegion region = widget->mask()
+ & rect.translated(-widget->geometry().topLeft());
+ newSize = region.boundingRect().size();
+ }
+#endif
+
+ return newSize;
+}
+
+#if defined(QVG_VGIMAGE_BACKBUFFERS)
+
+QVGEGLWindowSurfaceVGImage::QVGEGLWindowSurfaceVGImage(QWindowSurface *win)
+ : QVGEGLWindowSurfacePrivate(win)
+ , context(0)
+ , backBuffer(VG_INVALID_HANDLE)
+ , backBufferSurface(EGL_NO_SURFACE)
+ , recreateBackBuffer(false)
+ , isPaintingActive(false)
+ , windowSurface(EGL_NO_SURFACE)
+{
+}
+
+QVGEGLWindowSurfaceVGImage::~QVGEGLWindowSurfaceVGImage()
+{
+ destroyPaintEngine();
+ if (context) {
+ if (backBufferSurface != EGL_NO_SURFACE) {
+ // We need a current context to be able to destroy the image.
+ // We use the shared surface because the native window handle
+ // associated with "windowSurface" may have been destroyed already.
+ qt_vg_make_current(context, qt_vg_shared_surface());
+ qt_vg_destroy_surface(context, backBufferSurface);
+ vgDestroyImage(backBuffer);
+ qt_vg_done_current(context, true);
+ }
+ if (windowSurface != EGL_NO_SURFACE)
+ qt_vg_destroy_surface(context, windowSurface);
+ qt_vg_destroy_context(context);
+ }
+}
+
+QEglContext *QVGEGLWindowSurfaceVGImage::ensureContext(QWidget *widget)
+{
+ QSize newSize = windowSurfaceSize(widget);
+ if (context && size != newSize) {
+ // The surface size has changed, so we need to recreate
+ // the back buffer. Keep the same context and paint engine.
+ size = newSize;
+ if (isPaintingActive)
+ qt_vg_done_current(context, true);
+ isPaintingActive = false;
+ recreateBackBuffer = true;
+ }
+ if (!context) {
+ // Create a new EGL context. We create the surface in beginPaint().
+ size = newSize;
+ context = qt_vg_create_context(widget);
+ if (!context)
+ return 0;
+ isPaintingActive = false;
+ }
+ return context;
+}
+
+void QVGEGLWindowSurfaceVGImage::beginPaint(QWidget *widget)
+{
+ QEglContext *context = ensureContext(widget);
+ if (context) {
+ if (recreateBackBuffer || backBufferSurface == EGL_NO_SURFACE) {
+ // Create a VGImage object to act as the back buffer
+ // for this window. We have to create the VGImage with a
+ // current context, so activate the main surface for the window.
+ qt_vg_make_current(context, mainSurface());
+ recreateBackBuffer = false;
+ if (backBufferSurface != EGL_NO_SURFACE) {
+ eglDestroySurface(context->display(), backBufferSurface);
+ backBufferSurface = EGL_NO_SURFACE;
+ }
+ if (backBuffer != VG_INVALID_HANDLE) {
+ vgDestroyImage(backBuffer);
+ }
+ VGImageFormat format = qt_vg_config_to_vg_format(context);
+ backBuffer = vgCreateImage
+ (format, size.width(), size.height(),
+ VG_IMAGE_QUALITY_FASTER);
+ if (backBuffer != VG_INVALID_HANDLE) {
+ // Create an EGL surface for rendering into the VGImage.
+ backBufferSurface = eglCreatePbufferFromClientBuffer
+ (context->display(), EGL_OPENVG_IMAGE,
+ (EGLClientBuffer)(backBuffer),
+ context->config(), NULL);
+ if (backBufferSurface == EGL_NO_SURFACE) {
+ vgDestroyImage(backBuffer);
+ backBuffer = VG_INVALID_HANDLE;
+ }
+ }
+ }
+ if (backBufferSurface != EGL_NO_SURFACE)
+ qt_vg_make_current(context, backBufferSurface);
+ else
+ qt_vg_make_current(context, mainSurface());
+ isPaintingActive = true;
+ }
+}
+
+void QVGEGLWindowSurfaceVGImage::endPaint
+ (QWidget *widget, const QRegion& region, QImage *image)
+{
+ Q_UNUSED(region);
+ Q_UNUSED(image);
+ QEglContext *context = ensureContext(widget);
+ if (context) {
+ if (backBufferSurface != EGL_NO_SURFACE) {
+ if (isPaintingActive)
+ vgFlush();
+ qt_vg_done_current(context);
+ }
+ context->setSurface(EGL_NO_SURFACE);
+ isPaintingActive = false;
+ }
+}
+
+VGImage QVGEGLWindowSurfaceVGImage::surfaceImage() const
+{
+ return backBuffer;
+}
+
+EGLSurface QVGEGLWindowSurfaceVGImage::mainSurface() const
+{
+ if (windowSurface != EGL_NO_SURFACE)
+ return windowSurface;
+ else
+ return qt_vg_shared_surface();
+}
+
+QVGEGLWindowSurfaceQImage::QVGEGLWindowSurfaceQImage(QWindowSurface *win)
+ : QVGEGLWindowSurfaceVGImage(win)
+{
+}
+
+QVGEGLWindowSurfaceQImage::~QVGEGLWindowSurfaceQImage()
+{
+}
+
+void QVGEGLWindowSurfaceQImage::endPaint
+ (QWidget *widget, const QRegion& region, QImage *image)
+{
+ QEglContext *context = ensureContext(widget);
+ if (context) {
+ if (backBufferSurface != EGL_NO_SURFACE) {
+ if (isPaintingActive)
+ vgFlush();
+ qt_vg_make_current(context, mainSurface());
+ QRegion rgn = region.intersected
+ (QRect(0, 0, image->width(), image->height()));
+ if (rgn.numRects() == 1) {
+ copySubImage(image, backBuffer, rgn.boundingRect());
+ } else {
+ QVector<QRect> rects = rgn.rects();
+ for (int index = 0; index < rects.size(); ++index)
+ copySubImage(image, backBuffer, rects[index]);
+ }
+ qt_vg_done_current(context);
+ }
+ context->setSurface(EGL_NO_SURFACE);
+ isPaintingActive = false;
+ }
+}
+
+#endif // QVG_VGIMAGE_BACKBUFFERS
+
+QVGEGLWindowSurfaceDirect::QVGEGLWindowSurfaceDirect(QWindowSurface *win)
+ : QVGEGLWindowSurfacePrivate(win)
+ , context(0)
+ , isPaintingActive(false)
+ , needToSwap(false)
+ , windowSurface(EGL_NO_SURFACE)
+{
+}
+
+QVGEGLWindowSurfaceDirect::~QVGEGLWindowSurfaceDirect()
+{
+}
+
+QEglContext *QVGEGLWindowSurfaceDirect::ensureContext(QWidget *widget)
+{
+ QSize newSize = windowSurfaceSize(widget);
+ QEglProperties surfaceProps;
+
+#if defined(QVG_RECREATE_ON_SIZE_CHANGE)
+#if !defined(QVG_NO_SINGLE_CONTEXT)
+ if (context && size != newSize) {
+ // The surface size has changed, so we need to recreate it.
+ // We can keep the same context and paint engine.
+ size = newSize;
+ if (isPaintingActive)
+ qt_vg_done_current(context, true);
+ context->setSurface(windowSurface);
+ context->destroySurface();
+#if defined(EGL_VG_ALPHA_FORMAT_PRE_BIT)
+ if (isPremultipliedContext(context)) {
+ surfaceProps.setValue
+ (EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_PRE);
+ } else {
+ surfaceProps.removeValue(EGL_VG_ALPHA_FORMAT);
+ }
+#endif
+ context->createSurface(widget, &surfaceProps);
+ windowSurface = context->surface();
+ context->setSurface(EGL_NO_SURFACE);
+ isPaintingActive = false;
+ }
+#else
+ if (context && size != newSize) {
+ // The surface size has changed, so we need to recreate
+ // the EGL context for the widget. We also need to recreate
+ // the surface's paint engine if context sharing is not
+ // enabled because we cannot reuse the existing paint objects
+ // in the new context.
+ qt_vg_destroy_paint_engine(engine);
+ engine = 0;
+ context->setSurface(windowSurface);
+ context->destroySurface();
+ qt_vg_destroy_context(context);
+ context = 0;
+ windowSurface = EGL_NO_SURFACE;
+ }
+#endif
+#endif
+ if (!context) {
+ // Create a new EGL context and bind it to the widget surface.
+ size = newSize;
+ context = qt_vg_create_context(widget);
+ if (!context)
+ return 0;
+ // We want a direct to window rendering surface if possible.
+#if defined(QVG_DIRECT_TO_WINDOW)
+ surfaceProps.setValue(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER);
+#endif
+#if defined(EGL_VG_ALPHA_FORMAT_PRE_BIT)
+ if (isPremultipliedContext(context)) {
+ surfaceProps.setValue
+ (EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_PRE);
+ } else {
+ surfaceProps.removeValue(EGL_VG_ALPHA_FORMAT);
+ }
+#endif
+ if (!context->createSurface(widget, &surfaceProps)) {
+ qt_vg_destroy_context(context);
+ context = 0;
+ return 0;
+ }
+ needToSwap = true;
+#if defined(QVG_DIRECT_TO_WINDOW)
+ // Did we get a direct to window rendering surface?
+ EGLint buffer = 0;
+ if (eglQueryContext(context->display(), context->context(),
+ EGL_RENDER_BUFFER, &buffer) &&
+ buffer == EGL_SINGLE_BUFFER) {
+ needToSwap = false;
+ }
+#endif
+#if !defined(QVG_NO_PRESERVED_SWAP)
+ // Try to force the surface back buffer to preserve its contents.
+ if (needToSwap) {
+ eglGetError(); // Clear error state first.
+ eglSurfaceAttrib(context->display(), context->surface(),
+ EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);
+ if (eglGetError() != EGL_SUCCESS) {
+ qWarning("QVG: could not enable preserved swap");
+ }
+ }
+#endif
+ windowSurface = context->surface();
+ context->setSurface(EGL_NO_SURFACE);
+ isPaintingActive = false;
+ }
+ return context;
+}
+
+void QVGEGLWindowSurfaceDirect::beginPaint(QWidget *widget)
+{
+ QEglContext *context = ensureContext(widget);
+ if (context) {
+ qt_vg_make_current(context, windowSurface);
+ isPaintingActive = true;
+ }
+}
+
+void QVGEGLWindowSurfaceDirect::endPaint
+ (QWidget *widget, const QRegion& region, QImage *image)
+{
+ Q_UNUSED(region);
+ Q_UNUSED(image);
+ QEglContext *context = ensureContext(widget);
+ if (context) {
+ if (needToSwap) {
+ if (!isPaintingActive)
+ qt_vg_make_current(context, windowSurface);
+ context->swapBuffers();
+ qt_vg_done_current(context);
+ } else if (isPaintingActive) {
+ vgFlush();
+ qt_vg_done_current(context);
+ }
+ context->setSurface(EGL_NO_SURFACE);
+ isPaintingActive = false;
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/openvg/qwindowsurface_vgegl_p.h b/src/openvg/qwindowsurface_vgegl_p.h
new file mode 100644
index 0000000..aa23772
--- /dev/null
+++ b/src/openvg/qwindowsurface_vgegl_p.h
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSURFACE_VGEGL_P_H
+#define QWINDOWSURFACE_VGEGL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the QLibrary class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qwindowsurface_p.h>
+#include "qvg_p.h"
+
+#if !defined(QT_NO_EGL)
+
+#include <QtGui/private/qegl_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWindowSurface;
+
+class Q_OPENVG_EXPORT QVGEGLWindowSurfacePrivate
+{
+public:
+ QVGEGLWindowSurfacePrivate(QWindowSurface *win);
+ virtual ~QVGEGLWindowSurfacePrivate();
+
+ enum SurfaceType
+ {
+ WindowSurface,
+ VGImageSurface,
+ QImageSurface
+ };
+
+ static QVGEGLWindowSurfacePrivate *create
+ (SurfaceType type, QWindowSurface *win);
+
+ QVGPaintEngine *paintEngine();
+ virtual QEglContext *ensureContext(QWidget *widget) = 0;
+ virtual void beginPaint(QWidget *widget) = 0;
+ virtual void endPaint
+ (QWidget *widget, const QRegion& region, QImage *image = 0) = 0;
+ virtual VGImage surfaceImage() const;
+ virtual QSize surfaceSize() const = 0;
+
+private:
+ QVGPaintEngine *engine;
+
+protected:
+ QWindowSurface *winSurface;
+
+ void destroyPaintEngine();
+ QSize windowSurfaceSize(QWidget *widget) const;
+};
+
+#if defined(EGL_OPENVG_IMAGE) && !defined(QVG_NO_SINGLE_CONTEXT)
+
+#define QVG_VGIMAGE_BACKBUFFERS 1
+
+class Q_OPENVG_EXPORT QVGEGLWindowSurfaceVGImage : public QVGEGLWindowSurfacePrivate
+{
+public:
+ QVGEGLWindowSurfaceVGImage(QWindowSurface *win);
+ virtual ~QVGEGLWindowSurfaceVGImage();
+
+ QEglContext *ensureContext(QWidget *widget);
+ void beginPaint(QWidget *widget);
+ void endPaint(QWidget *widget, const QRegion& region, QImage *image);
+ VGImage surfaceImage() const;
+ QSize surfaceSize() const { return size; }
+
+protected:
+ QEglContext *context;
+ VGImage backBuffer;
+ EGLSurface backBufferSurface;
+ bool recreateBackBuffer;
+ bool isPaintingActive;
+ QSize size;
+ EGLSurface windowSurface;
+
+ EGLSurface mainSurface() const;
+};
+
+class Q_OPENVG_EXPORT QVGEGLWindowSurfaceQImage : public QVGEGLWindowSurfaceVGImage
+{
+public:
+ QVGEGLWindowSurfaceQImage(QWindowSurface *win);
+ virtual ~QVGEGLWindowSurfaceQImage();
+
+ void endPaint(QWidget *widget, const QRegion& region, QImage *image);
+};
+
+#endif // EGL_OPENVG_IMAGE
+
+class Q_OPENVG_EXPORT QVGEGLWindowSurfaceDirect : public QVGEGLWindowSurfacePrivate
+{
+public:
+ QVGEGLWindowSurfaceDirect(QWindowSurface *win);
+ virtual ~QVGEGLWindowSurfaceDirect();
+
+ QEglContext *ensureContext(QWidget *widget);
+ void beginPaint(QWidget *widget);
+ void endPaint(QWidget *widget, const QRegion& region, QImage *image);
+ QSize surfaceSize() const { return size; }
+
+protected:
+ QEglContext *context;
+ QSize size;
+ bool isPaintingActive;
+ bool needToSwap;
+ EGLSurface windowSurface;
+};
+
+QT_END_NAMESPACE
+
+#endif // !QT_NO_EGL
+
+#endif // QWINDOWSURFACE_VGEGL_P_H
diff --git a/src/plugins/graphicssystems/graphicssystems.pro b/src/plugins/graphicssystems/graphicssystems.pro
index b8216ff..bfdec6a 100644
--- a/src/plugins/graphicssystems/graphicssystems.pro
+++ b/src/plugins/graphicssystems/graphicssystems.pro
@@ -1,2 +1,8 @@
TEMPLATE = subdirs
contains(QT_CONFIG, opengl):SUBDIRS += opengl
+contains(QT_CONFIG, openvg):contains(QT_CONFIG, egl):SUBDIRS += openvg
+
+contains(QT_CONFIG, shivavg) {
+ # Only works under X11 at present
+ !win32:!embedded:!mac:SUBDIRS += shivavg
+}
diff --git a/src/plugins/graphicssystems/openvg/main.cpp b/src/plugins/graphicssystems/openvg/main.cpp
new file mode 100644
index 0000000..265ccd3
--- /dev/null
+++ b/src/plugins/graphicssystems/openvg/main.cpp
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qgraphicssystemplugin_p.h>
+#include "qgraphicssystem_vg_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QVGGraphicsSystemPlugin : public QGraphicsSystemPlugin
+{
+public:
+ QStringList keys() const;
+ QGraphicsSystem *create(const QString&);
+};
+
+QStringList QVGGraphicsSystemPlugin::keys() const
+{
+ QStringList list;
+ list << "OpenVG";
+ return list;
+}
+
+QGraphicsSystem* QVGGraphicsSystemPlugin::create(const QString& system)
+{
+ if (system.toLower() == "openvg")
+ return new QVGGraphicsSystem;
+
+ return 0;
+}
+
+Q_EXPORT_PLUGIN2(openvg, QVGGraphicsSystemPlugin)
+
+QT_END_NAMESPACE
diff --git a/src/plugins/graphicssystems/openvg/openvg.pro b/src/plugins/graphicssystems/openvg/openvg.pro
new file mode 100644
index 0000000..0abbfbd
--- /dev/null
+++ b/src/plugins/graphicssystems/openvg/openvg.pro
@@ -0,0 +1,20 @@
+TARGET = qvggraphicssystem
+include(../../qpluginbase.pri)
+
+QT += openvg
+
+QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/graphicssystems
+
+SOURCES = main.cpp qgraphicssystem_vg.cpp
+HEADERS = qgraphicssystem_vg_p.h
+
+target.path += $$[QT_INSTALL_PLUGINS]/graphicssystems
+INSTALLS += target
+
+!isEmpty(QMAKE_INCDIR_OPENVG): INCLUDEPATH += $$QMAKE_INCDIR_OPENVG
+!isEmpty(QMAKE_LIBDIR_OPENVG): LIBS += -L$$QMAKE_LIBDIR_OPENVG
+!isEmpty(QMAKE_LIBS_OPENVG): LIBS += $$QMAKE_LIBS_OPENVG
+
+!isEmpty(QMAKE_INCDIR_EGL): INCLUDEPATH += $$QMAKE_INCDIR_EGL
+!isEmpty(QMAKE_LIBDIR_EGL): LIBS += -L$$QMAKE_LIBDIR_EGL
+!isEmpty(QMAKE_LIBS_EGL): LIBS += $$QMAKE_LIBS_EGL
diff --git a/src/plugins/graphicssystems/openvg/qgraphicssystem_vg.cpp b/src/plugins/graphicssystems/openvg/qgraphicssystem_vg.cpp
new file mode 100644
index 0000000..d975ad7
--- /dev/null
+++ b/src/plugins/graphicssystems/openvg/qgraphicssystem_vg.cpp
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgraphicssystem_vg_p.h"
+#include <QtOpenVG/private/qpixmapdata_vg_p.h>
+#include <QtOpenVG/private/qwindowsurface_vg_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QVGGraphicsSystem::QVGGraphicsSystem()
+{
+}
+
+QPixmapData *QVGGraphicsSystem::createPixmapData(QPixmapData::PixelType type) const
+{
+#if !defined(QVG_NO_SINGLE_CONTEXT) && !defined(QVG_NO_PIXMAP_DATA)
+ // Pixmaps can use QVGPixmapData; bitmaps must use raster.
+ if (type == QPixmapData::PixmapType)
+ return new QVGPixmapData(type);
+ else
+ return new QRasterPixmapData(type);
+#else
+ return new QRasterPixmapData(type);
+#endif
+}
+
+QWindowSurface *QVGGraphicsSystem::createWindowSurface(QWidget *widget) const
+{
+ return new QVGWindowSurface(widget);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/graphicssystems/openvg/qgraphicssystem_vg_p.h b/src/plugins/graphicssystems/openvg/qgraphicssystem_vg_p.h
new file mode 100644
index 0000000..368f48d
--- /dev/null
+++ b/src/plugins/graphicssystems/openvg/qgraphicssystem_vg_p.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGRAPHICSSYSTEM_VG_P_H
+#define QGRAPHICSSYSTEM_VG_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qgraphicssystem_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QVGGraphicsSystem : public QGraphicsSystem
+{
+public:
+ QVGGraphicsSystem();
+
+ QPixmapData *createPixmapData(QPixmapData::PixelType type) const;
+ QWindowSurface *createWindowSurface(QWidget *widget) const;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/graphicssystems/shivavg/README b/src/plugins/graphicssystems/shivavg/README
new file mode 100644
index 0000000..15ee710
--- /dev/null
+++ b/src/plugins/graphicssystems/shivavg/README
@@ -0,0 +1,8 @@
+
+This graphics system uses ShivaVG (http://sourceforge.net/projects/shivavg)
+to perform OpenVG rendering on X11 systems. The graphics system name for
+the "-graphicssystem" command-line option is "ShivaVG".
+
+ShivaVG support is experimental, mostly to demonstrate how to integrate
+non-EGL OpenVG engines into the system. It will probably not produce
+good output.
diff --git a/src/plugins/graphicssystems/shivavg/main.cpp b/src/plugins/graphicssystems/shivavg/main.cpp
new file mode 100644
index 0000000..037bfb2
--- /dev/null
+++ b/src/plugins/graphicssystems/shivavg/main.cpp
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qgraphicssystemplugin_p.h>
+#include "shivavggraphicssystem.h"
+
+QT_BEGIN_NAMESPACE
+
+class ShivaVGGraphicsSystemPlugin : public QGraphicsSystemPlugin
+{
+public:
+ QStringList keys() const;
+ QGraphicsSystem *create(const QString&);
+};
+
+QStringList ShivaVGGraphicsSystemPlugin::keys() const
+{
+ QStringList list;
+ list << "ShivaVG";
+ return list;
+}
+
+QGraphicsSystem* ShivaVGGraphicsSystemPlugin::create(const QString& system)
+{
+ if (system.toLower() == "shivavg")
+ return new ShivaVGGraphicsSystem;
+
+ return 0;
+}
+
+Q_EXPORT_PLUGIN2(shivavg, ShivaVGGraphicsSystemPlugin)
+
+QT_END_NAMESPACE
diff --git a/src/plugins/graphicssystems/shivavg/shivavg.pro b/src/plugins/graphicssystems/shivavg/shivavg.pro
new file mode 100644
index 0000000..68345af
--- /dev/null
+++ b/src/plugins/graphicssystems/shivavg/shivavg.pro
@@ -0,0 +1,16 @@
+TARGET = qshivavggraphicssystem
+include(../../qpluginbase.pri)
+
+QT += openvg
+
+QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/graphicssystems
+
+SOURCES = main.cpp shivavggraphicssystem.cpp shivavgwindowsurface.cpp
+HEADERS = shivavggraphicssystem.h shivavgwindowsurface.h
+
+target.path += $$[QT_INSTALL_PLUGINS]/graphicssystems
+INSTALLS += target
+
+!isEmpty(QMAKE_INCDIR_OPENVG): INCLUDEPATH += $$QMAKE_INCDIR_OPENVG
+!isEmpty(QMAKE_LIBDIR_OPENVG): LIBS += -L$$QMAKE_LIBDIR_OPENVG
+!isEmpty(QMAKE_LIBS_OPENVG): LIBS += $$QMAKE_LIBS_OPENVG
diff --git a/src/plugins/graphicssystems/shivavg/shivavggraphicssystem.cpp b/src/plugins/graphicssystems/shivavg/shivavggraphicssystem.cpp
new file mode 100644
index 0000000..fb60a42
--- /dev/null
+++ b/src/plugins/graphicssystems/shivavg/shivavggraphicssystem.cpp
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "shivavggraphicssystem.h"
+#include "shivavgwindowsurface.h"
+#include <QtGui/private/qpixmap_raster_p.h>
+
+QT_BEGIN_NAMESPACE
+
+ShivaVGGraphicsSystem::ShivaVGGraphicsSystem()
+{
+}
+
+QPixmapData *ShivaVGGraphicsSystem::createPixmapData(QPixmapData::PixelType type) const
+{
+ return new QRasterPixmapData(type);
+}
+
+QWindowSurface *ShivaVGGraphicsSystem::createWindowSurface(QWidget *widget) const
+{
+ return new ShivaVGWindowSurface(widget);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/graphicssystems/shivavg/shivavggraphicssystem.h b/src/plugins/graphicssystems/shivavg/shivavggraphicssystem.h
new file mode 100644
index 0000000..1c9ec70
--- /dev/null
+++ b/src/plugins/graphicssystems/shivavg/shivavggraphicssystem.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SHIVAVGGRAPHICSSYSTEM_H
+#define SHIVAVGGRAPHICSSYSTEM_H
+
+#include <QtGui/private/qgraphicssystem_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class ShivaVGGraphicsSystem : public QGraphicsSystem
+{
+public:
+ ShivaVGGraphicsSystem();
+
+ QPixmapData *createPixmapData(QPixmapData::PixelType type) const;
+ QWindowSurface *createWindowSurface(QWidget *widget) const;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/graphicssystems/shivavg/shivavgwindowsurface.cpp b/src/plugins/graphicssystems/shivavg/shivavgwindowsurface.cpp
new file mode 100644
index 0000000..bf1f942
--- /dev/null
+++ b/src/plugins/graphicssystems/shivavg/shivavgwindowsurface.cpp
@@ -0,0 +1,370 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#define GL_GLEXT_PROTOTYPES
+#include "shivavgwindowsurface.h"
+#include <QtOpenVG/private/qpaintengine_vg_p.h>
+#if defined(Q_WS_X11)
+#include "private/qt_x11_p.h"
+#include "qx11info_x11.h"
+#include <GL/glx.h>
+
+extern QX11Info *qt_x11Info(const QPaintDevice *pd);
+#endif
+
+// Define this to use framebuffer objects.
+//#define QVG_USE_FBO 1
+
+#include <vg/openvg.h>
+
+QT_BEGIN_NAMESPACE
+
+class QShivaContext
+{
+public:
+ QShivaContext();
+ ~QShivaContext();
+
+ bool makeCurrent(ShivaVGWindowSurfacePrivate *surface);
+ void doneCurrent();
+
+ bool initialized;
+ QSize currentSize;
+ ShivaVGWindowSurfacePrivate *currentSurface;
+};
+
+Q_GLOBAL_STATIC(QShivaContext, shivaContext);
+
+class ShivaVGWindowSurfacePrivate
+{
+public:
+ ShivaVGWindowSurfacePrivate()
+ : isCurrent(false)
+ , needsResize(true)
+ , engine(0)
+#if defined(QVG_USE_FBO)
+ , fbo(0)
+ , texture(0)
+#endif
+#if defined(Q_WS_X11)
+ , drawable(0)
+ , context(0)
+#endif
+ {
+ }
+ ~ShivaVGWindowSurfacePrivate();
+
+ void ensureContext(QWidget *widget);
+
+ QSize size;
+ bool isCurrent;
+ bool needsResize;
+ QVGPaintEngine *engine;
+#if defined(QVG_USE_FBO)
+ GLuint fbo;
+ GLuint texture;
+#endif
+#if defined(Q_WS_X11)
+ GLXDrawable drawable;
+ GLXContext context;
+#endif
+};
+
+QShivaContext::QShivaContext()
+ : initialized(false)
+ , currentSurface(0)
+{
+}
+
+QShivaContext::~QShivaContext()
+{
+ if (initialized)
+ vgDestroyContextSH();
+}
+
+bool QShivaContext::makeCurrent(ShivaVGWindowSurfacePrivate *surface)
+{
+ if (currentSurface)
+ currentSurface->isCurrent = false;
+ surface->isCurrent = true;
+ currentSurface = surface;
+ currentSize = surface->size;
+#if defined(Q_WS_X11)
+ glXMakeCurrent(X11->display, surface->drawable, surface->context);
+#endif
+ if (!initialized) {
+ if (!vgCreateContextSH(currentSize.width(), currentSize.height())) {
+ qWarning("vgCreateContextSH(%d, %d): could not create context", currentSize.width(), currentSize.height());
+ return false;
+ }
+ initialized = true;
+ } else {
+ vgResizeSurfaceSH(currentSize.width(), currentSize.height());
+ }
+#if defined(QVG_USE_FBO)
+ if (surface->fbo)
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, surface->fbo);
+ else
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+#endif
+ return true;
+}
+
+void QShivaContext::doneCurrent()
+{
+ if (currentSurface) {
+ currentSurface->isCurrent = false;
+ currentSurface = 0;
+ }
+#if defined(Q_WS_X11)
+ glXMakeCurrent(X11->display, 0, 0);
+#endif
+}
+
+ShivaVGWindowSurfacePrivate::~ShivaVGWindowSurfacePrivate()
+{
+#if defined(QVG_USE_FBO)
+ if (fbo) {
+ glDeleteTextures(1, &texture);
+ glDeleteFramebuffersEXT(1, &fbo);
+ }
+#endif
+}
+
+void ShivaVGWindowSurfacePrivate::ensureContext(QWidget *widget)
+{
+#if defined(Q_WS_X11)
+ Window win = widget->winId();
+ if (win != drawable) {
+ if (context)
+ glXDestroyContext(X11->display, context);
+ drawable = win;
+ }
+ if (context == 0) {
+ const QX11Info *xinfo = qt_x11Info(widget);
+ int spec[64];
+ int i = 0;
+ spec[i++] = GLX_DOUBLEBUFFER;
+ spec[i++] = GLX_DEPTH_SIZE;
+ spec[i++] = 1;
+ spec[i++] = GLX_STENCIL_SIZE;
+ spec[i++] = 1;
+ spec[i++] = GLX_RGBA;
+ spec[i++] = GLX_RED_SIZE;
+ spec[i++] = 1;
+ spec[i++] = GLX_GREEN_SIZE;
+ spec[i++] = 1;
+ spec[i++] = GLX_BLUE_SIZE;
+ spec[i++] = 1;
+ spec[i++] = GLX_SAMPLE_BUFFERS_ARB;
+ spec[i++] = 1;
+ spec[i++] = GLX_SAMPLES_ARB;
+ spec[i++] = 4;
+ spec[i] = XNone;
+ XVisualInfo *visual = glXChooseVisual
+ (xinfo->display(), xinfo->screen(), spec);
+ context = glXCreateContext(X11->display, visual, 0, True);
+ if (!context)
+ qWarning("glXCreateContext: could not create GL context for VG rendering");
+ }
+#else
+ Q_UNUSED(widget);
+#endif
+#if defined(QVG_USE_FBO)
+ if (needsResize && fbo) {
+#if defined(Q_WS_X11)
+ glXMakeCurrent(X11->display, drawable, context);
+#endif
+ glDeleteTextures(1, &texture);
+ glDeleteFramebuffersEXT(1, &fbo);
+#if defined(Q_WS_X11)
+ glXMakeCurrent(X11->display, 0, 0);
+#endif
+ fbo = 0;
+ texture = 0;
+ }
+ if (!fbo) {
+#if defined(Q_WS_X11)
+ glXMakeCurrent(X11->display, drawable, context);
+#endif
+ glGenFramebuffersEXT(1, &fbo);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
+
+ glGenTextures(1, &texture);
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, size.width(), size.height(), 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glFramebufferTexture2DEXT
+ (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D,
+ texture, 0);
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+#if defined(Q_WS_X11)
+ glXMakeCurrent(X11->display, 0, 0);
+#endif
+ }
+#endif
+ needsResize = false;
+}
+
+ShivaVGWindowSurface::ShivaVGWindowSurface(QWidget *window)
+ : QWindowSurface(window), d_ptr(new ShivaVGWindowSurfacePrivate)
+{
+}
+
+ShivaVGWindowSurface::~ShivaVGWindowSurface()
+{
+ if (d_ptr->isCurrent) {
+ shivaContext()->doneCurrent();
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ }
+#if defined(Q_WS_X11)
+ if (d_ptr->context)
+ glXDestroyContext(X11->display, d_ptr->context);
+#endif
+ delete d_ptr;
+}
+
+QPaintDevice *ShivaVGWindowSurface::paintDevice()
+{
+ d_ptr->ensureContext(window());
+ shivaContext()->makeCurrent(d_ptr);
+ glClearDepth(0.0f);
+ glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ return this;
+}
+
+void ShivaVGWindowSurface::flush(QWidget *widget, const QRegion &region, const QPoint &offset)
+{
+ Q_UNUSED(region);
+ Q_UNUSED(offset);
+ QWidget *parent = widget->internalWinId() ? widget : widget->nativeParentWidget();
+ d_ptr->ensureContext(parent);
+ QShivaContext *context = shivaContext();
+ if (!d_ptr->isCurrent)
+ context->makeCurrent(d_ptr);
+#if defined(QVG_USE_FBO)
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ if (d_ptr->fbo) {
+ static GLfloat const vertices[][2] = {
+ {-1, -1}, {1, -1}, {1, 1}, {-1, 1}
+ };
+ static GLfloat const texCoords[][2] = {
+ {0, 0}, {1, 0}, {1, 1}, {0, 1}
+ };
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glVertexPointer(2, GL_FLOAT, 0, vertices);
+ glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
+ glBindTexture(GL_TEXTURE_2D, d_ptr->texture);
+ glEnable(GL_TEXTURE_2D);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
+#endif
+#if defined(Q_WS_X11)
+ glXSwapBuffers(X11->display, d_ptr->drawable);
+#endif
+ context->doneCurrent();
+}
+
+void ShivaVGWindowSurface::setGeometry(const QRect &rect)
+{
+ QWindowSurface::setGeometry(rect);
+ d_ptr->needsResize = true;
+ d_ptr->size = rect.size();
+}
+
+bool ShivaVGWindowSurface::scroll(const QRegion &area, int dx, int dy)
+{
+ return QWindowSurface::scroll(area, dx, dy);
+}
+
+void ShivaVGWindowSurface::beginPaint(const QRegion &region)
+{
+ // Nothing to do here.
+ Q_UNUSED(region);
+}
+
+void ShivaVGWindowSurface::endPaint(const QRegion &region)
+{
+ // Nothing to do here.
+ Q_UNUSED(region);
+}
+
+Q_GLOBAL_STATIC(QVGPaintEngine, sharedPaintEngine);
+
+QPaintEngine *ShivaVGWindowSurface::paintEngine() const
+{
+ if (!d_ptr->engine)
+ d_ptr->engine = sharedPaintEngine();
+ return d_ptr->engine;
+}
+
+// We need to get access to QWidget::metric() from ShivaVGWindowSurface::metric,
+// but it is not a friend of QWidget. To get around this, we create a
+// fake QX11PaintEngine class, which is a friend.
+class QX11PaintEngine
+{
+public:
+ static int metric(const QWidget *widget, QPaintDevice::PaintDeviceMetric met)
+ {
+ return widget->metric(met);
+ }
+};
+
+int ShivaVGWindowSurface::metric(PaintDeviceMetric met) const
+{
+ return QX11PaintEngine::metric(window(), met);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/graphicssystems/shivavg/shivavgwindowsurface.h b/src/plugins/graphicssystems/shivavg/shivavgwindowsurface.h
new file mode 100644
index 0000000..5211ba4
--- /dev/null
+++ b/src/plugins/graphicssystems/shivavg/shivavgwindowsurface.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SHIVAVGWINDOWSURFACE_H
+#define SHIVAVGWINDOWSURFACE_H
+
+#include <QtGui/private/qwindowsurface_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class ShivaVGWindowSurfacePrivate;
+
+class ShivaVGWindowSurface : public QWindowSurface, public QPaintDevice
+{
+public:
+ ShivaVGWindowSurface(QWidget *window);
+ virtual ~ShivaVGWindowSurface();
+
+ QPaintDevice *paintDevice();
+ void flush(QWidget *widget, const QRegion &region, const QPoint &offset);
+ void setGeometry(const QRect &rect);
+ bool scroll(const QRegion &area, int dx, int dy);
+
+ void beginPaint(const QRegion &region);
+ void endPaint(const QRegion &region);
+
+ QPaintEngine *paintEngine() const;
+
+protected:
+ int metric(PaintDeviceMetric metric) const;
+
+private:
+ ShivaVGWindowSurfacePrivate *d_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/src.pro b/src/src.pro
index f40c6ad..9bff20d 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -19,6 +19,7 @@ win32:{
}
contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles1)|contains(QT_CONFIG, opengles2): SRC_SUBDIRS += src_opengl
+contains(QT_CONFIG, openvg): SRC_SUBDIRS += src_openvg
contains(QT_CONFIG, xmlpatterns): SRC_SUBDIRS += src_xmlpatterns
contains(QT_CONFIG, phonon): SRC_SUBDIRS += src_phonon
contains(QT_CONFIG, svg): SRC_SUBDIRS += src_svg
@@ -61,6 +62,8 @@ src_scripttools.subdir = $$QT_SOURCE_TREE/src/scripttools
src_scripttools.target = sub-scripttools
src_opengl.subdir = $$QT_SOURCE_TREE/src/opengl
src_opengl.target = sub-opengl
+src_openvg.subdir = $$QT_SOURCE_TREE/src/openvg
+src_openvg.target = sub-openvg
src_qt3support.subdir = $$QT_SOURCE_TREE/src/qt3support
src_qt3support.target = sub-qt3support
src_phonon.subdir = $$QT_SOURCE_TREE/src/phonon
@@ -96,6 +99,7 @@ src_webkit.target = sub-webkit
src_scripttools.depends = src_script src_gui src_network
src_network.depends = src_corelib
src_opengl.depends = src_gui
+ src_openvg.depends = src_gui
src_sql.depends = src_corelib
src_testlib.depends = src_corelib
src_qt3support.depends = src_gui src_xml src_network src_sql
diff --git a/src/svg/qsvggraphics.cpp b/src/svg/qsvggraphics.cpp
index 6782429..e09f382 100644
--- a/src/svg/qsvggraphics.cpp
+++ b/src/svg/qsvggraphics.cpp
@@ -198,9 +198,8 @@ QRectF QSvgPath::bounds() const
}
QSvgPolygon::QSvgPolygon(QSvgNode *parent, const QPolygonF &poly)
- : QSvgNode(parent), m_poly(poly)
+ : QSvgNode(parent), m_poly(poly), m_fillRule(Qt::WindingFill)
{
-
}
QRectF QSvgPolygon::bounds() const
@@ -217,7 +216,7 @@ QRectF QSvgPolygon::bounds() const
void QSvgPolygon::draw(QPainter *p, QSvgExtraStates &states)
{
- QT_SVG_DRAW_SHAPE(p->drawPolygon(m_poly));
+ QT_SVG_DRAW_SHAPE(p->drawPolygon(m_poly, m_fillRule));
}
diff --git a/src/svg/qsvggraphics_p.h b/src/svg/qsvggraphics_p.h
index 8a412c4..4a19c7e 100644
--- a/src/svg/qsvggraphics_p.h
+++ b/src/svg/qsvggraphics_p.h
@@ -155,8 +155,13 @@ public:
virtual void draw(QPainter *p, QSvgExtraStates &states);
virtual Type type() const;
virtual QRectF bounds() const;
+ void setFillRule(Qt::FillRule f)
+ {
+ m_fillRule = f;
+ }
private:
QPolygonF m_poly;
+ Qt::FillRule m_fillRule;
};
class QSvgPolyline : public QSvgNode
diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp
index e2c1312..345dcf3 100644
--- a/src/svg/qsvghandler.cpp
+++ b/src/svg/qsvghandler.cpp
@@ -497,10 +497,8 @@ static bool constructColor(const QString &colorStr, const QString &opacity,
if (!resolveColor(colorStr, color, handler))
return false;
if (!opacity.isEmpty()) {
- qreal op = toDouble(opacity);
- if (op <= 1)
- op *= 255;
- color.setAlpha(int(op));
+ qreal op = qMin(qreal(1.0), qMax(qreal(0.0), toDouble(opacity)));
+ color.setAlphaF(op);
}
return true;
}
@@ -641,15 +639,22 @@ static void parseBrush(QSvgNode *node,
f = Qt::OddEvenFill;
if (value.startsWith(QLatin1String("url"))) {
value = value.remove(0, 3);
+ QSvgFillStyle *prop = new QSvgFillStyle(0);
QSvgStyleProperty *style = styleFromUrl(node, value);
if (style) {
- QSvgFillStyle *prop = new QSvgFillStyle(style);
- if (!opacity.isEmpty())
- prop->setFillOpacity(toDouble(opacity));
- node->appendStyleProperty(prop, myId);
+ prop->setFillStyle(style);
} else {
- qWarning("Couldn't resolve property: %s", qPrintable(idFromUrl(value)));
+ QString id = idFromUrl(value);
+ prop->setGradientId(id);
+ prop->setGradientResolved(false);
}
+ if (!opacity.isEmpty()) {
+ qreal clampedOpacity = qMin(qreal(1.0), qMax(qreal(0.0), toDouble(opacity)));
+ prop->setFillOpacity(clampedOpacity);
+ }
+ if (!fillRule.isEmpty())
+ prop->setFillRule(f);
+ node->appendStyleProperty(prop,myId);
} else if (value != QLatin1String("none")) {
QColor color;
if (constructColor(value, opacity, color, handler)) {
@@ -1377,6 +1382,11 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
y = y0 = arg[1] + offsetY;
path.moveTo(x0, y0);
arg.pop_front(); arg.pop_front();
+
+ // As per 1.2 spec 8.3.2 The "moveto" commands
+ // If a 'moveto' is followed by multiple pairs of coordinates without explicit commands,
+ // the subsequent pairs shall be treated as implicit 'lineto' commands.
+ pathElem = QLatin1Char('l');
}
break;
case 'M': {
@@ -1389,6 +1399,11 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
path.moveTo(x0, y0);
arg.pop_front(); arg.pop_front();
+
+ // As per 1.2 spec 8.3.2 The "moveto" commands
+ // If a 'moveto' is followed by multiple pairs of coordinates without explicit commands,
+ // the subsequent pairs shall be treated as implicit 'lineto' commands.
+ pathElem = QLatin1Char('L');
}
break;
case 'z':
@@ -1943,7 +1958,7 @@ static void parseOpacity(QSvgNode *node,
qreal op = value.toDouble(&ok);
if (ok) {
- QSvgOpacityStyle *opacity = new QSvgOpacityStyle(op);
+ QSvgOpacityStyle *opacity = new QSvgOpacityStyle(qMin(qreal(1.0), qMax(qreal(0.0), op)));
node->appendStyleProperty(opacity, someId(attributes));
}
}
@@ -3570,8 +3585,34 @@ bool QSvgHandler::endElement(const QStringRef &localName)
node->popFormat();
}
- if (node == Graphics)
+ if (node == Graphics) {
+ // Iterate through the m_renderers to resolve any unresolved gradients.
+ QSvgNode* curNode = static_cast<QSvgNode*>(m_nodes.top());
+ if (curNode->type() == QSvgNode::DOC ||
+ curNode->type() == QSvgNode::G ||
+ curNode->type() == QSvgNode::DEFS ||
+ curNode->type() == QSvgNode::SWITCH) {
+ QSvgStructureNode* structureNode = static_cast<QSvgStructureNode*>(curNode);
+ QList<QSvgNode*> ren = structureNode->renderers();
+ QList<QSvgNode*>::iterator itr = ren.begin();
+ while (itr != ren.end()) {
+ QSvgNode *eleNode = *itr++;
+ QSvgFillStyle *prop = static_cast<QSvgFillStyle*>(eleNode->styleProperty(QSvgStyleProperty::FILL));
+ if (prop && !(prop->isGradientResolved())) {
+ QString id = prop->getGradientId();
+ QSvgStyleProperty *style = structureNode->scopeStyle(id);
+ if (style) {
+ prop->setFillStyle(style);
+ } else {
+ qWarning("Couldn't resolve property : %s",qPrintable(id));
+ prop->setBrush(QBrush(Qt::NoBrush));
+ }
+ }
+ }
+ }
m_nodes.pop();
+ }
+
else if (m_style && !m_skipNodes.isEmpty() && m_skipNodes.top() != Style)
m_style = 0;
diff --git a/src/svg/qsvgstructure.cpp b/src/svg/qsvgstructure.cpp
index 67a21bf..c1ad4bf 100644
--- a/src/svg/qsvgstructure.cpp
+++ b/src/svg/qsvgstructure.cpp
@@ -68,13 +68,11 @@ void QSvgG::draw(QPainter *p, QSvgExtraStates &states)
QList<QSvgNode*>::iterator itr = m_renderers.begin();
applyStyle(p, states);
- if (displayMode() != QSvgNode::NoneMode) {
- while (itr != m_renderers.end()) {
- QSvgNode *node = *itr;
- if (node->isVisible())
- node->draw(p, states);
- ++itr;
- }
+ while (itr != m_renderers.end()) {
+ QSvgNode *node = *itr;
+ if ((node->isVisible()) && (node->displayMode() != QSvgNode::NoneMode))
+ node->draw(p, states);
+ ++itr;
}
revertStyle(p, states);
}
@@ -321,63 +319,61 @@ void QSvgSwitch::draw(QPainter *p, QSvgExtraStates &states)
QList<QSvgNode*>::iterator itr = m_renderers.begin();
applyStyle(p, states);
- if (displayMode() != QSvgNode::NoneMode) {
- while (itr != m_renderers.end()) {
- QSvgNode *node = *itr;
- if (node->isVisible()) {
- const QStringList &features = node->requiredFeatures();
- const QStringList &extensions = node->requiredExtensions();
- const QStringList &languages = node->requiredLanguages();
- const QStringList &formats = node->requiredFormats();
- const QStringList &fonts = node->requiredFonts();
-
- bool okToRender = true;
- if (!features.isEmpty()) {
- QStringList::const_iterator sitr = features.constBegin();
- for (; sitr != features.constEnd(); ++sitr) {
- if (!isSupportedSvgFeature(*sitr)) {
- okToRender = false;
- break;
- }
+ while (itr != m_renderers.end()) {
+ QSvgNode *node = *itr;
+ if (node->isVisible() && (node->displayMode() != QSvgNode::NoneMode)) {
+ const QStringList &features = node->requiredFeatures();
+ const QStringList &extensions = node->requiredExtensions();
+ const QStringList &languages = node->requiredLanguages();
+ const QStringList &formats = node->requiredFormats();
+ const QStringList &fonts = node->requiredFonts();
+
+ bool okToRender = true;
+ if (!features.isEmpty()) {
+ QStringList::const_iterator sitr = features.constBegin();
+ for (; sitr != features.constEnd(); ++sitr) {
+ if (!isSupportedSvgFeature(*sitr)) {
+ okToRender = false;
+ break;
}
}
+ }
- if (okToRender && !extensions.isEmpty()) {
- QStringList::const_iterator sitr = extensions.constBegin();
- for (; sitr != extensions.constEnd(); ++sitr) {
- if (!isSupportedSvgExtension(*sitr)) {
- okToRender = false;
- break;
- }
+ if (okToRender && !extensions.isEmpty()) {
+ QStringList::const_iterator sitr = extensions.constBegin();
+ for (; sitr != extensions.constEnd(); ++sitr) {
+ if (!isSupportedSvgExtension(*sitr)) {
+ okToRender = false;
+ break;
}
}
+ }
- if (okToRender && !languages.isEmpty()) {
- QStringList::const_iterator sitr = languages.constBegin();
- okToRender = false;
- for (; sitr != languages.constEnd(); ++sitr) {
- if ((*sitr).startsWith(m_systemLanguagePrefix)) {
- okToRender = true;
- break;
- }
+ if (okToRender && !languages.isEmpty()) {
+ QStringList::const_iterator sitr = languages.constBegin();
+ okToRender = false;
+ for (; sitr != languages.constEnd(); ++sitr) {
+ if ((*sitr).startsWith(m_systemLanguagePrefix)) {
+ okToRender = true;
+ break;
}
}
+ }
- if (okToRender && !formats.isEmpty()) {
- okToRender = false;
- }
+ if (okToRender && !formats.isEmpty()) {
+ okToRender = false;
+ }
- if (okToRender && !fonts.isEmpty()) {
- okToRender = false;
- }
+ if (okToRender && !fonts.isEmpty()) {
+ okToRender = false;
+ }
- if (okToRender) {
- node->draw(p, states);
- break;
- }
+ if (okToRender) {
+ node->draw(p, states);
+ break;
}
- ++itr;
}
+ ++itr;
}
revertStyle(p, states);
}
diff --git a/src/svg/qsvgstyle.cpp b/src/svg/qsvgstyle.cpp
index fa996f4..fec6231 100644
--- a/src/svg/qsvgstyle.cpp
+++ b/src/svg/qsvgstyle.cpp
@@ -81,12 +81,12 @@ void QSvgQualityStyle::revert(QPainter *, QSvgExtraStates &)
}
QSvgFillStyle::QSvgFillStyle(const QBrush &brush)
- : m_fill(brush), m_style(0), m_fillRuleSet(false), m_fillOpacitySet(false)
+ : m_fill(brush), m_style(0), m_fillRuleSet(false), m_fillOpacitySet(false), m_gradientResolved (true)
{
}
QSvgFillStyle::QSvgFillStyle(QSvgStyleProperty *style)
- : m_style(style), m_fillRuleSet(false), m_fillOpacitySet(false)
+ : m_style(style), m_fillRuleSet(false), m_fillOpacitySet(false), m_gradientResolved (true)
{
}
@@ -107,6 +107,9 @@ static void recursivelySetFill(QSvgNode *node, Qt::FillRule f)
if (node->type() == QSvgNode::PATH) {
QSvgPath *path = static_cast<QSvgPath*>(node);
path->qpath()->setFillRule(f);
+ } else if (node->type() == QSvgNode::POLYGON) {
+ QSvgPolygon *polygon = static_cast<QSvgPolygon*>(node);
+ polygon->setFillRule(f);
} else if (node->type() == QSvgNode::G) {
QList<QSvgNode*> renderers = static_cast<QSvgG*>(node)->renderers();
foreach(QSvgNode *n, renderers) {
diff --git a/src/svg/qsvgstyle_p.h b/src/svg/qsvgstyle_p.h
index 4bbc6cf..e65b6f5 100644
--- a/src/svg/qsvgstyle_p.h
+++ b/src/svg/qsvgstyle_p.h
@@ -229,6 +229,38 @@ public:
{
return m_fill;
}
+
+ void setGradientId(const QString &Id)
+ {
+ m_gradientId = Id;
+ }
+
+ QString getGradientId() const
+ {
+ return m_gradientId;
+ }
+
+
+ void setGradientResolved(bool resolved)
+ {
+ m_gradientResolved = resolved;
+ }
+
+ bool isGradientResolved() const
+ {
+ return m_gradientResolved;
+ }
+
+ void setFillStyle(QSvgStyleProperty* style)
+ {
+ m_style = style;
+ }
+
+ void setBrush(QBrush brush)
+ {
+ m_fill = brush;
+ }
+
private:
// fill v v 'inherit' | <Paint.datatype>
// fill-opacity v v 'inherit' | <OpacityValue.datatype>
@@ -241,6 +273,8 @@ private:
bool m_fillOpacitySet;
qreal m_fillOpacity;
qreal m_oldOpacity;
+ QString m_gradientId;
+ bool m_gradientResolved;
};
class QSvgViewportFillStyle : public QSvgStyleProperty
diff --git a/src/svg/qsvgtinydocument.cpp b/src/svg/qsvgtinydocument.cpp
index de214bb..3058569 100644
--- a/src/svg/qsvgtinydocument.cpp
+++ b/src/svg/qsvgtinydocument.cpp
@@ -231,8 +231,10 @@ void QSvgTinyDocument::draw(QPainter *p, const QRectF &bounds)
m_time.start();
}
- p->save();
+ if (displayMode() == QSvgNode::NoneMode)
+ return;
+ p->save();
//sets default style on the painter
//### not the most optimal way
mapSourceToTarget(p, bounds);
@@ -244,7 +246,7 @@ void QSvgTinyDocument::draw(QPainter *p, const QRectF &bounds)
applyStyle(p, m_states);
while (itr != m_renderers.end()) {
QSvgNode *node = *itr;
- if (node->isVisible())
+ if ((node->isVisible()) && (node->displayMode() != QSvgNode::NoneMode))
node->draw(p, m_states);
++itr;
}
@@ -262,6 +264,12 @@ void QSvgTinyDocument::draw(QPainter *p, const QString &id,
qDebug("Couldn't find node %s. Skipping rendering.", qPrintable(id));
return;
}
+ if (m_time.isNull()) {
+ m_time.start();
+ }
+
+ if (node->displayMode() == QSvgNode::NoneMode)
+ return;
p->save();
diff --git a/src/testlib/qtestlog.cpp b/src/testlib/qtestlog.cpp
index 4a9675a..64c1312 100644
--- a/src/testlib/qtestlog.cpp
+++ b/src/testlib/qtestlog.cpp
@@ -139,7 +139,7 @@ namespace QTest {
if (!counter.deref()) {
QTest::testLogger->addMessage(QAbstractTestLogger::QSystem,
- "Maximum amount of warnings exceeded.");
+ "Maximum amount of warnings exceeded. Use -maxwarnings to override.");
return;
}
}