OpenVG Scenegraph Adaptation

This is an OpenVG backend for the Qt Quick 2 scenegraph.

Should be feature complete now, but there are still some issues that
could be improved in future commits:

If Rectangle nodes are rendered with a non-affine transform, they will
be rendered incorrectly.  This is because paths expect affine
transformations.

The Glyph cache is a bit cheeky in that it's caching paths, but doing
so per font size.  It shoudln't need to, but right now I've not though
up a good way of getting the transform/scale needed when rendering yet.

Change-Id: Ie3c4f2df35d14279b0f9f55e0e10a873328c025b
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
This commit is contained in:
Andy Nichols 2016-04-03 18:06:46 +02:00
parent bff7302fc2
commit 3f57f2b7cc
42 changed files with 6128 additions and 1 deletions

View File

@ -0,0 +1,3 @@
{
"Keys": ["openvg"]
}

View File

@ -0,0 +1,54 @@
TARGET = qsgopenvgbackend
QT += gui-private core-private qml-private quick-private
PLUGIN_TYPE = scenegraph
PLUGIN_CLASS_NAME = QSGOpenVGAdaptation
load(qt_plugin)
QMAKE_TARGET_PRODUCT = "Qt Quick OpenVG Renderer (Qt $$QT_VERSION)"
QMAKE_TARGET_DESCRIPTION = "Quick OpenVG Renderer for Qt."
QMAKE_USE += openvg
OTHER_FILES += $$PWD/openvg.json
HEADERS += \
qsgopenvgadaptation_p.h \
qsgopenvgcontext_p.h \
qsgopenvgrenderloop_p.h \
qsgopenvgglyphnode_p.h \
qopenvgcontext_p.h \
qsgopenvgrenderer_p.h \
qsgopenvginternalrectanglenode.h \
qsgopenvgnodevisitor.h \
qopenvgmatrix.h \
qsgopenvgpublicnodes.h \
qsgopenvginternalimagenode.h \
qsgopenvgtexture.h \
qsgopenvglayer.h \
qsgopenvghelpers.h \
qsgopenvgfontglyphcache.h \
qsgopenvgpainternode.h \
qsgopenvgspritenode.h \
qsgopenvgrenderable.h
SOURCES += \
qsgopenvgadaptation.cpp \
qsgopenvgcontext.cpp \
qsgopenvgrenderloop.cpp \
qsgopenvgglyphnode.cpp \
qopenvgcontext.cpp \
qsgopenvgrenderer.cpp \
qsgopenvginternalrectanglenode.cpp \
qsgopenvgnodevisitor.cpp \
qopenvgmatrix.cpp \
qsgopenvgpublicnodes.cpp \
qsgopenvginternalimagenode.cpp \
qsgopenvgtexture.cpp \
qsgopenvglayer.cpp \
qsgopenvghelpers.cpp \
qsgopenvgfontglyphcache.cpp \
qsgopenvgpainternode.cpp \
qsgopenvgspritenode.cpp \
qsgopenvgrenderable.cpp

View File

@ -0,0 +1,218 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <qpa/qplatformnativeinterface.h>
#include <QtGui/QGuiApplication>
#include <QtCore/QVector>
#include <QtCore/QDebug>
#include "qopenvgcontext_p.h"
QT_BEGIN_NAMESPACE
QOpenVGContext::QOpenVGContext(QWindow *window)
: m_window(window)
{
QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
m_display = reinterpret_cast<EGLDisplay>(nativeInterface->nativeResourceForWindow("EglDisplay", window));
m_surface = reinterpret_cast<EGLSurface>(nativeInterface->nativeResourceForWindow("EglSurface", window));
if (m_display == 0)
qFatal("QOpenVGContext: failed to get EGLDisplay");
if (m_surface == 0)
qFatal("QOpenVGContext: failed to get EGLSurface");
EGLint configID = 0;
if (eglQuerySurface(m_display, m_surface, EGL_CONFIG_ID, &configID)) {
EGLint numConfigs;
const EGLint configAttribs[] = {
EGL_CONFIG_ID, configID,
EGL_NONE
};
eglChooseConfig(m_display, configAttribs, &m_config, 1, &numConfigs);
} else {
qFatal("QOpenVGContext: failed to get surface config");
}
// Create an EGL Context
eglBindAPI(EGL_OPENVG_API);
m_context = eglCreateContext(m_display, m_config, EGL_NO_CONTEXT, 0);
if (!m_context)
qFatal("QOpenVGContext: eglCreateContext failed");
}
QOpenVGContext::~QOpenVGContext()
{
doneCurrent();
eglDestroyContext(m_display, m_context);
}
void QOpenVGContext::makeCurrent()
{
makeCurrent(m_surface);
}
void QOpenVGContext::makeCurrent(EGLSurface surface)
{
eglMakeCurrent(m_display, surface, surface, m_context);
}
void QOpenVGContext::doneCurrent()
{
eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
}
void QOpenVGContext::swapBuffers()
{
swapBuffers(m_surface);
}
void QOpenVGContext::swapBuffers(EGLSurface surface)
{
eglSwapBuffers(m_display, surface);
}
QWindow *QOpenVGContext::window() const
{
return m_window;
}
QImage QOpenVGContext::readFramebuffer(const QSize &size)
{
QImage framebufferImage(size, QImage::Format_RGB32);
vgReadPixels(framebufferImage.bits(), framebufferImage.bytesPerLine(), VG_sXRGB_8888, 0, 0, size.width(), size.height());
return framebufferImage.mirrored(false, true);
}
void QOpenVGContext::getConfigs()
{
EGLint configsAvailable = 0;
eglGetConfigs(m_display, 0, 0, &configsAvailable);
QVector<EGLConfig> configs(configsAvailable);
eglGetConfigs(m_display, configs.data(), configs.size(), &configsAvailable);
for (EGLConfig config : configs) {
EGLint value;
eglGetConfigAttrib(m_display, config, EGL_CONFIG_ID, &value);
qDebug() << "#################\n" << "EGL_CONFIG_ID:" << value;
eglGetConfigAttrib(m_display, config, EGL_BUFFER_SIZE, &value);
qDebug() << "EGL_BUFFER_SIZE:" << value;
eglGetConfigAttrib(m_display, config, EGL_ALPHA_SIZE, &value);
qDebug() << "EGL_ALPHA_SIZE:" << value;
eglGetConfigAttrib(m_display, config, EGL_RED_SIZE, &value);
qDebug() << "EGL_RED_SIZE:" << value;
eglGetConfigAttrib(m_display, config, EGL_GREEN_SIZE, &value);
qDebug() << "EGL_GREEN_SIZE:" << value;
eglGetConfigAttrib(m_display, config, EGL_BLUE_SIZE, &value);
qDebug() << "EGL_BLUE_SIZE:" << value;
eglGetConfigAttrib(m_display, config, EGL_DEPTH_SIZE, &value);
qDebug() << "EGL_DEPTH_SIZE:" << value;
eglGetConfigAttrib(m_display, config, EGL_STENCIL_SIZE, &value);
qDebug() << "EGL_STENCIL_SIZE:" << value;
eglGetConfigAttrib(m_display, config, EGL_ALPHA_MASK_SIZE, &value);
qDebug() << "EGL_ALPHA_MASK_SIZE:" << value;
eglGetConfigAttrib(m_display, config, EGL_BIND_TO_TEXTURE_RGB, &value);
qDebug() << "EGL_BIND_TO_TEXTURE_RGB:" << value;
eglGetConfigAttrib(m_display, config, EGL_BIND_TO_TEXTURE_RGBA, &value);
qDebug() << "EGL_BIND_TO_TEXTURE_RGBA:" << value;
eglGetConfigAttrib(m_display, config, EGL_COLOR_BUFFER_TYPE, &value);
qDebug() << "EGL_COLOR_BUFFER_TYPE:" << value;
eglGetConfigAttrib(m_display, config, EGL_CONFIG_CAVEAT, &value);
qDebug() << "EGL_CONFIG_CAVEAT:" << value;
eglGetConfigAttrib(m_display, config, EGL_CONFORMANT, &value);
qDebug() << "EGL_CONFORMANT:" << value;
eglGetConfigAttrib(m_display, config, EGL_LEVEL, &value);
qDebug() << "EGL_LEVEL:" << value;
eglGetConfigAttrib(m_display, config, EGL_LUMINANCE_SIZE, &value);
qDebug() << "EGL_LUMINANCE_SIZE:" << value;
eglGetConfigAttrib(m_display, config, EGL_MAX_PBUFFER_WIDTH, &value);
qDebug() << "EGL_MAX_PBUFFER_WIDTH:" << value;
eglGetConfigAttrib(m_display, config, EGL_MAX_PBUFFER_HEIGHT, &value);
qDebug() << "EGL_MAX_PBUFFER_HEIGHT:" << value;
eglGetConfigAttrib(m_display, config, EGL_MAX_PBUFFER_PIXELS, &value);
qDebug() << "EGL_MAX_PBUFFER_PIXELS:" << value;
eglGetConfigAttrib(m_display, config, EGL_MAX_SWAP_INTERVAL, &value);
qDebug() << "EGL_MAX_SWAP_INTERVAL:" << value;
eglGetConfigAttrib(m_display, config, EGL_MIN_SWAP_INTERVAL, &value);
qDebug() << "EGL_MIN_SWAP_INTERVAL:" << value;
eglGetConfigAttrib(m_display, config, EGL_NATIVE_RENDERABLE, &value);
qDebug() << "EGL_NATIVE_RENDERABLE:" << value;
eglGetConfigAttrib(m_display, config, EGL_NATIVE_VISUAL_ID, &value);
qDebug() << "EGL_NATIVE_VISUAL_ID:" << value;
eglGetConfigAttrib(m_display, config, EGL_NATIVE_VISUAL_TYPE, &value);
qDebug() << "EGL_NATIVE_VISUAL_TYPE:" << value;
eglGetConfigAttrib(m_display, config, EGL_RENDERABLE_TYPE, &value);
qDebug() << "EGL_RENDERABLE_TYPE:" << value;
eglGetConfigAttrib(m_display, config, EGL_SAMPLE_BUFFERS, &value);
qDebug() << "EGL_SAMPLE_BUFFERS:" << value;
eglGetConfigAttrib(m_display, config, EGL_SAMPLES, &value);
qDebug() << "EGL_SAMPLES:" << value;
eglGetConfigAttrib(m_display, config, EGL_SURFACE_TYPE, &value);
qDebug() << "EGL_SURFACE_TYPE:" << value;
eglGetConfigAttrib(m_display, config, EGL_TRANSPARENT_TYPE, &value);
qDebug() << "EGL_TRANSPARENT_TYPE:" << value;
eglGetConfigAttrib(m_display, config, EGL_TRANSPARENT_RED_VALUE, &value);
qDebug() << "EGL_TRANSPARENT_RED_VALUE:" << value;
eglGetConfigAttrib(m_display, config, EGL_TRANSPARENT_GREEN_VALUE, &value);
qDebug() << "EGL_TRANSPARENT_GREEN_VALUE:" << value;
eglGetConfigAttrib(m_display, config, EGL_TRANSPARENT_BLUE_VALUE, &value);
qDebug() << "EGL_TRANSPARENT_BLUE_VALUE:" << value;
}
}
void QOpenVGContext::checkErrors()
{
VGErrorCode error;
EGLint eglError;
do {
error = vgGetError();
eglError = eglGetError();
qDebug() << "error: " << QString::number(error, 16);
qDebug() << "eglError: " << QString::number(eglError, 16);
} while (error != VG_NO_ERROR && eglError != EGL_SUCCESS);
}
QT_END_NAMESPACE

View File

@ -0,0 +1,88 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QOPENVGCONTEXT_H
#define QOPENVGCONTEXT_H
#include <QtGui/QWindow>
#include <QtGui/QImage>
#include <EGL/egl.h>
#include <VG/openvg.h>
QT_BEGIN_NAMESPACE
class QOpenVGContext
{
public:
QOpenVGContext(QWindow *window);
~QOpenVGContext();
void makeCurrent();
void makeCurrent(EGLSurface surface);
void doneCurrent();
void swapBuffers();
void swapBuffers(EGLSurface surface);
QWindow *window() const;
EGLDisplay eglDisplay() { return m_display; }
EGLConfig eglConfig() { return m_config; }
EGLContext eglContext() { return m_context; }
QImage readFramebuffer(const QSize &size);
void getConfigs();
static void checkErrors();
private:
EGLSurface m_surface;
EGLDisplay m_display;
EGLConfig m_config;
EGLContext m_context;
QWindow *m_window;
};
QT_END_NAMESPACE
#endif // QOPENVGCONTEXT_H

View File

@ -0,0 +1,325 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qopenvgmatrix.h"
QT_BEGIN_NAMESPACE
// QOpenVGMatrix: Because Qt will never have enough matrix classes
// Internally the data is stored as column-major format
// So this is a 3x3 version of QMatrix4x4 for optimal
// OpenVG usage.
QOpenVGMatrix::QOpenVGMatrix()
{
setToIdentity();
}
QOpenVGMatrix::QOpenVGMatrix(const float *values)
{
for (int col = 0; col < 3; ++col)
for (int row = 0; row < 3; ++row)
m[col][row] = values[col * 3 + row];
}
const float &QOpenVGMatrix::operator()(int row, int column) const
{
Q_ASSERT(row >= 0 && row < 4 && column >= 0 && column < 4);
return m[column][row];
}
float &QOpenVGMatrix::operator()(int row, int column)
{
Q_ASSERT(row >= 0 && row < 4 && column >= 0 && column < 4);
return m[column][row];
}
bool QOpenVGMatrix::isIdentity() const
{
if (m[0][0] != 1.0f || m[0][1] != 0.0f || m[0][2] != 0.0f)
return false;
if ( m[1][0] != 0.0f || m[1][1] != 1.0f)
return false;
if (m[1][2] != 0.0f || m[2][0] != 0.0f)
return false;
if (m[2][1] != 0.0f || m[2][2] != 1.0f)
return false;
return true;
}
void QOpenVGMatrix::setToIdentity()
{
m[0][0] = 1.0f;
m[0][1] = 0.0f;
m[0][2] = 0.0f;
m[1][0] = 0.0f;
m[1][1] = 1.0f;
m[1][2] = 0.0f;
m[2][0] = 0.0f;
m[2][1] = 0.0f;
m[2][2] = 1.0f;
}
void QOpenVGMatrix::fill(float value)
{
m[0][0] = value;
m[0][1] = value;
m[0][2] = value;
m[1][0] = value;
m[1][1] = value;
m[1][2] = value;
m[2][0] = value;
m[2][1] = value;
m[2][2] = value;
}
QOpenVGMatrix QOpenVGMatrix::transposed() const
{
QOpenVGMatrix result;
for (int row = 0; row < 3; ++row) {
for (int col = 0; col < 3; ++col)
result.m[col][row] = m[row][col];
}
return result;
}
QOpenVGMatrix &QOpenVGMatrix::operator+=(const QOpenVGMatrix &other)
{
m[0][0] += other.m[0][0];
m[0][1] += other.m[0][1];
m[0][2] += other.m[0][2];
m[1][0] += other.m[1][0];
m[1][1] += other.m[1][1];
m[1][2] += other.m[1][2];
m[2][0] += other.m[2][0];
m[2][1] += other.m[2][1];
m[2][2] += other.m[2][2];
return *this;
}
QOpenVGMatrix &QOpenVGMatrix::operator-=(const QOpenVGMatrix &other)
{
m[0][0] -= other.m[0][0];
m[0][1] -= other.m[0][1];
m[0][2] -= other.m[0][2];
m[1][0] -= other.m[1][0];
m[1][1] -= other.m[1][1];
m[1][2] -= other.m[1][2];
m[2][0] -= other.m[2][0];
m[2][1] -= other.m[2][1];
m[2][2] -= other.m[2][2];
return *this;
}
QOpenVGMatrix &QOpenVGMatrix::operator*=(const QOpenVGMatrix &other)
{
float m0, m1;
m0 = m[0][0] * other.m[0][0]
+ m[1][0] * other.m[0][1]
+ m[2][0] * other.m[0][2];
m1 = m[0][0] * other.m[1][0]
+ m[1][0] * other.m[1][1]
+ m[2][0] * other.m[1][2];
m[2][0] = m[0][0] * other.m[2][0]
+ m[1][0] * other.m[2][1]
+ m[2][0] * other.m[2][2];
m[0][0] = m0;
m[1][0] = m1;
m0 = m[0][1] * other.m[0][0]
+ m[1][1] * other.m[0][1]
+ m[2][1] * other.m[0][2];
m1 = m[0][1] * other.m[1][0]
+ m[1][1] * other.m[1][1]
+ m[2][1] * other.m[1][2];
m[2][1] = m[0][1] * other.m[2][0]
+ m[1][1] * other.m[2][1]
+ m[2][1] * other.m[2][2];
m[0][1] = m0;
m[1][1] = m1;
m0 = m[0][2] * other.m[0][0]
+ m[1][2] * other.m[0][1]
+ m[2][2] * other.m[0][2];
m1 = m[0][2] * other.m[1][0]
+ m[1][2] * other.m[1][1]
+ m[2][2] * other.m[1][2];
m[2][2] = m[0][2] * other.m[2][0]
+ m[1][2] * other.m[2][1]
+ m[2][2] * other.m[2][2];
m[0][2] = m0;
m[1][2] = m1;
return *this;
}
QOpenVGMatrix &QOpenVGMatrix::operator*=(float factor)
{
m[0][0] *= factor;
m[0][1] *= factor;
m[0][2] *= factor;
m[1][0] *= factor;
m[1][1] *= factor;
m[1][2] *= factor;
m[2][0] *= factor;
m[2][1] *= factor;
m[2][2] *= factor;
return *this;
}
QOpenVGMatrix &QOpenVGMatrix::operator/=(float divisor)
{
m[0][0] /= divisor;
m[0][1] /= divisor;
m[0][2] /= divisor;
m[1][0] /= divisor;
m[1][1] /= divisor;
m[1][2] /= divisor;
m[2][0] /= divisor;
m[2][1] /= divisor;
m[2][2] /= divisor;
return *this;
}
bool QOpenVGMatrix::operator==(const QOpenVGMatrix &other) const
{
return m[0][0] == other.m[0][0] &&
m[0][1] == other.m[0][1] &&
m[0][2] == other.m[0][2] &&
m[1][0] == other.m[1][0] &&
m[1][1] == other.m[1][1] &&
m[1][2] == other.m[1][2] &&
m[2][0] == other.m[2][0] &&
m[2][1] == other.m[2][1] &&
m[2][2] == other.m[2][2];
}
bool QOpenVGMatrix::operator!=(const QOpenVGMatrix &other) const
{
return m[0][0] != other.m[0][0] ||
m[0][1] != other.m[0][1] ||
m[0][2] != other.m[0][2] ||
m[1][0] != other.m[1][0] ||
m[1][1] != other.m[1][1] ||
m[1][2] != other.m[1][2] ||
m[2][0] != other.m[2][0] ||
m[2][1] != other.m[2][1] ||
m[2][2] != other.m[2][2];
}
void QOpenVGMatrix::copyDataTo(float *values) const
{
// Row-Major?
for (int row = 0; row < 3; ++row) {
for (int col = 0; col < 3; ++col)
values[row * 3 + col] = float(m[col][row]);
}
}
QOpenVGMatrix operator*(const QOpenVGMatrix &m1, const QOpenVGMatrix &m2)
{
QOpenVGMatrix matrix;
matrix.m[0][0] = m1.m[0][0] * m2.m[0][0]
+ m1.m[1][0] * m2.m[0][1]
+ m1.m[2][0] * m2.m[0][2];
matrix.m[0][1] = m1.m[0][1] * m2.m[0][0]
+ m1.m[1][1] * m2.m[0][1]
+ m1.m[2][1] * m2.m[0][2];
matrix.m[0][2] = m1.m[0][2] * m2.m[0][0]
+ m1.m[1][2] * m2.m[0][1]
+ m1.m[2][2] * m2.m[0][2];
matrix.m[1][0] = m1.m[0][0] * m2.m[1][0]
+ m1.m[1][0] * m2.m[1][1]
+ m1.m[2][0] * m2.m[1][2];
matrix.m[1][1] = m1.m[0][1] * m2.m[1][0]
+ m1.m[1][1] * m2.m[1][1]
+ m1.m[2][1] * m2.m[1][2];
matrix.m[1][2] = m1.m[0][2] * m2.m[1][0]
+ m1.m[1][2] * m2.m[1][1]
+ m1.m[2][2] * m2.m[1][2];
matrix.m[2][0] = m1.m[0][0] * m2.m[2][0]
+ m1.m[1][0] * m2.m[2][1]
+ m1.m[2][0] * m2.m[2][2];
matrix.m[2][1] = m1.m[0][1] * m2.m[2][0]
+ m1.m[1][1] * m2.m[2][1]
+ m1.m[2][1] * m2.m[2][2];
matrix.m[2][2] = m1.m[0][2] * m2.m[2][0]
+ m1.m[1][2] * m2.m[2][1]
+ m1.m[2][2] * m2.m[2][2];
return matrix;
}
QDebug operator<<(QDebug dbg, const QOpenVGMatrix &m)
{
QDebugStateSaver saver(dbg);
// Output in row-major order because it is more human-readable.
dbg.nospace() << "QOpenVGMatrix:(" << endl
<< qSetFieldWidth(10)
<< m(0, 0) << m(0, 1) << m(0, 2) << endl
<< m(1, 0) << m(1, 1) << m(1, 2) << endl
<< m(2, 0) << m(2, 1) << m(2, 2) << endl
<< qSetFieldWidth(0) << ')';
return dbg;
}
QDataStream &operator<<(QDataStream &stream, const QOpenVGMatrix &matrix)
{
for (int row = 0; row < 3; ++row)
for (int col = 0; col < 3; ++col)
stream << matrix(row, col);
return stream;
}
QDataStream &operator>>(QDataStream &stream, QOpenVGMatrix &matrix)
{
float x;
for (int row = 0; row < 4; ++row) {
for (int col = 0; col < 4; ++col) {
stream >> x;
matrix(row, col) = x;
}
}
return stream;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,99 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QOPENVGMATRIX_H
#define QOPENVGMATRIX_H
#include <QtCore/qdebug.h>
#include <QtCore/QDataStream>
QT_BEGIN_NAMESPACE
class QOpenVGMatrix
{
public:
QOpenVGMatrix();
explicit QOpenVGMatrix(const float *values);
const float& operator()(int row, int column) const;
float& operator()(int row, int column);
bool isIdentity() const;
void setToIdentity();
void fill(float value);
QOpenVGMatrix transposed() const;
QOpenVGMatrix& operator+=(const QOpenVGMatrix& other);
QOpenVGMatrix& operator-=(const QOpenVGMatrix& other);
QOpenVGMatrix& operator*=(const QOpenVGMatrix& other);
QOpenVGMatrix& operator*=(float factor);
QOpenVGMatrix& operator/=(float divisor);
friend QOpenVGMatrix operator*(const QOpenVGMatrix& m1, const QOpenVGMatrix& m2);
#ifndef QT_NO_DEBUG_STREAM
friend QDebug operator<<(QDebug dbg, const QOpenVGMatrix &m);
#endif
bool operator==(const QOpenVGMatrix& other) const;
bool operator!=(const QOpenVGMatrix& other) const;
void copyDataTo(float *values) const;
float *data() { return *m; }
const float *data() const { return *m; }
const float *constData() const { return *m; }
private:
float m[3][3];
};
QOpenVGMatrix operator*(const QOpenVGMatrix& m1, const QOpenVGMatrix& m2);
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QOpenVGMatrix &m);
#endif
#ifndef QT_NO_DATASTREAM
QDataStream &operator<<(QDataStream &, const QOpenVGMatrix &);
QDataStream &operator>>(QDataStream &, QOpenVGMatrix &);
#endif
QT_END_NAMESPACE
#endif // QOPENVGMATRIX_H

View File

@ -0,0 +1,78 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsgopenvgadaptation_p.h"
#include "qsgopenvgcontext_p.h"
#include "qsgopenvgrenderloop_p.h"
QT_BEGIN_NAMESPACE
QSGOpenVGAdaptation::QSGOpenVGAdaptation(QObject *parent)
: QSGContextPlugin(parent)
{
}
QStringList QSGOpenVGAdaptation::keys() const
{
return QStringList() << QLatin1String("openvg");
}
QSGContext *QSGOpenVGAdaptation::create(const QString &key) const
{
Q_UNUSED(key)
if (!instance)
instance = new QSGOpenVGContext();
return instance;
}
QSGRenderLoop *QSGOpenVGAdaptation::createWindowManager()
{
return new QSGOpenVGRenderLoop();
}
QSGContextFactoryInterface::Flags QSGOpenVGAdaptation::flags(const QString &key) const
{
Q_UNUSED(key)
return 0;
}
QSGOpenVGContext *QSGOpenVGAdaptation::instance = nullptr;
QT_END_NAMESPACE

View File

@ -0,0 +1,68 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSGOPENVGADAPTATION_H
#define QSGOPENVGADAPTATION_H
#include <private/qsgcontextplugin_p.h>
QT_BEGIN_NAMESPACE
class QSGContext;
class QSGRenderLoop;
class QSGOpenVGContext;
class QSGOpenVGAdaptation : public QSGContextPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QSGContextFactoryInterface" FILE "openvg.json")
public:
QSGOpenVGAdaptation(QObject *parent = nullptr);
QStringList keys() const override;
QSGContext *create(const QString &key) const override;
QSGRenderLoop *createWindowManager() override;
Flags flags(const QString &key) const override;
private:
static QSGOpenVGContext *instance;
};
QT_END_NAMESPACE
#endif // QSGOPENVGADAPTATION_H

View File

@ -0,0 +1,219 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsgopenvgcontext_p.h"
#include "qsgopenvgrenderer_p.h"
#include "qsgopenvginternalrectanglenode.h"
#include "qsgopenvginternalimagenode.h"
#include "qsgopenvgpublicnodes.h"
#include "qsgopenvgtexture.h"
#include "qsgopenvglayer.h"
#include "qsgopenvgglyphnode_p.h"
#include "qsgopenvgfontglyphcache.h"
#include "qsgopenvgpainternode.h"
#include "qsgopenvgspritenode.h"
#include "qopenvgcontext_p.h"
#include <private/qsgrenderer_p.h>
// polish, animations, sync, render and swap in the render loop
Q_LOGGING_CATEGORY(QSG_OPENVG_LOG_TIME_RENDERLOOP, "qt.scenegraph.time.renderloop")
QT_BEGIN_NAMESPACE
QSGOpenVGRenderContext::QSGOpenVGRenderContext(QSGContext *context)
: QSGRenderContext(context)
, m_vgContext(nullptr)
, m_glyphCacheManager(nullptr)
{
}
void QSGOpenVGRenderContext::initialize(void *context)
{
m_vgContext = static_cast<QOpenVGContext*>(context);
QSGRenderContext::initialize(context);
}
void QSGOpenVGRenderContext::invalidate()
{
m_vgContext = nullptr;
delete m_glyphCacheManager;
m_glyphCacheManager = nullptr;
QSGRenderContext::invalidate();
}
void QSGOpenVGRenderContext::renderNextFrame(QSGRenderer *renderer, uint fboId)
{
renderer->renderScene(fboId);
}
QSGTexture *QSGOpenVGRenderContext::createTexture(const QImage &image, uint flags) const
{
QImage tmp = image;
// Make sure image is not larger than maxTextureSize
int maxSize = maxTextureSize();
if (tmp.width() > maxSize || tmp.height() > maxSize) {
tmp = tmp.scaled(qMin(maxSize, tmp.width()), qMin(maxSize, tmp.height()), Qt::IgnoreAspectRatio, Qt::FastTransformation);
}
return new QSGOpenVGTexture(tmp, flags);
}
QSGRenderer *QSGOpenVGRenderContext::createRenderer()
{
return new QSGOpenVGRenderer(this);
}
QSGOpenVGContext::QSGOpenVGContext(QObject *parent)
{
Q_UNUSED(parent)
}
QSGRenderContext *QSGOpenVGContext::createRenderContext()
{
return new QSGOpenVGRenderContext(this);
}
QSGRectangleNode *QSGOpenVGContext::createRectangleNode()
{
return new QSGOpenVGRectangleNode;
}
QSGImageNode *QSGOpenVGContext::createImageNode()
{
return new QSGOpenVGImageNode;
}
QSGPainterNode *QSGOpenVGContext::createPainterNode(QQuickPaintedItem *item)
{
Q_UNUSED(item)
return new QSGOpenVGPainterNode(item);
}
QSGGlyphNode *QSGOpenVGContext::createGlyphNode(QSGRenderContext *rc, bool preferNativeGlyphNode)
{
Q_UNUSED(preferNativeGlyphNode)
return new QSGOpenVGGlyphNode(rc);
}
QSGNinePatchNode *QSGOpenVGContext::createNinePatchNode()
{
return new QSGOpenVGNinePatchNode;
}
QSGLayer *QSGOpenVGContext::createLayer(QSGRenderContext *renderContext)
{
return new QSGOpenVGLayer(renderContext);
}
QSurfaceFormat QSGOpenVGContext::defaultSurfaceFormat() const
{
QSurfaceFormat format = QSurfaceFormat::defaultFormat();
format.setRenderableType(QSurfaceFormat::OpenVG);
format.setMajorVersion(1);
return format;
}
QSGInternalRectangleNode *QSGOpenVGContext::createInternalRectangleNode()
{
return new QSGOpenVGInternalRectangleNode();
}
QSGInternalImageNode *QSGOpenVGContext::createInternalImageNode()
{
return new QSGOpenVGInternalImageNode();
}
int QSGOpenVGRenderContext::maxTextureSize() const
{
VGint width = vgGeti(VG_MAX_IMAGE_WIDTH);
VGint height = vgGeti(VG_MAX_IMAGE_HEIGHT);
return qMin(width, height);
}
QSGSpriteNode *QSGOpenVGContext::createSpriteNode()
{
return new QSGOpenVGSpriteNode();
}
QSGRendererInterface *QSGOpenVGContext::rendererInterface(QSGRenderContext *renderContext)
{
return static_cast<QSGOpenVGRenderContext *>(renderContext);
}
QSGRendererInterface::GraphicsApi QSGOpenVGRenderContext::graphicsApi() const
{
return OpenVG;
}
QSGRendererInterface::ShaderType QSGOpenVGRenderContext::shaderType() const
{
return UnknownShadingLanguage;
}
QSGRendererInterface::ShaderCompilationTypes QSGOpenVGRenderContext::shaderCompilationType() const
{
return 0;
}
QSGRendererInterface::ShaderSourceTypes QSGOpenVGRenderContext::shaderSourceType() const
{
return 0;
}
QSGOpenVGFontGlyphCache *QSGOpenVGRenderContext::glyphCache(const QRawFont &rawFont)
{
if (!m_glyphCacheManager)
m_glyphCacheManager = new QSGOpenVGFontGlyphCacheManager;
QSGOpenVGFontGlyphCache *cache = m_glyphCacheManager->cache(rawFont);
if (!cache) {
cache = new QSGOpenVGFontGlyphCache(m_glyphCacheManager, rawFont);
m_glyphCacheManager->insertCache(rawFont, cache);
}
return cache;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,104 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSGOPENVGCONTEXT_H
#define QSGOPENVGCONTEXT_H
#include <private/qsgcontext_p.h>
#include <qsgrendererinterface.h>
Q_DECLARE_LOGGING_CATEGORY(QSG_OPENVG_LOG_TIME_RENDERLOOP)
QT_BEGIN_NAMESPACE
class QOpenVGContext;
class QSGOpenVGFontGlyphCache;
class QSGOpenVGFontGlyphCacheManager;
class QSGOpenVGRenderContext : public QSGRenderContext, public QSGRendererInterface
{
Q_OBJECT
public:
QSGOpenVGRenderContext(QSGContext *context);
void initialize(void *context) override;
void invalidate() override;
void renderNextFrame(QSGRenderer *renderer, uint fboId) override;
QSGTexture *createTexture(const QImage &image, uint flags) const override;
QSGRenderer *createRenderer() override;
int maxTextureSize() const override;
// QSGRendererInterface interface
GraphicsApi graphicsApi() const override;
ShaderType shaderType() const override;
ShaderCompilationTypes shaderCompilationType() const override;
ShaderSourceTypes shaderSourceType() const override;
QOpenVGContext* vgContext() { return m_vgContext; }
QSGOpenVGFontGlyphCache* glyphCache(const QRawFont &rawFont);
private:
QOpenVGContext *m_vgContext;
QSGOpenVGFontGlyphCacheManager *m_glyphCacheManager;
};
class QSGOpenVGContext : public QSGContext
{
Q_OBJECT
public:
QSGOpenVGContext(QObject *parent = nullptr);
QSGRenderContext *createRenderContext() override;
QSGRectangleNode *createRectangleNode() override;
QSGImageNode *createImageNode() override;
QSGPainterNode *createPainterNode(QQuickPaintedItem *item) override;
QSGGlyphNode *createGlyphNode(QSGRenderContext *rc, bool preferNativeGlyphNode) override;
QSGNinePatchNode *createNinePatchNode() override;
QSGLayer *createLayer(QSGRenderContext *renderContext) override;
QSurfaceFormat defaultSurfaceFormat() const override;
QSGInternalRectangleNode *createInternalRectangleNode() override;
QSGInternalImageNode *createInternalImageNode() override;
QSGSpriteNode *createSpriteNode() override;
QSGRendererInterface *rendererInterface(QSGRenderContext *renderContext) override;
};
#endif // QSGOPENVGCONTEXT_H
QT_END_NAMESPACE

View File

@ -0,0 +1,185 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsgopenvgfontglyphcache.h"
#include "qsgopenvghelpers.h"
#include <private/qfontengine_p.h>
#include <private/qrawfont_p.h>
QT_BEGIN_NAMESPACE
QSGOpenVGFontGlyphCacheManager::QSGOpenVGFontGlyphCacheManager()
{
}
QSGOpenVGFontGlyphCacheManager::~QSGOpenVGFontGlyphCacheManager()
{
qDeleteAll(m_caches);
}
QSGOpenVGFontGlyphCache *QSGOpenVGFontGlyphCacheManager::cache(const QRawFont &font)
{
return m_caches.value(fontKey(font), nullptr);
}
void QSGOpenVGFontGlyphCacheManager::insertCache(const QRawFont &font, QSGOpenVGFontGlyphCache *cache)
{
m_caches.insert(fontKey(font), cache);
}
QString QSGOpenVGFontGlyphCacheManager::fontKey(const QRawFont &font)
{
QFontEngine *fe = QRawFontPrivate::get(font)->fontEngine;
if (!fe->faceId().filename.isEmpty()) {
QByteArray keyName = fe->faceId().filename;
if (font.style() != QFont::StyleNormal)
keyName += QByteArray(" I");
if (font.weight() != QFont::Normal)
keyName += ' ' + QByteArray::number(font.weight());
keyName += " " + QString::number(font.pixelSize());
keyName += QByteArray(" DF");
return QString::fromUtf8(keyName);
} else {
return QString::fromLatin1("%1_%2_%3_%4_%5")
.arg(font.familyName())
.arg(font.styleName())
.arg(font.weight())
.arg(font.style())
.arg(font.pixelSize());
}
}
QSGOpenVGFontGlyphCache::QSGOpenVGFontGlyphCache(QSGOpenVGFontGlyphCacheManager *manager, const QRawFont &font)
: m_manager(manager)
{
m_referenceFont = font;
QRawFontPrivate *fontD = QRawFontPrivate::get(font);
m_glyphCount = fontD->fontEngine->glyphCount();
m_font = vgCreateFont(0);
}
QSGOpenVGFontGlyphCache::~QSGOpenVGFontGlyphCache()
{
if (m_font != VG_INVALID_HANDLE)
vgDestroyFont(m_font);
}
void QSGOpenVGFontGlyphCache::populate(const QVector<quint32> &glyphs)
{
QSet<quint32> referencedGlyphs;
QSet<quint32> newGlyphs;
int count = glyphs.count();
for (int i = 0; i < count; ++i) {
quint32 glyphIndex = glyphs.at(i);
if ((int) glyphIndex >= glyphCount()) {
qWarning("Warning: glyph is not available with index %d", glyphIndex);
continue;
}
referencedGlyphs.insert(glyphIndex);
if (!m_cachedGlyphs.contains(glyphIndex)) {
newGlyphs.insert(glyphIndex);
}
}
referenceGlyphs(referencedGlyphs);
if (!newGlyphs.isEmpty())
requestGlyphs(newGlyphs);
}
void QSGOpenVGFontGlyphCache::release(const QVector<quint32> &glyphs)
{
QSet<quint32> unusedGlyphs;
int count = glyphs.count();
for (int i = 0; i < count; ++i) {
quint32 glyphIndex = glyphs.at(i);
unusedGlyphs.insert(glyphIndex);
}
releaseGlyphs(unusedGlyphs);
}
void QSGOpenVGFontGlyphCache::requestGlyphs(const QSet<quint32> &glyphs)
{
VGfloat origin[2];
VGfloat escapement[2];
QRectF metrics;
QRawFont rawFont = m_referenceFont;
// Before adding any new glyphs, remove any unused glyphs
for (auto glyph : qAsConst(m_unusedGlyphs)) {
vgClearGlyph(m_font, glyph);
}
for (auto glyph : glyphs) {
m_cachedGlyphs.insert(glyph);
// Calculate the path for the glyph and cache it.
QPainterPath path = rawFont.pathForGlyph(glyph);
VGPath vgPath;
if (!path.isEmpty()) {
vgPath = QSGOpenVGHelpers::qPainterPathToVGPath(path);
} else {
// Probably a "space" character with no visible outline.
vgPath = VG_INVALID_HANDLE;
}
origin[0] = 0;
origin[1] = 0;
escapement[0] = 0;
escapement[1] = 0;
vgSetGlyphToPath(m_font, glyph, vgPath, VG_FALSE, origin, escapement);
vgDestroyPath(vgPath); // Reduce reference count.
}
}
void QSGOpenVGFontGlyphCache::referenceGlyphs(const QSet<quint32> &glyphs)
{
m_unusedGlyphs -= glyphs;
}
void QSGOpenVGFontGlyphCache::releaseGlyphs(const QSet<quint32> &glyphs)
{
m_unusedGlyphs += glyphs;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,99 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSGOPENVGFONTGLYPHCACHE_H
#define QSGOPENVGFONTGLYPHCACHE_H
#include <QtGui/QGlyphRun>
#include <QtCore/QSet>
#include <QtCore/QLinkedList>
#include <VG/openvg.h>
QT_BEGIN_NAMESPACE
class QSGOpenVGFontGlyphCache;
class QSGOpenVGFontGlyphCacheManager
{
public:
QSGOpenVGFontGlyphCacheManager();
~QSGOpenVGFontGlyphCacheManager();
QSGOpenVGFontGlyphCache *cache(const QRawFont &font);
void insertCache(const QRawFont &font, QSGOpenVGFontGlyphCache *cache);
private:
static QString fontKey(const QRawFont &font);
QHash<QString, QSGOpenVGFontGlyphCache *> m_caches;
};
class QSGOpenVGFontGlyphCache
{
public:
QSGOpenVGFontGlyphCache(QSGOpenVGFontGlyphCacheManager *manager, const QRawFont &font);
~QSGOpenVGFontGlyphCache();
const QSGOpenVGFontGlyphCacheManager *manager() const { return m_manager; }
const QRawFont &referenceFont() const { return m_referenceFont; }
int glyphCount() const { return m_glyphCount; }
void populate(const QVector<quint32> &glyphs);
void release(const QVector<quint32> &glyphs);
VGFont font() { return m_font; }
private:
void requestGlyphs(const QSet<quint32> &glyphs);
void referenceGlyphs(const QSet<quint32> &glyphs);
void releaseGlyphs(const QSet<quint32> &glyphs);
QSGOpenVGFontGlyphCacheManager *m_manager;
QRawFont m_referenceFont;
int m_glyphCount;
VGFont m_font;
QSet<quint32> m_cachedGlyphs;
QSet<quint32> m_unusedGlyphs;
};
QT_END_NAMESPACE
#endif // QSGOPENVGFONTGLYPHCACHE_H

View File

@ -0,0 +1,191 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsgopenvgglyphnode_p.h"
#include "qopenvgcontext_p.h"
#include "qsgopenvgcontext_p.h"
#include "qsgopenvghelpers.h"
#include "qsgopenvgfontglyphcache.h"
QT_BEGIN_NAMESPACE
QSGOpenVGGlyphNode::QSGOpenVGGlyphNode(QSGRenderContext *rc)
: m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 0)
, m_style(QQuickText::Normal)
, m_glyphCache(nullptr)
{
// Set Dummy material to avoid asserts
setMaterial((QSGMaterial*)1);
setGeometry(&m_geometry);
m_fontColorPaint = vgCreatePaint();
m_styleColorPaint = vgCreatePaint();
// Get handle to Glyph Cache
m_renderContext = static_cast<QSGOpenVGRenderContext*>(rc);
}
QSGOpenVGGlyphNode::~QSGOpenVGGlyphNode()
{
if (m_glyphCache)
m_glyphCache->release(m_glyphRun.glyphIndexes());
vgDestroyPaint(m_fontColorPaint);
vgDestroyPaint(m_styleColorPaint);
}
void QSGOpenVGGlyphNode::setGlyphs(const QPointF &position, const QGlyphRun &glyphs)
{
// Obtain glyph cache for font
auto oldGlyphCache = m_glyphCache;
m_glyphCache = m_renderContext->glyphCache(glyphs.rawFont());
if (m_glyphCache != oldGlyphCache) {
if (oldGlyphCache)
oldGlyphCache->release(m_glyphRun.glyphIndexes());
}
m_glyphCache->populate(glyphs.glyphIndexes());
m_position = position;
m_glyphRun = glyphs;
// Recreate ajustments
m_xAdjustments.clear();
m_yAdjustments.clear();
for (int i = 1; i < glyphs.positions().count(); ++i) {
m_xAdjustments.append(glyphs.positions().at(i).x() - glyphs.positions().at(i-1).x());
m_yAdjustments.append(glyphs.positions().at(i).y() - glyphs.positions().at(i-1).y());
}
}
void QSGOpenVGGlyphNode::setColor(const QColor &color)
{
m_color = color;
vgSetParameteri(m_fontColorPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
vgSetParameterfv(m_fontColorPaint, VG_PAINT_COLOR, 4, QSGOpenVGHelpers::qColorToVGColor(m_color, opacity()).constData());
}
void QSGOpenVGGlyphNode::setStyle(QQuickText::TextStyle style)
{
m_style = style;
}
void QSGOpenVGGlyphNode::setStyleColor(const QColor &color)
{
m_styleColor = color;
vgSetParameteri(m_styleColorPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
vgSetParameterfv(m_styleColorPaint, VG_PAINT_COLOR, 4, QSGOpenVGHelpers::qColorToVGColor(m_styleColor, opacity()).constData());
}
QPointF QSGOpenVGGlyphNode::baseLine() const
{
return QPointF();
}
void QSGOpenVGGlyphNode::setPreferredAntialiasingMode(QSGGlyphNode::AntialiasingMode)
{
}
void QSGOpenVGGlyphNode::update()
{
}
void QSGOpenVGGlyphNode::render()
{
if (m_glyphRun.positions().count() == 0)
return;
// Rendering Style
qreal offset = 1.0;
vgSeti(VG_RENDERING_QUALITY, VG_RENDERING_QUALITY_BETTER);
switch (m_style) {
case QQuickText::Normal: break;
case QQuickText::Outline:
// Set the correct fill state
vgSetPaint(m_styleColorPaint, VG_FILL_PATH);
drawGlyphsAtOffset(QPointF(0, offset));
drawGlyphsAtOffset(QPointF(0, -offset));
drawGlyphsAtOffset(QPointF(offset, 0));
drawGlyphsAtOffset(QPointF(-offset, 0));
break;
case QQuickText::Raised:
vgSetPaint(m_styleColorPaint, VG_FILL_PATH);
drawGlyphsAtOffset(QPointF(0, offset));
break;
case QQuickText::Sunken:
vgSetPaint(m_styleColorPaint, VG_FILL_PATH);
drawGlyphsAtOffset(QPointF(0, -offset));
break;
}
// Set the correct fill state
vgSetPaint(m_fontColorPaint, VG_FILL_PATH);
drawGlyphsAtOffset(QPointF(0.0, 0.0));
}
void QSGOpenVGGlyphNode::setOpacity(float opacity)
{
if (QSGOpenVGRenderable::opacity() != opacity) {
QSGOpenVGRenderable::setOpacity(opacity);
// Update Colors
setColor(m_color);
setStyleColor(m_styleColor);
}
}
void QSGOpenVGGlyphNode::drawGlyphsAtOffset(const QPointF &offset)
{
QPointF firstPosition = m_glyphRun.positions()[0] + (m_position - QPointF(0, m_glyphRun.rawFont().ascent()));
VGfloat origin[2];
origin[0] = firstPosition.x() + offset.x();
origin[1] = firstPosition.y() + offset.y();
vgSetfv(VG_GLYPH_ORIGIN, 2, origin);
vgDrawGlyphs(m_glyphCache->font(),
m_glyphRun.glyphIndexes().count(),
(VGuint*)m_glyphRun.glyphIndexes().constData(),
m_xAdjustments.constData(),
m_yAdjustments.constData(),
VG_FILL_PATH,
VG_TRUE);
}
QT_END_NAMESPACE

View File

@ -0,0 +1,95 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSGOPENVGGLYPHNODE_H
#define QSGOPENVGGLYPHNODE_H
#include <private/qsgadaptationlayer_p.h>
#include <QtCore/QVector>
#include <VG/openvg.h>
#include "qsgopenvgrenderable.h"
#include "qsgopenvgfontglyphcache.h"
QT_BEGIN_NAMESPACE
class QSGOpenVGFontGlyphCache;
class QSGOpenVGRenderContext;
class QSGRenderContext;
class QSGOpenVGGlyphNode : public QSGGlyphNode, public QSGOpenVGRenderable
{
public:
QSGOpenVGGlyphNode(QSGRenderContext *rc);
~QSGOpenVGGlyphNode();
void setGlyphs(const QPointF &position, const QGlyphRun &glyphs) override;
void setColor(const QColor &color) override;
void setStyle(QQuickText::TextStyle style) override;
void setStyleColor(const QColor &color) override;
QPointF baseLine() const override;
void setPreferredAntialiasingMode(AntialiasingMode) override;
void update() override;
void render() override;
void setOpacity(float opacity) override;
private:
void drawGlyphsAtOffset(const QPointF &offset);
QPointF m_position;
QGlyphRun m_glyphRun;
QColor m_color;
QSGGeometry m_geometry;
QQuickText::TextStyle m_style;
QColor m_styleColor;
QSGOpenVGFontGlyphCache *m_glyphCache;
QVector<VGfloat> m_xAdjustments;
QVector<VGfloat> m_yAdjustments;
VGPaint m_fontColorPaint;
VGPaint m_styleColorPaint;
QSGOpenVGRenderContext *m_renderContext;
};
QT_END_NAMESPACE
#endif // QSGOPENVGGLYPHNODE_H

View File

@ -0,0 +1,433 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsgopenvghelpers.h"
#include <cmath>
QT_BEGIN_NAMESPACE
namespace QSGOpenVGHelpers {
VGPath qPainterPathToVGPath(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;
QVector<VGfloat> coords;
QVector<VGubyte> 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;
for (int i = 0; i < count; ++i) {
const QPainterPath::Element element = path.elementAt(i);
switch (element.type) {
case QPainterPath::MoveToElement:
{
if (haveStart && haveEnd && startx == endx && starty == endy) {
// Implicitly close the previous sub-path.
segments.append(VG_CLOSE_PATH);
}
temp = QPointF(element.x, element.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 = QPointF(element.x, element.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 = QPointF(element.x, element.y);
coords.append(temp.x());
coords.append(temp.y());
haveEnd = false;
curvePos = 2;
}
break;
case QPainterPath::CurveToDataElement:
{
temp = QPointF(element.x, element.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;
}
void qDrawTiled(VGImage image, const QSize imageSize, const QRectF &targetRect, const QPointF offset, float scaleX, float scaleY) {
//Check for valid image size and targetRect
if (imageSize.width() <= 0 || imageSize.height() <= 0)
return;
if (targetRect.width() <= 0 || targetRect.height() <= 0)
return;
// This logic is mostly from the Qt Raster PaintEngine's qt_draw_tile
qreal drawH;
qreal drawW;
qreal xPos;
qreal xOff;
qreal yPos = targetRect.y();
qreal yOff;
if (offset.y() < 0)
yOff = imageSize.height() - qRound(-offset.y()) % imageSize.height();
else
yOff = qRound(offset.y()) % imageSize.height();
// Save the current image transform matrix
vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
QVector<float> originalMatrix(9);
vgGetMatrix(originalMatrix.data());
while (!qFuzzyCompare(yPos, targetRect.y() + targetRect.height()) &&
yPos < targetRect.y() + targetRect.height()) {
drawH = imageSize.height() - yOff; // Cropping first row
if (yPos + drawH * scaleY > targetRect.y() + targetRect.height()) { // Cropping last row
// Check that values aren't equal
if (!qFuzzyCompare((float)(yPos + drawH * scaleY), (float)(targetRect.y() + targetRect.height())))
drawH = targetRect.y() + targetRect.height() - yPos;
}
xPos = targetRect.x();
if (offset.x() < 0)
xOff = imageSize.width() - qRound(-offset.x()) % imageSize.width();
else
xOff = qRound(offset.x()) % imageSize.width();
while (!qFuzzyCompare(xPos, targetRect.x() + targetRect.width()) &&
xPos < targetRect.x() + targetRect.width()) {
drawW = imageSize.width() - xOff; // Cropping first column
if (xPos + drawW * scaleX > targetRect.x() + targetRect.width()) {
// Check that values aren't equal
if (!qFuzzyCompare((float)(xPos + drawW * scaleX), (float)(targetRect.x() + targetRect.width())))
drawW = targetRect.x() + targetRect.width() - xPos;
}
if (round(drawW) > 0 && round(drawH) > 0) { // Can't source image less than 1 width or height
//Draw here
VGImage childRectImage = vgChildImage(image, xOff, yOff, round(drawW), round(drawH));
vgTranslate(xPos, yPos);
vgScale(scaleX, scaleY);
vgDrawImage(childRectImage);
vgDestroyImage(childRectImage);
vgLoadMatrix(originalMatrix.constData());
}
if ( drawW > 0)
xPos += drawW * scaleX;
xOff = 0;
}
if ( drawH > 0)
yPos += drawH * scaleY;
yOff = 0;
}
}
void qDrawBorderImage(VGImage image, const QSizeF &textureSize, const QRectF &targetRect, const QRectF &innerTargetRect, const QRectF &subSourceRect)
{
// Create normalized margins
QMarginsF margins(qMax(innerTargetRect.left() - targetRect.left(), 0.0),
qMax(innerTargetRect.top() - targetRect.top(), 0.0),
qMax(targetRect.right() - innerTargetRect.right(), 0.0),
qMax(targetRect.bottom() - innerTargetRect.bottom(), 0.0));
QRectF sourceRect(0, 0, textureSize.width(), textureSize.height());
// Create all the subRects
QRectF topLeftSourceRect(sourceRect.topLeft(), QSizeF(margins.left(), margins.top()));
QRectF topRightSourceRect(sourceRect.width() - margins.right(), sourceRect.top(), margins.right(), margins.top());
QRectF bottomLeftSourceRect(sourceRect.left(), sourceRect.height() - margins.bottom(), margins.left(), margins.bottom());
QRectF bottomRightSourceRect(sourceRect.width() - margins.right(), sourceRect.height() - margins.bottom(), margins.right(), margins.bottom());
QRectF topSourceRect(margins.left(), 0.0, sourceRect.width() - (margins.right() + margins.left()), margins.top());
QRectF topTargetRect(margins.left(), 0.0, innerTargetRect.width(), margins.top());
QRectF bottomSourceRect(margins.left(), sourceRect.height() - margins.bottom(), sourceRect.width() - (margins.right() + margins.left()), margins.bottom());
QRectF bottomTargetRect(margins.left(), targetRect.height() - margins.bottom(), innerTargetRect.width(), margins.bottom());
QRectF leftSourceRect(0.0, margins.top(), margins.left(), sourceRect.height() - (margins.bottom() + margins.top()));
QRectF leftTargetRect(0.0, margins.top(), margins.left(), innerTargetRect.height());
QRectF rightSourceRect(sourceRect.width() - margins.right(), margins.top(), margins.right(), sourceRect.height() - (margins.bottom() + margins.top()));
QRectF rightTargetRect(targetRect.width() - margins.right(), margins.top(), margins.right(), innerTargetRect.height());
QRectF centerSourceRect(margins.left(), margins.top(), sourceRect.width() - (margins.right() + margins.left()), sourceRect.height() - (margins.top() + margins.bottom()));
// Draw the 9 different sections
// (1) Top Left (unscaled)
qDrawSubImage(image,
topLeftSourceRect,
targetRect.topLeft());
// (3) Top Right (unscaled)
qDrawSubImage(image,
topRightSourceRect,
QPointF(targetRect.width() - margins.right(), 0.0));
// (7) Bottom Left (unscaled)
qDrawSubImage(image,
bottomLeftSourceRect,
QPointF(targetRect.left(), targetRect.height() - margins.bottom()));
// (9) Bottom Right (unscaled)
qDrawSubImage(image,
bottomRightSourceRect,
QPointF(targetRect.width() - margins.right(), targetRect.height() - margins.bottom()));
double scaledWidth = 1.0;
double scaledHeight = 1.0;
// (2) Top (scaled via horizontalTileRule)
VGImage topImage = vgChildImage(image, topSourceRect.x(), topSourceRect.y(), topSourceRect.width(), topSourceRect.height());
scaledWidth = (topTargetRect.width() / subSourceRect.width()) / topSourceRect.width();
QSGOpenVGHelpers::qDrawTiled(topImage, topSourceRect.size().toSize(), topTargetRect, QPoint(0.0, 0.0), scaledWidth, 1);
vgDestroyImage(topImage);
// (8) Bottom (scaled via horizontalTileRule)
VGImage bottomImage = vgChildImage(image, bottomSourceRect.x(), bottomSourceRect.y(), bottomSourceRect.width(), bottomSourceRect.height());
scaledWidth = (bottomTargetRect.width() / subSourceRect.width()) / bottomSourceRect.width();
QSGOpenVGHelpers::qDrawTiled(bottomImage, bottomSourceRect.size().toSize(), bottomTargetRect, QPoint(0.0, 0.0), scaledWidth, 1);
vgDestroyImage(bottomImage);
// (4) Left (scaled via verticalTileRule)
VGImage leftImage = vgChildImage(image, leftSourceRect.x(), leftSourceRect.y(), leftSourceRect.width(), leftSourceRect.height());
scaledHeight = (leftTargetRect.height() / subSourceRect.height()) / leftSourceRect.height();
QSGOpenVGHelpers::qDrawTiled(leftImage, leftSourceRect.size().toSize(), leftTargetRect, QPointF(0.0, 0.0), 1, scaledHeight);
vgDestroyImage(leftImage);
// (6) Right (scaled via verticalTileRule)
VGImage rightImage = vgChildImage(image, rightSourceRect.x(), rightSourceRect.y(), rightSourceRect.width(), rightSourceRect.height());
scaledHeight = (rightTargetRect.height() / subSourceRect.height()) / rightSourceRect.height();
QSGOpenVGHelpers::qDrawTiled(rightImage, rightSourceRect.size().toSize(), rightTargetRect, QPointF(0, 0), 1, scaledHeight);
vgDestroyImage(rightImage);
// (5) Center (saled via verticalTileRule and horizontalTileRule)
VGImage centerImage = vgChildImage(image, centerSourceRect.x(), centerSourceRect.y(), centerSourceRect.width(), centerSourceRect.height());
scaledWidth = (innerTargetRect.width() / subSourceRect.width()) / centerSourceRect.width();
scaledHeight = (innerTargetRect.height() / subSourceRect.height()) / centerSourceRect.height();
QSGOpenVGHelpers::qDrawTiled(centerImage, centerSourceRect.size().toSize(), innerTargetRect, QPointF(0, 0), scaledWidth, scaledHeight);
vgDestroyImage(centerImage);
}
void qDrawSubImage(VGImage image, const QRectF &sourceRect, const QPointF &destOffset)
{
// Check for valid source size
if (sourceRect.width() <= 0 || sourceRect.height() <= 0)
return;
// Save the current image transform matrix
vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
QVector<float> originalMatrix(9);
vgGetMatrix(originalMatrix.data());
// Get the child Image
VGImage childRectImage = vgChildImage(image, sourceRect.x(), sourceRect.y(), sourceRect.width(), sourceRect.height());
vgTranslate(destOffset.x(), destOffset.y());
vgDrawImage(childRectImage);
vgDestroyImage(childRectImage);
// Pop Matrix
vgLoadMatrix(originalMatrix.constData());
}
const QVector<VGfloat> qColorToVGColor(const QColor &color, float opacity)
{
QVector<VGfloat> vgColor(4);
vgColor[0] = color.redF();
vgColor[1] = color.greenF();
vgColor[2] = color.blueF();
vgColor[3] = color.alphaF() * opacity;
return vgColor;
}
VGImageFormat qImageFormatToVGImageFormat(QImage::Format format)
{
VGImageFormat vgFormat;
switch (format) {
case QImage::Format_Mono:
case QImage::Format_MonoLSB:
vgFormat = VG_BW_1;
break;
case QImage::Format_RGB32:
vgFormat = VG_sXRGB_8888;
break;
case QImage::Format_ARGB32:
vgFormat = VG_sARGB_8888;
break;
case QImage::Format_ARGB32_Premultiplied:
vgFormat = VG_sARGB_8888_PRE;
break;
case QImage::Format_RGB16:
vgFormat = VG_sRGB_565;
break;
case QImage::Format_RGBX8888:
vgFormat = VG_sRGBX_8888;
break;
case QImage::Format_RGBA8888:
vgFormat = VG_sRGBA_8888;
break;
case QImage::Format_RGBA8888_Premultiplied:
vgFormat = VG_sRGBA_8888_PRE;
break;
case QImage::Format_Alpha8:
vgFormat = VG_A_8;
break;
case QImage::Format_Grayscale8:
vgFormat = VG_sL_8;
break;
default:
//Invalid
vgFormat = (VGImageFormat)-1;
break;
}
return vgFormat;
}
QImage::Format qVGImageFormatToQImageFormat(VGImageFormat format)
{
QImage::Format qImageFormat;
switch (format) {
case VG_BW_1:
qImageFormat = QImage::Format_Mono;
break;
case VG_sXRGB_8888:
qImageFormat = QImage::Format_RGB32;
break;
case VG_sARGB_8888:
qImageFormat = QImage::Format_ARGB32;
break;
case VG_sARGB_8888_PRE:
qImageFormat = QImage::Format_ARGB32_Premultiplied;
break;
case VG_sRGB_565:
qImageFormat = QImage::Format_RGB16;
break;
case VG_sRGBX_8888:
qImageFormat = QImage::Format_RGBX8888;
break;
case VG_sRGBA_8888:
qImageFormat = QImage::Format_RGBA8888;
break;
case VG_sRGBA_8888_PRE:
qImageFormat = QImage::Format_RGBA8888_Premultiplied;
break;
case VG_A_8:
qImageFormat = QImage::Format_Alpha8;
break;
case VG_sL_8:
qImageFormat = QImage::Format_Grayscale8;
default:
qImageFormat = QImage::Format_ARGB32;
break;
}
return qImageFormat;
}
} // end namespace QSGOpenVGHelpers
QT_END_NAMESPACE

View File

@ -0,0 +1,64 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSGOPENVGHELPERS_H
#define QSGOPENVGHELPERS_H
#include <QtGui/QPainterPath>
#include <QtGui/QColor>
#include <QtGui/QImage>
#include <VG/openvg.h>
QT_BEGIN_NAMESPACE
namespace QSGOpenVGHelpers {
VGPath qPainterPathToVGPath(const QPainterPath &path);
void qDrawTiled(VGImage image, const QSize imageSize, const QRectF &targetRect, const QPointF offset, float scaleX, float scaleY);
void qDrawBorderImage(VGImage image, const QSizeF &textureSize, const QRectF &targetRect, const QRectF &innerTargetRect, const QRectF &subSourceRect);
void qDrawSubImage(VGImage image, const QRectF &sourceRect, const QPointF &destOffset);
const QVector<VGfloat> qColorToVGColor(const QColor &color, float opacity = 1.0f);
VGImageFormat qImageFormatToVGImageFormat(QImage::Format format);
QImage::Format qVGImageFormatToQImageFormat(VGImageFormat format);
};
QT_END_NAMESPACE
#endif // QSGOPENVGHELPERS_H

View File

@ -0,0 +1,233 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsgopenvginternalimagenode.h"
#include "qsgopenvghelpers.h"
#include <VG/openvg.h>
QT_BEGIN_NAMESPACE
QSGOpenVGInternalImageNode::QSGOpenVGInternalImageNode()
{
// Set Dummy material and geometry to avoid asserts
setMaterial((QSGMaterial*)1);
setGeometry((QSGGeometry*)1);
}
QSGOpenVGInternalImageNode::~QSGOpenVGInternalImageNode()
{
if (m_subSourceRectImage != 0)
vgDestroyImage(m_subSourceRectImage);
}
void QSGOpenVGInternalImageNode::render()
{
if (!m_texture) {
return;
}
// Set Draw Mode
if (opacity() < 1.0) {
//Transparent
vgSetPaint(opacityPaint(), VG_FILL_PATH);
vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_MULTIPLY);
} else {
vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL);
}
VGImage image = static_cast<VGImage>(m_texture->textureId());
QSize textureSize = m_texture->textureSize();
// If Mirrored
if (m_mirror) {
vgTranslate(m_targetRect.width(), 0.0f);
vgScale(-1.0, 1.0);
}
if (m_smooth)
vgSeti(VG_IMAGE_QUALITY, VG_IMAGE_QUALITY_BETTER);
else
vgSeti(VG_IMAGE_QUALITY, VG_IMAGE_QUALITY_NONANTIALIASED);
if (m_innerTargetRect != m_targetRect) {
// border image
QSGOpenVGHelpers::qDrawBorderImage(image, textureSize, m_targetRect, m_innerTargetRect, m_subSourceRect);
} else if (m_tileHorizontal || m_tileVertical) {
// Tilled Image
float sx = m_targetRect.width() / (m_subSourceRect.width() * textureSize.width());
float sy = m_targetRect.height() / (m_subSourceRect.height() * textureSize.height());
QPointF offset(m_subSourceRect.left() * textureSize.width(), m_subSourceRect.top() * textureSize.height());
QSGOpenVGHelpers::qDrawTiled(image, textureSize, m_targetRect, offset, sx, sy);
} else {
// Regular BLIT
QRectF sr(m_subSourceRect.left() * textureSize.width(), m_subSourceRect.top() * textureSize.height(),
m_subSourceRect.width() * textureSize.width(), m_subSourceRect.height() * textureSize.height());
if (m_subSourceRectImageDirty) {
if (m_subSourceRectImage != 0)
vgDestroyImage(m_subSourceRectImage);
m_subSourceRectImage = vgChildImage(image, sr.x(), sr.y(), sr.width(), sr.height());
m_subSourceRectImageDirty = false;
}
// If the the source rect is the same as the target rect
if (sr == m_targetRect) {
vgDrawImage(image);
} else {
// Scale
float scaleX = m_targetRect.width() / sr.width();
float scaleY = m_targetRect.height() / sr.height();
vgTranslate(m_targetRect.x(), m_targetRect.y());
vgScale(scaleX, scaleY);
vgDrawImage(m_subSourceRectImage);
}
}
}
void QSGOpenVGInternalImageNode::setTargetRect(const QRectF &rect)
{
if (rect == m_targetRect)
return;
m_targetRect = rect;
markDirty(DirtyGeometry);
}
void QSGOpenVGInternalImageNode::setInnerTargetRect(const QRectF &rect)
{
if (rect == m_innerTargetRect)
return;
m_innerTargetRect = rect;
markDirty(DirtyGeometry);
}
void QSGOpenVGInternalImageNode::setInnerSourceRect(const QRectF &rect)
{
if (rect == m_innerSourceRect)
return;
m_innerSourceRect = rect;
markDirty(DirtyGeometry);
}
void QSGOpenVGInternalImageNode::setSubSourceRect(const QRectF &rect)
{
if (rect == m_subSourceRect)
return;
m_subSourceRect = rect;
m_subSourceRectImageDirty = true;
markDirty(DirtyGeometry);
}
void QSGOpenVGInternalImageNode::setTexture(QSGTexture *texture)
{
m_texture = texture;
m_subSourceRectImageDirty = true;
markDirty(DirtyMaterial);
}
void QSGOpenVGInternalImageNode::setMirror(bool mirror)
{
if (m_mirror != mirror) {
m_mirror = mirror;
markDirty(DirtyMaterial);
}
}
void QSGOpenVGInternalImageNode::setMipmapFiltering(QSGTexture::Filtering)
{
}
void QSGOpenVGInternalImageNode::setFiltering(QSGTexture::Filtering filtering)
{
bool smooth = (filtering == QSGTexture::Linear);
if (smooth == m_smooth)
return;
m_smooth = smooth;
markDirty(DirtyMaterial);
}
void QSGOpenVGInternalImageNode::setHorizontalWrapMode(QSGTexture::WrapMode wrapMode)
{
bool tileHorizontal = (wrapMode == QSGTexture::Repeat);
if (tileHorizontal == m_tileHorizontal)
return;
m_tileHorizontal = tileHorizontal;
markDirty(DirtyMaterial);
}
void QSGOpenVGInternalImageNode::setVerticalWrapMode(QSGTexture::WrapMode wrapMode)
{
bool tileVertical = (wrapMode == QSGTexture::Repeat);
if (tileVertical == m_tileVertical)
return;
m_tileVertical = (wrapMode == QSGTexture::Repeat);
markDirty(DirtyMaterial);
}
void QSGOpenVGInternalImageNode::update()
{
}
void QSGOpenVGInternalImageNode::preprocess()
{
bool doDirty = false;
QSGLayer *t = qobject_cast<QSGLayer *>(m_texture);
if (t) {
doDirty = t->updateTexture();
markDirty(DirtyGeometry);
}
if (doDirty)
markDirty(DirtyMaterial);
}
QT_END_NAMESPACE

View File

@ -0,0 +1,92 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSGOPENVGINTERNALIMAGENODE_H
#define QSGOPENVGINTERNALIMAGENODE_H
#include <private/qsgadaptationlayer_p.h>
#include "qsgopenvgrenderable.h"
#include <VG/openvg.h>
QT_BEGIN_NAMESPACE
class QSGOpenVGInternalImageNode : public QSGInternalImageNode, public QSGOpenVGRenderable
{
public:
QSGOpenVGInternalImageNode();
~QSGOpenVGInternalImageNode();
void render() override;
void setTargetRect(const QRectF &rect) override;
void setInnerTargetRect(const QRectF &rect) override;
void setInnerSourceRect(const QRectF &rect) override;
void setSubSourceRect(const QRectF &rect) override;
void setTexture(QSGTexture *texture) override;
void setMirror(bool mirror) override;
void setMipmapFiltering(QSGTexture::Filtering filtering) override;
void setFiltering(QSGTexture::Filtering filtering) override;
void setHorizontalWrapMode(QSGTexture::WrapMode wrapMode) override;
void setVerticalWrapMode(QSGTexture::WrapMode wrapMode) override;
void update() override;
void preprocess() override;
private:
QRectF m_targetRect;
QRectF m_innerTargetRect;
QRectF m_innerSourceRect = QRectF(0, 0, 1, 1);
QRectF m_subSourceRect = QRectF(0, 0, 1, 1);
bool m_mirror = false;
bool m_smooth = true;
bool m_tileHorizontal = false;
bool m_tileVertical = false;
QSGTexture *m_texture = nullptr;
VGImage m_subSourceRectImage = 0;
bool m_subSourceRectImageDirty = true;
};
QT_END_NAMESPACE
#endif // QSGOPENVGINTERNALIMAGENODE_H

View File

@ -0,0 +1,613 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsgopenvginternalrectanglenode.h"
#include "qsgopenvghelpers.h"
#include <VG/vgu.h>
QSGOpenVGInternalRectangleNode::QSGOpenVGInternalRectangleNode()
{
// Set Dummy material and geometry to avoid asserts
setMaterial((QSGMaterial*)1);
setGeometry((QSGGeometry*)1);
createVGResources();
}
QSGOpenVGInternalRectangleNode::~QSGOpenVGInternalRectangleNode()
{
destroyVGResources();
}
void QSGOpenVGInternalRectangleNode::setRect(const QRectF &rect)
{
m_rect = rect;
m_pathDirty = true;
}
void QSGOpenVGInternalRectangleNode::setColor(const QColor &color)
{
m_fillColor = color;
m_fillDirty = true;
}
void QSGOpenVGInternalRectangleNode::setPenColor(const QColor &color)
{
m_strokeColor = color;
m_strokeDirty = true;
}
void QSGOpenVGInternalRectangleNode::setPenWidth(qreal width)
{
m_penWidth = width;
m_strokeDirty = true;
m_pathDirty = true;
}
//Move first stop by pos relative to seconds
static QGradientStop interpolateStop(const QGradientStop &firstStop, const QGradientStop &secondStop, double newPos)
{
double distance = secondStop.first - firstStop.first;
double distanceDelta = newPos - firstStop.first;
double modifierValue = distanceDelta / distance;
int redDelta = (secondStop.second.red() - firstStop.second.red()) * modifierValue;
int greenDelta = (secondStop.second.green() - firstStop.second.green()) * modifierValue;
int blueDelta = (secondStop.second.blue() - firstStop.second.blue()) * modifierValue;
int alphaDelta = (secondStop.second.alpha() - firstStop.second.alpha()) * modifierValue;
QGradientStop newStop;
newStop.first = newPos;
newStop.second = QColor(firstStop.second.red() + redDelta,
firstStop.second.green() + greenDelta,
firstStop.second.blue() + blueDelta,
firstStop.second.alpha() + alphaDelta);
return newStop;
}
void QSGOpenVGInternalRectangleNode::setGradientStops(const QGradientStops &stops)
{
//normalize stops
bool needsNormalization = false;
for (const QGradientStop &stop : qAsConst(stops)) {
if (stop.first < 0.0 || stop.first > 1.0) {
needsNormalization = true;
continue;
}
}
if (needsNormalization) {
QGradientStops normalizedStops;
if (stops.count() == 1) {
//If there is only one stop, then the position does not matter
//It is just treated as a color
QGradientStop stop = stops.at(0);
stop.first = 0.0;
normalizedStops.append(stop);
} else {
//Clip stops to only the first below 0.0 and above 1.0
int below = -1;
int above = -1;
QVector<int> between;
for (int i = 0; i < stops.count(); ++i) {
if (stops.at(i).first < 0.0) {
below = i;
} else if (stops.at(i).first > 1.0) {
above = i;
break;
} else {
between.append(i);
}
}
//Interpoloate new color values for above and below
if (below != -1 ) {
//If there are more than one stops left, interpolate
if (below + 1 < stops.count()) {
normalizedStops.append(interpolateStop(stops.at(below), stops.at(below + 1), 0.0));
} else {
QGradientStop singleStop;
singleStop.first = 0.0;
singleStop.second = stops.at(below).second;
normalizedStops.append(singleStop);
}
}
for (int i = 0; i < between.count(); ++i)
normalizedStops.append(stops.at(between.at(i)));
if (above != -1) {
//If there stops before above, interpolate
if (above >= 1) {
normalizedStops.append(interpolateStop(stops.at(above), stops.at(above - 1), 1.0));
} else {
QGradientStop singleStop;
singleStop.first = 1.0;
singleStop.second = stops.at(above).second;
normalizedStops.append(singleStop);
}
}
}
m_gradientStops = normalizedStops;
} else {
m_gradientStops = stops;
}
m_fillDirty = true;
}
void QSGOpenVGInternalRectangleNode::setRadius(qreal radius)
{
m_radius = radius;
m_pathDirty = true;
}
void QSGOpenVGInternalRectangleNode::setAligned(bool aligned)
{
m_aligned = aligned;
}
void QSGOpenVGInternalRectangleNode::update()
{
}
void QSGOpenVGInternalRectangleNode::render()
{
// If path is dirty
if (m_pathDirty) {
vgClearPath(m_rectanglePath, VG_PATH_CAPABILITY_APPEND_TO);
vgClearPath(m_borderPath, VG_PATH_CAPABILITY_APPEND_TO);
if (m_penWidth == 0) {
generateRectanglePath(m_rect, m_radius, m_rectanglePath);
} else {
generateRectangleAndBorderPaths(m_rect, m_penWidth, m_radius, m_rectanglePath, m_borderPath);
}
m_pathDirty = false;
}
//If fill is drity
if (m_fillDirty) {
if (m_gradientStops.isEmpty()) {
vgSetParameteri(m_rectanglePaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
vgSetParameterfv(m_rectanglePaint, VG_PAINT_COLOR, 4, QSGOpenVGHelpers::qColorToVGColor(m_fillColor, opacity()).constData());
} else {
// Linear Gradient
vgSetParameteri(m_rectanglePaint, VG_PAINT_TYPE, VG_PAINT_TYPE_LINEAR_GRADIENT);
const VGfloat verticalLinearGradient[] = {
0.0f,
0.0f,
0.0f,
static_cast<VGfloat>(m_rect.height())
};
vgSetParameterfv(m_rectanglePaint, VG_PAINT_LINEAR_GRADIENT, 4, verticalLinearGradient);
vgSetParameteri(m_rectanglePaint, VG_PAINT_COLOR_RAMP_SPREAD_MODE, VG_COLOR_RAMP_SPREAD_PAD);
vgSetParameteri(m_rectanglePaint, VG_PAINT_COLOR_RAMP_PREMULTIPLIED, false);
QVector<VGfloat> stops;
for (const QGradientStop &stop : qAsConst(m_gradientStops)) {
// offset
stops.append(stop.first);
// color
stops.append(QSGOpenVGHelpers::qColorToVGColor(stop.second, opacity()));
}
vgSetParameterfv(m_rectanglePaint, VG_PAINT_COLOR_RAMP_STOPS, stops.length(), stops.constData());
}
m_fillDirty = false;
}
//If stroke is dirty
if (m_strokeDirty) {
vgSetParameteri(m_borderPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
vgSetParameterfv(m_borderPaint, VG_PAINT_COLOR, 4, QSGOpenVGHelpers::qColorToVGColor(m_strokeColor, opacity()).constData());
m_strokeDirty = false;
}
//Draw
if (m_penWidth > 0) {
vgSetPaint(m_borderPaint, VG_FILL_PATH);
vgDrawPath(m_borderPath, VG_FILL_PATH);
vgSetPaint(m_rectanglePaint, VG_FILL_PATH);
vgDrawPath(m_rectanglePath, VG_FILL_PATH);
} else {
vgSetPaint(m_rectanglePaint, VG_FILL_PATH);
vgDrawPath(m_rectanglePath, VG_FILL_PATH);
}
}
void QSGOpenVGInternalRectangleNode::setOpacity(float opacity)
{
if (opacity != QSGOpenVGRenderable::opacity()) {
QSGOpenVGRenderable::setOpacity(opacity);
m_strokeDirty = true;
m_fillDirty = true;
}
}
void QSGOpenVGInternalRectangleNode::createVGResources()
{
m_rectanglePaint = vgCreatePaint();
m_borderPaint = vgCreatePaint();
m_rectanglePath = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1, 0, 0, 0,
VG_PATH_CAPABILITY_APPEND_TO);
m_borderPath = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1, 0, 0, 0,
VG_PATH_CAPABILITY_APPEND_TO);
}
void QSGOpenVGInternalRectangleNode::destroyVGResources()
{
vgDestroyPaint(m_rectanglePaint);
vgDestroyPaint(m_borderPaint);
vgDestroyPath(m_rectanglePath);
vgDestroyPath(m_borderPath);
}
void QSGOpenVGInternalRectangleNode::generateRectanglePath(const QRectF &rect, float radius, VGPath path) const
{
if (radius == 0) {
// Generate a rectangle
// Create command list
static const VGubyte rectCommands[] = {
VG_MOVE_TO_ABS,
VG_HLINE_TO_REL,
VG_VLINE_TO_REL,
VG_HLINE_TO_REL,
VG_CLOSE_PATH
};
// Create command data
QVector<VGfloat> coordinates(5);
coordinates[0] = rect.x();
coordinates[1] = rect.y();
coordinates[2] = rect.width();
coordinates[3] = rect.height();
coordinates[4] = -rect.width();
vgAppendPathData(path, 5, rectCommands, coordinates.constData());
} else {
// Generate a rounded rectangle
//Radius should never exceeds half of the width or half of the height
float adjustedRadius = qMin((float)qMin(rect.width(), rect.height()) * 0.5f, radius);
// OpenVG expectes radius to be 2x what we expect
adjustedRadius *= 2;
// Create command list
static const VGubyte roundedRectCommands[] = {
VG_MOVE_TO_ABS,
VG_HLINE_TO_REL,
VG_SCCWARC_TO_REL,
VG_VLINE_TO_REL,
VG_SCCWARC_TO_REL,
VG_HLINE_TO_REL,
VG_SCCWARC_TO_REL,
VG_VLINE_TO_REL,
VG_SCCWARC_TO_REL,
VG_CLOSE_PATH
};
// Create command data
QVector<VGfloat> coordinates(26);
coordinates[0] = rect.x() + adjustedRadius / 2;
coordinates[1] = rect.y();
coordinates[2] = rect.width() - adjustedRadius;
coordinates[3] = adjustedRadius / 2;
coordinates[4] = adjustedRadius / 2;
coordinates[5] = 0;
coordinates[6] = adjustedRadius / 2;
coordinates[7] = adjustedRadius / 2;
coordinates[8] = rect.height() - adjustedRadius;
coordinates[9] = adjustedRadius / 2;
coordinates[10] = adjustedRadius / 2;
coordinates[11] = 0;
coordinates[12] = -adjustedRadius / 2;
coordinates[13] = adjustedRadius / 2;
coordinates[14] = -(rect.width() - adjustedRadius);
coordinates[15] = adjustedRadius / 2;
coordinates[16] = adjustedRadius / 2;
coordinates[17] = 0;
coordinates[18] = -adjustedRadius / 2;
coordinates[19] = -adjustedRadius / 2;
coordinates[20] = -(rect.height() - adjustedRadius);
coordinates[21] = adjustedRadius / 2;
coordinates[22] = adjustedRadius / 2;
coordinates[23] = 0;
coordinates[24] = adjustedRadius / 2;
coordinates[25] = -adjustedRadius / 2;
vgAppendPathData(path, 10, roundedRectCommands, coordinates.constData());
}
}
void QSGOpenVGInternalRectangleNode::generateBorderPath(const QRectF &rect, float borderWidth, float borderHeight, float radius, VGPath path) const
{
if (radius == 0) {
// squared frame
// Create command list
static const VGubyte squaredBorderCommands[] = {
VG_MOVE_TO_ABS,
VG_HLINE_TO_REL,
VG_VLINE_TO_REL,
VG_HLINE_TO_REL,
VG_MOVE_TO_ABS,
VG_VLINE_TO_REL,
VG_HLINE_TO_REL,
VG_VLINE_TO_REL,
VG_CLOSE_PATH
};
// Create command data
QVector<VGfloat> coordinates(10);
// Outside Square
coordinates[0] = rect.x();
coordinates[1] = rect.y();
coordinates[2] = rect.width();
coordinates[3] = rect.height();
coordinates[4] = -rect.width();
// Inside Square (opposite direction)
coordinates[5] = rect.x() + borderWidth;
coordinates[6] = rect.y() + borderHeight;
coordinates[7] = rect.height() - (borderHeight * 2);
coordinates[8] = rect.width() - (borderWidth * 2);
coordinates[9] = -(rect.height() - (borderHeight * 2));
vgAppendPathData(path, 9, squaredBorderCommands, coordinates.constData());
} else if (radius < qMax(borderWidth, borderHeight)){
// rounded outside, squared inside
// Create command list
static const VGubyte roundedRectCommands[] = {
VG_MOVE_TO_ABS,
VG_HLINE_TO_REL,
VG_SCCWARC_TO_REL,
VG_VLINE_TO_REL,
VG_SCCWARC_TO_REL,
VG_HLINE_TO_REL,
VG_SCCWARC_TO_REL,
VG_VLINE_TO_REL,
VG_SCCWARC_TO_REL,
VG_MOVE_TO_ABS,
VG_VLINE_TO_REL,
VG_HLINE_TO_REL,
VG_VLINE_TO_REL,
VG_CLOSE_PATH
};
// Ajust for OpenVG's usage or radius
float adjustedRadius = radius * 2;
// Create command data
QVector<VGfloat> coordinates(31);
// Outside Rounded Rect
coordinates[0] = rect.x() + adjustedRadius / 2;
coordinates[1] = rect.y();
coordinates[2] = rect.width() - adjustedRadius;
coordinates[3] = adjustedRadius / 2;
coordinates[4] = adjustedRadius / 2;
coordinates[5] = 0;
coordinates[6] = adjustedRadius / 2;
coordinates[7] = adjustedRadius / 2;
coordinates[8] = rect.height() - adjustedRadius;
coordinates[9] = adjustedRadius / 2;
coordinates[10] = adjustedRadius / 2;
coordinates[11] = 0;
coordinates[12] = -adjustedRadius / 2;
coordinates[13] = adjustedRadius / 2;
coordinates[14] = -(rect.width() - adjustedRadius);
coordinates[15] = adjustedRadius / 2;
coordinates[16] = adjustedRadius / 2;
coordinates[17] = 0;
coordinates[18] = -adjustedRadius / 2;
coordinates[19] = -adjustedRadius / 2;
coordinates[20] = -(rect.height() - adjustedRadius);
coordinates[21] = adjustedRadius / 2;
coordinates[22] = adjustedRadius / 2;
coordinates[23] = 0;
coordinates[24] = adjustedRadius / 2;
coordinates[25] = -adjustedRadius / 2;
// Inside Square (opposite direction)
coordinates[26] = rect.x() + borderWidth;
coordinates[27] = rect.y() + borderHeight;
coordinates[28] = rect.height() - (borderHeight * 2);
coordinates[29] = rect.width() - (borderWidth * 2);
coordinates[30] = -(rect.height() - (borderHeight * 2));
vgAppendPathData(path, 14, roundedRectCommands, coordinates.constData());
} else {
// rounded outside, rounded inside
static const VGubyte roundedBorderCommands[] = {
// Outer
VG_MOVE_TO_ABS,
VG_HLINE_TO_REL,
VG_SCCWARC_TO_REL,
VG_VLINE_TO_REL,
VG_SCCWARC_TO_REL,
VG_HLINE_TO_REL,
VG_SCCWARC_TO_REL,
VG_VLINE_TO_REL,
VG_SCCWARC_TO_REL,
// Inner
VG_MOVE_TO_ABS,
VG_SCWARC_TO_REL,
VG_VLINE_TO_REL,
VG_SCWARC_TO_REL,
VG_HLINE_TO_REL,
VG_SCWARC_TO_REL,
VG_VLINE_TO_REL,
VG_SCWARC_TO_REL,
VG_HLINE_TO_REL,
VG_CLOSE_PATH
};
// Adjust for OpenVG's usage or radius
float adjustedRadius = radius * 2;
float adjustedInnerRadius = (radius - qMax(borderWidth, borderHeight)) * 2;
// Create command data
QVector<VGfloat> coordinates(52);
// Outer
coordinates[0] = rect.x() + adjustedRadius / 2;
coordinates[1] = rect.y();
coordinates[2] = rect.width() - adjustedRadius;
coordinates[3] = adjustedRadius / 2;
coordinates[4] = adjustedRadius / 2;
coordinates[5] = 0;
coordinates[6] = adjustedRadius / 2;
coordinates[7] = adjustedRadius / 2;
coordinates[8] = rect.height() - adjustedRadius;
coordinates[9] = adjustedRadius / 2;
coordinates[10] = adjustedRadius / 2;
coordinates[11] = 0;
coordinates[12] = -adjustedRadius / 2;
coordinates[13] = adjustedRadius / 2;
coordinates[14] = -(rect.width() - adjustedRadius);
coordinates[15] = adjustedRadius / 2;
coordinates[16] = adjustedRadius / 2;
coordinates[17] = 0;
coordinates[18] = -adjustedRadius / 2;
coordinates[19] = -adjustedRadius / 2;
coordinates[20] = -(rect.height() - adjustedRadius);
coordinates[21] = adjustedRadius / 2;
coordinates[22] = adjustedRadius / 2;
coordinates[23] = 0;
coordinates[24] = adjustedRadius / 2;
coordinates[25] = -adjustedRadius / 2;
// Inner
coordinates[26] = rect.width() - (adjustedInnerRadius / 2 + borderWidth);
coordinates[27] = rect.height() - borderHeight;
coordinates[28] = adjustedInnerRadius / 2;
coordinates[29] = adjustedInnerRadius / 2;
coordinates[30] = 0;
coordinates[31] = adjustedInnerRadius / 2;
coordinates[32] = -adjustedInnerRadius / 2;
coordinates[33] = -((rect.height() - borderHeight * 2) - adjustedInnerRadius);
coordinates[34] = adjustedInnerRadius / 2;
coordinates[35] = adjustedInnerRadius / 2;
coordinates[36] = 0;
coordinates[37] = -adjustedInnerRadius / 2;
coordinates[38] = -adjustedInnerRadius / 2;
coordinates[39] = -((rect.width() - borderWidth * 2) - adjustedInnerRadius);
coordinates[40] = adjustedInnerRadius / 2;
coordinates[41] = adjustedInnerRadius / 2;
coordinates[42] = 0;
coordinates[43] = -adjustedInnerRadius / 2;
coordinates[44] = adjustedInnerRadius / 2;
coordinates[45] = (rect.height() - borderHeight * 2) - adjustedInnerRadius;
coordinates[46] = adjustedInnerRadius / 2;
coordinates[47] = adjustedInnerRadius / 2;
coordinates[48] = 0;
coordinates[49] = adjustedInnerRadius / 2;
coordinates[50] = adjustedInnerRadius / 2;
coordinates[51] = (rect.width() - borderWidth * 2) - adjustedInnerRadius;
vgAppendPathData(path, 19, roundedBorderCommands, coordinates.constData());
}
}
void QSGOpenVGInternalRectangleNode::generateRectangleAndBorderPaths(const QRectF &rect, float penWidth, float radius, VGPath inside, VGPath outside) const
{
//Borders can not be more than half the height/width of a rect
float borderWidth = qMin(penWidth, (float)rect.width() * 0.5f);
float borderHeight = qMin(penWidth, (float)rect.height() * 0.5f);
//Radius should never exceeds half of the width or half of the height
float adjustedRadius = qMin((float)qMin(rect.width(), rect.height()) * 0.5f, radius);
QRectF innerRect = rect;
innerRect.adjust(borderWidth, borderHeight, -borderWidth, -borderHeight);
if (radius == 0) {
// Regular rect with border
generateRectanglePath(innerRect, 0, inside);
generateBorderPath(rect, borderWidth, borderHeight, 0, outside);
} else {
// Rounded Rect with border
float innerRadius = radius - qMax(borderWidth, borderHeight);
if (innerRadius < 0)
innerRadius = 0.0f;
generateRectanglePath(innerRect, innerRadius, inside);
generateBorderPath(rect, borderWidth, borderHeight, adjustedRadius, outside);
}
}

View File

@ -0,0 +1,96 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSGOPENVGINTERNALRECTANGLENODE_H
#define QSGOPENVGINTERNALRECTANGLENODE_H
#include <private/qsgadaptationlayer_p.h>
#include "qsgopenvgrenderable.h"
#include <VG/openvg.h>
QT_BEGIN_NAMESPACE
class QSGOpenVGInternalRectangleNode : public QSGInternalRectangleNode, public QSGOpenVGRenderable
{
public:
QSGOpenVGInternalRectangleNode();
~QSGOpenVGInternalRectangleNode();
void setRect(const QRectF &rect) override;
void setColor(const QColor &color) override;
void setPenColor(const QColor &color) override;
void setPenWidth(qreal width) override;
void setGradientStops(const QGradientStops &stops) override;
void setRadius(qreal radius) override;
void setAligned(bool aligned) override;
void update() override;
void render() override;
void setOpacity(float opacity) override;
private:
void createVGResources();
void destroyVGResources();
void generateRectanglePath(const QRectF &rect, float radius, VGPath path) const;
void generateRectangleAndBorderPaths(const QRectF &rect, float penWidth, float radius, VGPath inside, VGPath outside) const;
void generateBorderPath(const QRectF &rect, float borderWidth, float borderHeight, float radius, VGPath path) const;
bool m_pathDirty = true;
bool m_fillDirty = true;
bool m_strokeDirty = true;
QRectF m_rect;
QColor m_fillColor;
QColor m_strokeColor;
qreal m_penWidth = 0.0;
qreal m_radius = 0.0;
bool m_aligned = false;
QGradientStops m_gradientStops;
VGPath m_rectanglePath;
VGPath m_borderPath;
VGPaint m_rectanglePaint;
VGPaint m_borderPaint;
};
QT_END_NAMESPACE
#endif // QSGOPENVGINTERNALRECTANGLENODE_H

View File

@ -0,0 +1,360 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsgopenvglayer.h"
#include "qsgopenvgrenderer_p.h"
#include "qsgopenvgcontext_p.h"
QT_BEGIN_NAMESPACE
QSGOpenVGLayer::QSGOpenVGLayer(QSGRenderContext *renderContext)
: m_item(nullptr)
, m_renderer(nullptr)
, m_device_pixel_ratio(1)
, m_mirrorHorizontal(false)
, m_mirrorVertical(false)
, m_live(true)
, m_grab(true)
, m_recursive(false)
, m_dirtyTexture(true)
, m_image(0)
, m_renderTarget(0)
, m_layerContext(0)
{
m_context = static_cast<QSGOpenVGRenderContext*>(renderContext);
m_vgContext = m_context->vgContext();
}
QSGOpenVGLayer::~QSGOpenVGLayer()
{
invalidated();
}
int QSGOpenVGLayer::textureId() const
{
return static_cast<int>(m_image);
}
QSize QSGOpenVGLayer::textureSize() const
{
if (m_image != 0) {
VGint imageWidth = vgGetParameteri(m_image, VG_IMAGE_WIDTH);
VGint imageHeight = vgGetParameteri(m_image, VG_IMAGE_HEIGHT);
return QSize(imageWidth, imageHeight);
}
return QSize();
}
bool QSGOpenVGLayer::hasAlphaChannel() const
{
VGImageFormat format = static_cast<VGImageFormat>(vgGetParameteri(m_image, VG_IMAGE_FORMAT));
switch (format) {
case VG_sRGBA_8888:
case VG_sRGBA_8888_PRE:
case VG_sRGBA_5551:
case VG_sRGBA_4444:
case VG_lRGBA_8888:
case VG_lRGBA_8888_PRE:
case VG_A_8:
case VG_A_1:
case VG_A_4:
case VG_sARGB_8888:
case VG_sARGB_8888_PRE:
case VG_sARGB_1555:
case VG_sARGB_4444:
case VG_lARGB_8888:
case VG_lARGB_8888_PRE:
case VG_sBGRA_8888:
case VG_sBGRA_8888_PRE:
case VG_sBGRA_5551:
case VG_sBGRA_4444:
case VG_lBGRA_8888:
case VG_lBGRA_8888_PRE:
case VG_sABGR_8888:
case VG_sABGR_8888_PRE:
case VG_sABGR_1555:
case VG_sABGR_4444:
case VG_lABGR_8888:
case VG_lABGR_8888_PRE:
return true;
break;
default:
break;
}
return false;
}
bool QSGOpenVGLayer::hasMipmaps() const
{
return false;
}
void QSGOpenVGLayer::bind()
{
}
bool QSGOpenVGLayer::updateTexture()
{
bool doGrab = (m_live || m_grab) && m_dirtyTexture;
if (doGrab)
grab();
if (m_grab)
emit scheduledUpdateCompleted();
m_grab = false;
return doGrab;
}
void QSGOpenVGLayer::setItem(QSGNode *item)
{
if (item == m_item)
return;
m_item = item;
if (m_live && !m_item) {
vgDestroyImage(m_image);
m_image = 0;
}
markDirtyTexture();
}
void QSGOpenVGLayer::setRect(const QRectF &rect)
{
if (rect == m_rect)
return;
m_rect = rect;
markDirtyTexture();
}
void QSGOpenVGLayer::setSize(const QSize &size)
{
if (size == m_size)
return;
m_size = size;
if (m_live && m_size.isNull()) {
vgDestroyImage(m_image);
m_image = 0;
}
markDirtyTexture();
}
void QSGOpenVGLayer::scheduleUpdate()
{
if (m_grab)
return;
m_grab = true;
if (m_dirtyTexture) {
emit updateRequested();
}
}
QImage QSGOpenVGLayer::toImage() const
{
// XXX
return QImage();
}
void QSGOpenVGLayer::setLive(bool live)
{
if (live == m_live)
return;
m_live = live;
if (m_live && (!m_item || m_size.isNull())) {
vgDestroyImage(m_image);
m_image = 0;
}
markDirtyTexture();
}
void QSGOpenVGLayer::setRecursive(bool recursive)
{
m_recursive = recursive;
}
void QSGOpenVGLayer::setFormat(uint format)
{
Q_UNUSED(format)
}
void QSGOpenVGLayer::setHasMipmaps(bool mipmap)
{
Q_UNUSED(mipmap)
}
void QSGOpenVGLayer::setDevicePixelRatio(qreal ratio)
{
m_device_pixel_ratio = ratio;
}
void QSGOpenVGLayer::setMirrorHorizontal(bool mirror)
{
if (m_mirrorHorizontal == mirror)
return;
m_mirrorHorizontal = mirror;
markDirtyTexture();
}
void QSGOpenVGLayer::setMirrorVertical(bool mirror)
{
if (m_mirrorVertical == mirror)
return;
m_mirrorVertical = mirror;
markDirtyTexture();
}
void QSGOpenVGLayer::markDirtyTexture()
{
m_dirtyTexture = true;
if (m_live || m_grab) {
emit updateRequested();
}
}
void QSGOpenVGLayer::invalidated()
{
delete m_renderer;
m_renderer = 0;
}
void QSGOpenVGLayer::grab()
{
if (!m_item || m_size.isNull()) {
vgDestroyImage(m_image);
m_image = 0;
m_dirtyTexture = false;
return;
}
QSGNode *root = m_item;
while (root->firstChild() && root->type() != QSGNode::RootNodeType)
root = root->firstChild();
if (root->type() != QSGNode::RootNodeType)
return;
if (!m_renderer) {
m_renderer = new QSGOpenVGRenderer(m_context);
connect(m_renderer, SIGNAL(sceneGraphChanged()), this, SLOT(markDirtyTexture()));
}
m_renderer->setDevicePixelRatio(m_device_pixel_ratio);
m_renderer->setRootNode(static_cast<QSGRootNode *>(root));
if (m_image == 0 || m_imageSize != m_size ) {
if (m_image != 0)
vgDestroyImage(m_image);
m_image = vgCreateImage(VG_lARGB_8888_PRE, m_size.width(), m_size.height(), VG_IMAGE_QUALITY_BETTER);
m_imageSize = m_size;
//Destroy old RenderTarget
if (m_renderTarget != 0)
eglDestroySurface(m_vgContext->eglDisplay(), m_renderTarget);
const EGLint configAttribs[] = {
EGL_CONFORMANT, EGL_OPENVG_BIT,
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_ALPHA_MASK_SIZE, 8,
EGL_NONE
};
EGLConfig pbufferConfig;
EGLint numConfig;
eglChooseConfig(m_vgContext->eglDisplay(), configAttribs, &pbufferConfig, 1, &numConfig);
if (m_layerContext == 0) {
// Create new context
m_layerContext = eglCreateContext(m_vgContext->eglDisplay(), pbufferConfig, m_vgContext->eglContext(), 0);
}
m_renderTarget = eglCreatePbufferFromClientBuffer(m_vgContext->eglDisplay(),
EGL_OPENVG_IMAGE,
(EGLClientBuffer)m_image,
pbufferConfig,
0);
}
if (m_renderTarget == EGL_NO_SURFACE) {
qDebug() << "invalid renderTarget!";
return;
}
// Render texture.
root->markDirty(QSGNode::DirtyForceUpdate); // Force matrix, clip and opacity update.
m_renderer->nodeChanged(root, QSGNode::DirtyForceUpdate); // Force render list update.
m_dirtyTexture = false;
m_renderer->setDeviceRect(m_size);
m_renderer->setViewportRect(m_size);
QRect mirrored(m_mirrorHorizontal ? m_rect.right() * m_device_pixel_ratio : m_rect.left() * m_device_pixel_ratio,
m_mirrorVertical ? m_rect.top() * m_device_pixel_ratio : m_rect.bottom() * m_device_pixel_ratio,
m_mirrorHorizontal ? -m_rect.width() * m_device_pixel_ratio : m_rect.width() * m_device_pixel_ratio,
m_mirrorVertical ? m_rect.height() * m_device_pixel_ratio : -m_rect.height() * m_device_pixel_ratio);
m_renderer->setProjectionMatrixToRect(mirrored);
m_renderer->setClearColor(Qt::transparent);
eglMakeCurrent(m_vgContext->eglDisplay(), m_renderTarget, m_renderTarget, m_layerContext);
// Before Rendering setup context for adjusting to Qt Coordinates to PixelBuffer
// Should already be inverted by default
vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
vgLoadIdentity();
m_renderer->renderScene();
eglSwapBuffers(m_vgContext->eglDisplay(), m_renderTarget);
// make the default surface current again
m_vgContext->makeCurrent();
root->markDirty(QSGNode::DirtyForceUpdate); // Force matrix, clip, opacity and render list update.
if (m_recursive)
markDirtyTexture(); // Continuously update if 'live' and 'recursive'.
}
QT_END_NAMESPACE

View File

@ -0,0 +1,115 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSGOPENVGLAYER_H
#define QSGOPENVGLAYER_H
#include <private/qsgadaptationlayer_p.h>
#include <private/qsgcontext_p.h>
#include "qopenvgcontext_p.h"
QT_BEGIN_NAMESPACE
class QSGOpenVGRenderer;
class QSGOpenVGRenderContext;
class QSGOpenVGLayer : public QSGLayer
{
public:
QSGOpenVGLayer(QSGRenderContext *renderContext);
~QSGOpenVGLayer();
// QSGTexture interface
public:
int textureId() const override;
QSize textureSize() const override;
bool hasAlphaChannel() const override;
bool hasMipmaps() const override;
void bind() override;
// QSGDynamicTexture interface
public:
bool updateTexture() override;
// QSGLayer interface
public:
void setItem(QSGNode *item) override;
void setRect(const QRectF &rect) override;
void setSize(const QSize &size) override;
void scheduleUpdate() override;
QImage toImage() const override;
void setLive(bool live) override;
void setRecursive(bool recursive) override;
void setFormat(uint format) override;
void setHasMipmaps(bool mipmap) override;
void setDevicePixelRatio(qreal ratio) override;
void setMirrorHorizontal(bool mirror) override;
void setMirrorVertical(bool mirror) override;
public slots:
void markDirtyTexture() override;
void invalidated() override;
private:
void grab();
QSGNode *m_item;
QSGOpenVGRenderContext *m_context;
QSGOpenVGRenderer *m_renderer;
QRectF m_rect;
QSize m_size;
qreal m_device_pixel_ratio;
bool m_mirrorHorizontal;
bool m_mirrorVertical;
bool m_live;
bool m_grab;
bool m_recursive;
bool m_dirtyTexture;
QOpenVGContext *m_vgContext;
VGImage m_image;
QSize m_imageSize;
EGLSurface m_renderTarget;
EGLContext m_layerContext;
};
QT_END_NAMESPACE
#endif // QSGOPENVGLAYER_H

View File

@ -0,0 +1,283 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsgopenvgnodevisitor.h"
#include "qsgopenvginternalrectanglenode.h"
#include "qsgopenvginternalimagenode.h"
#include "qsgopenvgpublicnodes.h"
#include "qsgopenvgglyphnode_p.h"
#include "qsgopenvgpainternode.h"
#include "qsgopenvgspritenode.h"
#include "qsgopenvgrenderable.h"
#include "qopenvgcontext_p.h"
#include <QtQuick/qsgsimplerectnode.h>
#include <QtQuick/qsgsimpletexturenode.h>
#include <QtQuick/qsgrendernode.h>
QT_BEGIN_NAMESPACE
QSGOpenVGNodeVisitor::QSGOpenVGNodeVisitor()
{
//Store the current matrix state
QVector<VGfloat> matrix(9);
vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
vgGetMatrix(matrix.data());
m_transformStack.push(QOpenVGMatrix(matrix.constData()));
// Opacity
m_opacityState.push(1.0f);
}
bool QSGOpenVGNodeVisitor::visit(QSGTransformNode *node)
{
const QVector<float> matrixData = { node->matrix().constData()[0], node->matrix().constData()[1], node->matrix().constData()[3],
node->matrix().constData()[4], node->matrix().constData()[5], node->matrix().constData()[7],
node->matrix().constData()[12], node->matrix().constData()[13], node->matrix().constData()[15] };
const QOpenVGMatrix matrix2d(matrixData.constData());
m_transformStack.push(m_transformStack.top() * matrix2d);
return true;
}
void QSGOpenVGNodeVisitor::endVisit(QSGTransformNode *)
{
m_transformStack.pop();
}
bool QSGOpenVGNodeVisitor::visit(QSGClipNode *node)
{
VGMaskOperation maskOperation = VG_INTERSECT_MASK;
if (m_clipStack.count() == 0) {
vgSeti(VG_MASKING, VG_TRUE);
vgMask(0,VG_FILL_MASK, 0, 0, VG_MAXINT, VG_MAXINT);
}
// Render clip node geometry to mask
vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
vgLoadMatrix(m_transformStack.top().constData());
VGPath clipPath = generateClipPath(node->clipRect());
vgRenderToMask(clipPath, VG_FILL_PATH, maskOperation);
auto clipState = new ClipState(clipPath, m_transformStack.top());
m_clipStack.push(clipState);
return true;
}
void QSGOpenVGNodeVisitor::endVisit(QSGClipNode *)
{
// Remove clip node geometry from mask
auto clipState = m_clipStack.pop();
vgDestroyPath(clipState->path);
if (m_clipStack.count() == 0) {
vgSeti(VG_MASKING, VG_FALSE);
} else {
// Recreate the mask
vgMask(0,VG_FILL_MASK, 0, 0, VG_MAXINT, VG_MAXINT);
for (auto state : m_clipStack) {
vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
vgLoadMatrix(state->transform.constData());
vgRenderToMask(state->path, VG_FILL_PATH, VG_INTERSECT_MASK);
}
}
delete clipState;
}
bool QSGOpenVGNodeVisitor::visit(QSGGeometryNode *node)
{
vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
vgLoadMatrix(m_transformStack.top().constData());
vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
vgLoadMatrix(m_transformStack.top().constData());
if (QSGSimpleRectNode *rectNode = dynamic_cast<QSGSimpleRectNode *>(node)) {
// TODO: Try and render the QSGSimpleRectNode
Q_UNUSED(rectNode)
return false;
} else if (QSGSimpleTextureNode *tn = dynamic_cast<QSGSimpleTextureNode *>(node)) {
// TODO: Try and render the QSGSimpleTextureNode
Q_UNUSED(tn)
return false;
} else if (QSGOpenVGNinePatchNode *nn = dynamic_cast<QSGOpenVGNinePatchNode *>(node)) {
renderRenderableNode(nn);
} else if (QSGOpenVGRectangleNode *rn = dynamic_cast<QSGOpenVGRectangleNode *>(node)) {
renderRenderableNode(rn);
} else if (QSGOpenVGImageNode *n = dynamic_cast<QSGOpenVGImageNode *>(node)) {
renderRenderableNode(n);
} else {
// We dont know, so skip
return false;
}
return true;
}
void QSGOpenVGNodeVisitor::endVisit(QSGGeometryNode *)
{
}
bool QSGOpenVGNodeVisitor::visit(QSGOpacityNode *node)
{
m_opacityState.push(m_opacityState.top() * node->opacity());
return true;
}
void QSGOpenVGNodeVisitor::endVisit(QSGOpacityNode *)
{
m_opacityState.pop();
}
bool QSGOpenVGNodeVisitor::visit(QSGInternalImageNode *node)
{
vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
vgLoadMatrix(m_transformStack.top().constData());
renderRenderableNode(static_cast<QSGOpenVGInternalImageNode*>(node));
return true;
}
void QSGOpenVGNodeVisitor::endVisit(QSGInternalImageNode *)
{
}
bool QSGOpenVGNodeVisitor::visit(QSGPainterNode *node)
{
vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
vgLoadMatrix(m_transformStack.top().constData());
renderRenderableNode(static_cast<QSGOpenVGPainterNode*>(node));
return true;
}
void QSGOpenVGNodeVisitor::endVisit(QSGPainterNode *)
{
}
bool QSGOpenVGNodeVisitor::visit(QSGInternalRectangleNode *node)
{
vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
vgLoadMatrix(m_transformStack.top().constData());
renderRenderableNode(static_cast<QSGOpenVGInternalRectangleNode*>(node));
return true;
}
void QSGOpenVGNodeVisitor::endVisit(QSGInternalRectangleNode *)
{
}
bool QSGOpenVGNodeVisitor::visit(QSGGlyphNode *node)
{
vgSeti(VG_MATRIX_MODE, VG_MATRIX_GLYPH_USER_TO_SURFACE);
vgLoadMatrix(m_transformStack.top().constData());
renderRenderableNode(static_cast<QSGOpenVGGlyphNode*>(node));
return true;
}
void QSGOpenVGNodeVisitor::endVisit(QSGGlyphNode *)
{
}
bool QSGOpenVGNodeVisitor::visit(QSGRootNode *)
{
return true;
}
void QSGOpenVGNodeVisitor::endVisit(QSGRootNode *)
{
}
bool QSGOpenVGNodeVisitor::visit(QSGSpriteNode *node)
{
vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
vgLoadMatrix(m_transformStack.top().constData());
renderRenderableNode(static_cast<QSGOpenVGSpriteNode*>(node));
return true;
}
void QSGOpenVGNodeVisitor::endVisit(QSGSpriteNode *)
{
}
bool QSGOpenVGNodeVisitor::visit(QSGRenderNode *)
{
return true;
}
void QSGOpenVGNodeVisitor::endVisit(QSGRenderNode *)
{
}
VGPath QSGOpenVGNodeVisitor::generateClipPath(const QRectF &rect) const
{
VGPath clipPath = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1, 0, 0, 0,
VG_PATH_CAPABILITY_APPEND_TO);
// Create command list
static const VGubyte rectCommands[] = {
VG_MOVE_TO_ABS,
VG_HLINE_TO_REL,
VG_VLINE_TO_REL,
VG_HLINE_TO_REL,
VG_CLOSE_PATH
};
// Create command data
QVector<VGfloat> coordinates(5);
coordinates[0] = rect.x();
coordinates[1] = rect.y();
coordinates[2] = rect.width();
coordinates[3] = rect.height();
coordinates[4] = -rect.width();
vgAppendPathData(clipPath, 5, rectCommands, coordinates.constData());
return clipPath;
}
void QSGOpenVGNodeVisitor::renderRenderableNode(QSGOpenVGRenderable *node)
{
if (!node)
return;
node->setOpacity(m_opacityState.top());
node->render();
}
QT_END_NAMESPACE

View File

@ -0,0 +1,104 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSGOPENVGNODEVISITOR_H
#define QSGOPENVGNODEVISITOR_H
#include <private/qsgadaptationlayer_p.h>
#include <QtCore/QStack>
#include "qopenvgmatrix.h"
#include <VG/openvg.h>
QT_BEGIN_NAMESPACE
class QSGOpenVGRenderable;
class QSGOpenVGNodeVisitor : public QSGNodeVisitorEx
{
public:
QSGOpenVGNodeVisitor();
bool visit(QSGTransformNode *) override;
void endVisit(QSGTransformNode *) override;
bool visit(QSGClipNode *) override;
void endVisit(QSGClipNode *) override;
bool visit(QSGGeometryNode *) override;
void endVisit(QSGGeometryNode *) override;
bool visit(QSGOpacityNode *) override;
void endVisit(QSGOpacityNode *) override;
bool visit(QSGInternalImageNode *) override;
void endVisit(QSGInternalImageNode *) override;
bool visit(QSGPainterNode *) override;
void endVisit(QSGPainterNode *) override;
bool visit(QSGInternalRectangleNode *) override;
void endVisit(QSGInternalRectangleNode *) override;
bool visit(QSGGlyphNode *) override;
void endVisit(QSGGlyphNode *) override;
bool visit(QSGRootNode *) override;
void endVisit(QSGRootNode *) override;
bool visit(QSGSpriteNode *) override;
void endVisit(QSGSpriteNode *) override;
bool visit(QSGRenderNode *) override;
void endVisit(QSGRenderNode *) override;
private:
struct ClipState {
ClipState(VGPath p, QOpenVGMatrix t)
{
path = p;
transform = t;
}
VGPath path;
QOpenVGMatrix transform;
};
VGPath generateClipPath(const QRectF &rect) const;
void renderRenderableNode(QSGOpenVGRenderable *node);
QStack<QOpenVGMatrix> m_transformStack;
QStack<float> m_opacityState;
QStack<ClipState*> m_clipStack;
};
QT_END_NAMESPACE
#endif // QSGOPENVGNODEVISITOR_H

View File

@ -0,0 +1,249 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsgopenvgpainternode.h"
#include "qsgopenvgtexture.h"
#include <qmath.h>
#include <QtGui/QPainter>
QT_BEGIN_NAMESPACE
QSGOpenVGPainterNode::QSGOpenVGPainterNode(QQuickPaintedItem *item)
: m_preferredRenderTarget(QQuickPaintedItem::Image)
, m_item(item)
, m_texture(nullptr)
, m_dirtyContents(false)
, m_opaquePainting(false)
, m_linear_filtering(false)
, m_smoothPainting(false)
, m_fillColor(Qt::transparent)
, m_contentsScale(1.0)
, m_dirtyGeometry(false)
{
// Set Dummy material and geometry to avoid asserts
setMaterial((QSGMaterial*)1);
setGeometry((QSGGeometry*)1);
}
QSGOpenVGPainterNode::~QSGOpenVGPainterNode()
{
delete m_texture;
}
void QSGOpenVGPainterNode::setPreferredRenderTarget(QQuickPaintedItem::RenderTarget)
{
}
void QSGOpenVGPainterNode::setSize(const QSize &size)
{
if (size == m_size)
return;
m_size = size;
m_dirtyGeometry = true;
}
void QSGOpenVGPainterNode::setDirty(const QRect &dirtyRect)
{
m_dirtyContents = true;
m_dirtyRect = dirtyRect;
markDirty(DirtyMaterial);
}
void QSGOpenVGPainterNode::setOpaquePainting(bool opaque)
{
if (opaque == m_opaquePainting)
return;
m_opaquePainting = opaque;
}
void QSGOpenVGPainterNode::setLinearFiltering(bool linearFiltering)
{
if (linearFiltering == m_linear_filtering)
return;
m_linear_filtering = linearFiltering;
}
void QSGOpenVGPainterNode::setMipmapping(bool)
{
}
void QSGOpenVGPainterNode::setSmoothPainting(bool s)
{
if (s == m_smoothPainting)
return;
m_smoothPainting = s;
}
void QSGOpenVGPainterNode::setFillColor(const QColor &c)
{
if (c == m_fillColor)
return;
m_fillColor = c;
markDirty(DirtyMaterial);
}
void QSGOpenVGPainterNode::setContentsScale(qreal s)
{
if (s == m_contentsScale)
return;
m_contentsScale = s;
markDirty(DirtyMaterial);
}
void QSGOpenVGPainterNode::setFastFBOResizing(bool)
{
}
void QSGOpenVGPainterNode::setTextureSize(const QSize &size)
{
if (size == m_textureSize)
return;
m_textureSize = size;
m_dirtyGeometry = true;
}
QImage QSGOpenVGPainterNode::toImage() const
{
return m_image;
}
void QSGOpenVGPainterNode::update()
{
if (m_dirtyGeometry) {
if (!m_opaquePainting)
m_image = QImage(m_size, QImage::Format_ARGB32_Premultiplied);
else
m_image = QImage(m_size, QImage::Format_RGB32);
}
if (m_dirtyContents)
paint();
m_dirtyGeometry = false;
m_dirtyContents = false;
}
QSGTexture *QSGOpenVGPainterNode::texture() const
{
return m_texture;
}
void QSGOpenVGPainterNode::render()
{
if (!m_texture)
return;
// Set Draw Mode
if (opacity() < 1.0) {
//Transparent
vgSetPaint(opacityPaint(), VG_FILL_PATH);
vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_MULTIPLY);
} else {
vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL);
}
if (m_linear_filtering)
vgSeti(VG_IMAGE_QUALITY, VG_IMAGE_QUALITY_BETTER);
else
vgSeti(VG_IMAGE_QUALITY, VG_IMAGE_QUALITY_NONANTIALIASED);
vgDrawImage(static_cast<VGImage>(m_texture->textureId()));
}
void QSGOpenVGPainterNode::paint()
{
QRect dirtyRect = m_dirtyRect.isNull() ? QRect(0, 0, m_size.width(), m_size.height()) : m_dirtyRect;
QPainter painter;
painter.begin(&m_image);
if (m_smoothPainting) {
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
}
QRect clipRect;
if (m_contentsScale == 1) {
qreal scaleX = m_textureSize.width() / (qreal) m_size.width();
qreal scaleY = m_textureSize.height() / (qreal) m_size.height();
painter.scale(scaleX, scaleY);
clipRect = dirtyRect;
} else {
painter.scale(m_contentsScale, m_contentsScale);
QRect sclip(qFloor(dirtyRect.x()/m_contentsScale),
qFloor(dirtyRect.y()/m_contentsScale),
qCeil(dirtyRect.width()/m_contentsScale+dirtyRect.x()/m_contentsScale-qFloor(dirtyRect.x()/m_contentsScale)),
qCeil(dirtyRect.height()/m_contentsScale+dirtyRect.y()/m_contentsScale-qFloor(dirtyRect.y()/m_contentsScale)));
clipRect = sclip;
}
if (!m_dirtyRect.isNull())
painter.setClipRect(clipRect);
painter.setCompositionMode(QPainter::CompositionMode_Source);
painter.fillRect(clipRect, m_fillColor);
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
m_item->paint(&painter);
painter.end();
m_dirtyRect = QRect();
if (m_texture)
delete m_texture;
uint textureFlags = m_opaquePainting ? 0 : QSGRenderContext::CreateTexture_Alpha;
m_texture = new QSGOpenVGTexture(m_image, textureFlags);
}
QT_END_NAMESPACE

View File

@ -0,0 +1,97 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSGOPENVGPAINTERNODE_H
#define QSGOPENVGPAINTERNODE_H
#include <private/qsgadaptationlayer_p.h>
#include <QtQuick/QQuickPaintedItem>
#include "qsgopenvgrenderable.h"
QT_BEGIN_NAMESPACE
class QSGOpenVGTexture;
class QSGOpenVGPainterNode : public QSGPainterNode, public QSGOpenVGRenderable
{
public:
QSGOpenVGPainterNode(QQuickPaintedItem *item);
~QSGOpenVGPainterNode();
void setPreferredRenderTarget(QQuickPaintedItem::RenderTarget target) override;
void setSize(const QSize &size) override;
void setDirty(const QRect &dirtyRect) override;
void setOpaquePainting(bool opaque) override;
void setLinearFiltering(bool linearFiltering) override;
void setMipmapping(bool mipmapping) override;
void setSmoothPainting(bool s) override;
void setFillColor(const QColor &c) override;
void setContentsScale(qreal s) override;
void setFastFBOResizing(bool dynamic) override;
void setTextureSize(const QSize &size) override;
QImage toImage() const override;
void update() override;
QSGTexture *texture() const override;
void render() override;
void paint();
private:
QQuickPaintedItem::RenderTarget m_preferredRenderTarget;
QQuickPaintedItem *m_item;
QSGOpenVGTexture *m_texture;
QImage m_image;
QSize m_size;
bool m_dirtyContents;
QRect m_dirtyRect;
bool m_opaquePainting;
bool m_linear_filtering;
bool m_smoothPainting;
QColor m_fillColor;
qreal m_contentsScale;
QSize m_textureSize;
bool m_dirtyGeometry;
};
QT_END_NAMESPACE
#endif // QSGOPENVGPAINTERNODE_H

View File

@ -0,0 +1,266 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsgopenvgpublicnodes.h"
#include "qsgopenvghelpers.h"
QT_BEGIN_NAMESPACE
QSGOpenVGRectangleNode::QSGOpenVGRectangleNode()
{
// Set Dummy material and geometry to avoid asserts
setMaterial((QSGMaterial*)1);
setGeometry((QSGGeometry*)1);
m_rectPath = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1, 0, 0, 0,
VG_PATH_CAPABILITY_APPEND_TO);
m_rectPaint = vgCreatePaint();
}
QSGOpenVGRectangleNode::~QSGOpenVGRectangleNode()
{
vgDestroyPaint(m_rectPaint);
vgDestroyPath(m_rectPath);
}
void QSGOpenVGRectangleNode::setRect(const QRectF &rect)
{
m_rect = rect;
m_pathDirty = true;
markDirty(DirtyMaterial);
}
void QSGOpenVGRectangleNode::setColor(const QColor &color)
{
m_color = color;
m_paintDirty = true;
markDirty(DirtyMaterial);
}
void QSGOpenVGRectangleNode::render()
{
if (m_pathDirty) {
vgClearPath(m_rectPath, VG_PATH_CAPABILITY_APPEND_TO);
// Create command list
static const VGubyte rectCommands[] = {
VG_MOVE_TO_ABS,
VG_HLINE_TO_REL,
VG_VLINE_TO_REL,
VG_HLINE_TO_REL,
VG_CLOSE_PATH
};
// Create command data
QVector<VGfloat> coordinates(5);
coordinates[0] = m_rect.x();
coordinates[1] = m_rect.y();
coordinates[2] = m_rect.width();
coordinates[3] = m_rect.height();
coordinates[4] = -m_rect.width();
vgAppendPathData(m_rectPath, 5, rectCommands, coordinates.constData());
m_pathDirty = false;
}
if (m_paintDirty) {
vgSetPaint(m_rectPaint, VG_FILL_PATH);
vgSetParameteri(m_rectPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
vgSetParameterfv(m_rectPaint, VG_PAINT_COLOR, 4, QSGOpenVGHelpers::qColorToVGColor(m_color).constData());
m_paintDirty = false;
}
vgSetPaint(m_rectPaint, VG_FILL_PATH);
vgDrawPath(m_rectPath, VG_FILL_PATH);
}
QSGOpenVGImageNode::QSGOpenVGImageNode()
{
// Set Dummy material and geometry to avoid asserts
setMaterial((QSGMaterial*)1);
setGeometry((QSGGeometry*)1);
}
QSGOpenVGImageNode::~QSGOpenVGImageNode()
{
if (m_owns) {
m_texture->deleteLater();
}
}
void QSGOpenVGImageNode::setTexture(QSGTexture *texture)
{
m_texture = texture;
markDirty(DirtyMaterial);
}
void QSGOpenVGImageNode::setTextureCoordinatesTransform(QSGImageNode::TextureCoordinatesTransformMode transformNode)
{
if (m_transformMode == transformNode)
return;
m_transformMode = transformNode;
markDirty(DirtyGeometry);
}
void QSGOpenVGImageNode::render()
{
if (!m_texture) {
return;
}
// Set Draw Mode
if (opacity() < 1.0) {
//Transparent
vgSetPaint(opacityPaint(), VG_FILL_PATH);
vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_MULTIPLY);
} else {
vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL);
}
VGImage image = static_cast<VGImage>(m_texture->textureId());
//Apply the TextureCoordinateTransform Flag
if (m_transformMode != QSGImageNode::NoTransform) {
float translateX = 0.0f;
float translateY = 0.0f;
float scaleX = 1.0f;
float scaleY = 1.0f;
if (m_transformMode & QSGImageNode::MirrorHorizontally) {
translateX = m_rect.width();
scaleX = -1.0;
}
if (m_transformMode & QSGImageNode::MirrorVertically) {
translateY = m_rect.height();
scaleY = -1.0;
}
vgTranslate(translateX, translateY);
vgScale(scaleX, scaleY);
}
// If the the source rect is the same as the target rect
if (m_sourceRect == m_rect) {
vgDrawImage(image);
} else {
// Scale
float scaleX = m_rect.width() / m_sourceRect.width();
float scaleY = m_rect.height() / m_sourceRect.height();
vgScale(scaleX, scaleY);
VGImage subImage = vgChildImage(image, m_sourceRect.x(), m_sourceRect.y(), m_sourceRect.width(), m_sourceRect.height());
vgDrawImage(subImage);
vgDestroyImage(subImage);
}
}
QSGOpenVGNinePatchNode::QSGOpenVGNinePatchNode()
{
// Set Dummy material and geometry to avoid asserts
setMaterial((QSGMaterial*)1);
setGeometry((QSGGeometry*)1);
}
void QSGOpenVGNinePatchNode::setTexture(QSGTexture *texture)
{
m_texture = texture;
markDirty(DirtyMaterial);
}
void QSGOpenVGNinePatchNode::setBounds(const QRectF &bounds)
{
if (m_bounds == bounds)
return;
m_bounds = bounds;
markDirty(DirtyGeometry);
}
void QSGOpenVGNinePatchNode::setDevicePixelRatio(qreal ratio)
{
if (m_pixelRatio == ratio)
return;
m_pixelRatio = ratio;
markDirty(DirtyGeometry);
}
void QSGOpenVGNinePatchNode::setPadding(qreal left, qreal top, qreal right, qreal bottom)
{
QMarginsF margins(left, top, right, bottom);
if (m_margins == margins)
return;
m_margins = margins;
markDirty(DirtyGeometry);
}
void QSGOpenVGNinePatchNode::update()
{
}
void QSGOpenVGNinePatchNode::render()
{
if (!m_texture)
return;
// Set Draw Mode
if (opacity() < 1.0) {
//Transparent
vgSetPaint(opacityPaint(), VG_FILL_PATH);
vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_MULTIPLY);
} else {
vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL);
}
VGImage image = static_cast<VGImage>(m_texture->textureId());
//Draw borderImage
QSGOpenVGHelpers::qDrawBorderImage(image, m_texture->textureSize(), m_bounds, m_bounds.marginsRemoved(m_margins), QRectF(0, 0, 1, 1));
}
QRectF QSGOpenVGNinePatchNode::bounds() const
{
return m_bounds;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,143 @@
#ifndef QSGOPENVGPUBLICNODES_H
#define QSGOPENVGPUBLICNODES_H
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtQuick/qsgrectanglenode.h>
#include <QtQuick/qsgimagenode.h>
#include <QtQuick/qsgninepatchnode.h>
#include <QtGui/QPixmap>
#include <VG/openvg.h>
#include "qsgopenvgrenderable.h"
QT_BEGIN_NAMESPACE
class QSGOpenVGRectangleNode : public QSGRectangleNode, public QSGOpenVGRenderable
{
public:
QSGOpenVGRectangleNode();
~QSGOpenVGRectangleNode();
void setRect(const QRectF &rect) override;
QRectF rect() const override { return m_rect; }
void setColor(const QColor &color) override;
QColor color() const override { return m_color; }
void render() override;
private:
QRectF m_rect;
QColor m_color;
bool m_pathDirty = true;
bool m_paintDirty = true;
VGPath m_rectPath;
VGPaint m_rectPaint;
};
class QSGOpenVGImageNode : public QSGImageNode, public QSGOpenVGRenderable
{
public:
QSGOpenVGImageNode();
~QSGOpenVGImageNode();
void setRect(const QRectF &rect) override { m_rect = rect; markDirty(DirtyMaterial); }
QRectF rect() const override { return m_rect; }
void setSourceRect(const QRectF &r) override { m_sourceRect = r; }
QRectF sourceRect() const override { return m_sourceRect; }
void setTexture(QSGTexture *texture) override;
QSGTexture *texture() const override { return m_texture; }
void setFiltering(QSGTexture::Filtering filtering) override { m_filtering = filtering; markDirty(DirtyMaterial); }
QSGTexture::Filtering filtering() const override { return m_filtering; }
void setMipmapFiltering(QSGTexture::Filtering) override { }
QSGTexture::Filtering mipmapFiltering() const override { return QSGTexture::None; }
void setTextureCoordinatesTransform(TextureCoordinatesTransformMode transformNode) override;
TextureCoordinatesTransformMode textureCoordinatesTransform() const override { return m_transformMode; }
void setOwnsTexture(bool owns) override { m_owns = owns; }
bool ownsTexture() const override { return m_owns; }
void render() override;
private:
QSGTexture *m_texture;
QRectF m_rect;
QRectF m_sourceRect;
bool m_owns;
QSGTexture::Filtering m_filtering;
TextureCoordinatesTransformMode m_transformMode;
};
class QSGOpenVGNinePatchNode : public QSGNinePatchNode, public QSGOpenVGRenderable
{
public:
QSGOpenVGNinePatchNode();
void setTexture(QSGTexture *texture) override;
void setBounds(const QRectF &bounds) override;
void setDevicePixelRatio(qreal ratio) override;
void setPadding(qreal left, qreal top, qreal right, qreal bottom) override;
void update() override;
void render() override;
QRectF bounds() const;
private:
QSGTexture *m_texture;
QRectF m_bounds;
qreal m_pixelRatio;
QMarginsF m_margins;
};
QT_END_NAMESPACE
#endif // QSGOPENVGPUBLICNODES_H

View File

@ -0,0 +1,77 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsgopenvgrenderable.h"
QT_BEGIN_NAMESPACE
QSGOpenVGRenderable::QSGOpenVGRenderable()
: m_opacity(1.0f)
{
m_opacityPaint = vgCreatePaint();
}
QSGOpenVGRenderable::~QSGOpenVGRenderable()
{
vgDestroyPaint(m_opacityPaint);
}
void QSGOpenVGRenderable::setOpacity(float opacity)
{
if (m_opacity == opacity)
return;
m_opacity = opacity;
VGfloat values[] = {
1.0f, 1.0f, 1.0f, m_opacity
};
vgSetParameterfv(m_opacityPaint, VG_PAINT_COLOR, 4, values);
}
float QSGOpenVGRenderable::opacity() const
{
return m_opacity;
}
VGPaint QSGOpenVGRenderable::opacityPaint() const
{
return m_opacityPaint;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,69 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSGOPENVGRENDERABLE_H
#define QSGOPENVGRENDERABLE_H
#include <QtGlobal>
#include <VG/openvg.h>
QT_BEGIN_NAMESPACE
class QSGOpenVGRenderable
{
public:
QSGOpenVGRenderable();
virtual ~QSGOpenVGRenderable();
virtual void render() = 0;
virtual void setOpacity(float opacity);
float opacity() const;
VGPaint opacityPaint() const;
private:
float m_opacity;
VGPaint m_opacityPaint;
};
QT_END_NAMESPACE
#endif // QSGOPENVGRENDERABLE_H

View File

@ -0,0 +1,90 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsgopenvgrenderer_p.h"
#include "qsgopenvgcontext_p.h"
#include "qsgopenvgnodevisitor.h"
#include "qopenvgcontext_p.h"
#include "qsgopenvghelpers.h"
#include <QtGui/QWindow>
#include <VG/openvg.h>
QT_BEGIN_NAMESPACE
QSGOpenVGRenderer::QSGOpenVGRenderer(QSGRenderContext *context)
: QSGRenderer(context)
{
}
QSGOpenVGRenderer::~QSGOpenVGRenderer()
{
}
void QSGOpenVGRenderer::renderScene(uint fboId)
{
Q_UNUSED(fboId)
class B : public QSGBindable
{
public:
void bind() const { }
} bindable;
QSGRenderer::renderScene(bindable);
}
void QSGOpenVGRenderer::render()
{
//Clear the window geometry with the clear color
vgSetfv(VG_CLEAR_COLOR, 4, QSGOpenVGHelpers::qColorToVGColor(clearColor()).constData());
vgClear(0, 0, VG_MAXINT, VG_MAXINT);
// Visit each node to render scene
QSGOpenVGNodeVisitor rendererVisitor;
rendererVisitor.visitChildren(rootNode());
}
void QSGOpenVGRenderer::nodeChanged(QSGNode *node, QSGNode::DirtyState state)
{
QSGRenderer::nodeChanged(node, state);
}
QT_END_NAMESPACE

View File

@ -0,0 +1,61 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSGOPENVGRENDERER_H
#define QSGOPENVGRENDERER_H
#include <private/qsgrenderer_p.h>
QT_BEGIN_NAMESPACE
class QSGOpenVGRenderer : public QSGRenderer
{
public:
QSGOpenVGRenderer(QSGRenderContext *context);
virtual ~QSGOpenVGRenderer();
void nodeChanged(QSGNode *node, QSGNode::DirtyState state) override;
void renderScene(uint fboId = 0) final;
void render() final;
};
QT_END_NAMESPACE
#endif // QSGOPENVGRENDERER_H

View File

@ -0,0 +1,257 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsgopenvgrenderloop_p.h"
#include "qsgopenvgcontext_p.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QElapsedTimer>
#include <private/qquickwindow_p.h>
#include <private/qquickprofiler_p.h>
#include "qopenvgcontext_p.h"
QT_BEGIN_NAMESPACE
QSGOpenVGRenderLoop::QSGOpenVGRenderLoop()
: vg(nullptr)
{
sg = QSGContext::createDefaultContext();
rc = sg->createRenderContext();
}
QSGOpenVGRenderLoop::~QSGOpenVGRenderLoop()
{
delete rc;
delete sg;
}
void QSGOpenVGRenderLoop::show(QQuickWindow *window)
{
WindowData data;
data.updatePending = false;
data.grabOnly = false;
m_windows[window] = data;
maybeUpdate(window);
}
void QSGOpenVGRenderLoop::hide(QQuickWindow *window)
{
QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window);
cd->fireAboutToStop();
}
void QSGOpenVGRenderLoop::windowDestroyed(QQuickWindow *window)
{
m_windows.remove(window);
hide(window);
QQuickWindowPrivate *d = QQuickWindowPrivate::get(window);
d->cleanupNodesOnShutdown();
if (m_windows.size() == 0) {
rc->invalidate();
delete vg;
vg = nullptr;
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
} else if (vg && window == vg->window()) {
vg->doneCurrent();
}
}
void QSGOpenVGRenderLoop::exposureChanged(QQuickWindow *window)
{
if (window->isExposed()) {
m_windows[window].updatePending = true;
renderWindow(window);
}
}
QImage QSGOpenVGRenderLoop::grab(QQuickWindow *window)
{
if (!m_windows.contains(window))
return QImage();
m_windows[window].grabOnly = true;
renderWindow(window);
QImage grabbed = grabContent;
grabContent = QImage();
return grabbed;
}
void QSGOpenVGRenderLoop::update(QQuickWindow *window)
{
maybeUpdate(window);
}
void QSGOpenVGRenderLoop::handleUpdateRequest(QQuickWindow *window)
{
renderWindow(window);
}
void QSGOpenVGRenderLoop::maybeUpdate(QQuickWindow *window)
{
if (!m_windows.contains(window))
return;
m_windows[window].updatePending = true;
window->requestUpdate();
}
QAnimationDriver *QSGOpenVGRenderLoop::animationDriver() const
{
return nullptr;
}
QSGContext *QSGOpenVGRenderLoop::sceneGraphContext() const
{
return sg;
}
QSGRenderContext *QSGOpenVGRenderLoop::createRenderContext(QSGContext *) const
{
return rc;
}
void QSGOpenVGRenderLoop::releaseResources(QQuickWindow *window)
{
Q_UNUSED(window)
}
QSurface::SurfaceType QSGOpenVGRenderLoop::windowSurfaceType() const
{
return QSurface::OpenVGSurface;
}
void QSGOpenVGRenderLoop::renderWindow(QQuickWindow *window)
{
QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window);
if (!cd->isRenderable() || !m_windows.contains(window))
return;
WindowData &data = const_cast<WindowData &>(m_windows[window]);
if (vg == nullptr) {
vg = new QOpenVGContext(window);
vg->makeCurrent();
cd->context->initialize(vg);
} else {
vg->makeCurrent();
}
bool alsoSwap = data.updatePending;
data.updatePending = false;
if (!data.grabOnly) {
// Event delivery/processing triggered the window to be deleted or stop rendering.
if (!m_windows.contains(window))
return;
}
QElapsedTimer renderTimer;
qint64 renderTime = 0, syncTime = 0, polishTime = 0;
bool profileFrames = QSG_OPENVG_LOG_TIME_RENDERLOOP().isDebugEnabled();
if (profileFrames)
renderTimer.start();
Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphPolishFrame);
cd->polishItems();
if (profileFrames)
polishTime = renderTimer.nsecsElapsed();
Q_QUICK_SG_PROFILE_SWITCH(QQuickProfiler::SceneGraphPolishFrame,
QQuickProfiler::SceneGraphRenderLoopFrame);
emit window->afterAnimating();
cd->syncSceneGraph();
if (profileFrames)
syncTime = renderTimer.nsecsElapsed();
Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame);
// setup coordinate system for window
vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
vgLoadIdentity();
vgTranslate(0.0f, window->size().height());
vgScale(1.0, -1.0);
cd->renderSceneGraph(window->size());
if (profileFrames)
renderTime = renderTimer.nsecsElapsed();
Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame);
if (data.grabOnly) {
grabContent = vg->readFramebuffer(window->size() * window->effectiveDevicePixelRatio());
data.grabOnly = false;
}
if (alsoSwap && window->isVisible()) {
vg->swapBuffers();
cd->fireFrameSwapped();
}
qint64 swapTime = 0;
if (profileFrames)
swapTime = renderTimer.nsecsElapsed();
Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphRenderLoopFrame);
if (QSG_OPENVG_LOG_TIME_RENDERLOOP().isDebugEnabled()) {
static QTime lastFrameTime = QTime::currentTime();
qCDebug(QSG_OPENVG_LOG_TIME_RENDERLOOP,
"Frame rendered with 'basic' renderloop in %dms, polish=%d, sync=%d, render=%d, swap=%d, frameDelta=%d",
int(swapTime / 1000000),
int(polishTime / 1000000),
int((syncTime - polishTime) / 1000000),
int((renderTime - syncTime) / 1000000),
int((swapTime - renderTime) / 10000000),
int(lastFrameTime.msecsTo(QTime::currentTime())));
lastFrameTime = QTime::currentTime();
}
// Might have been set during syncSceneGraph()
if (data.updatePending)
maybeUpdate(window);
}
QT_END_NAMESPACE

View File

@ -0,0 +1,94 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSGOPENVGRENDERLOOP_H
#define QSGOPENVGRENDERLOOP_H
#include <private/qsgrenderloop_p.h>
QT_BEGIN_NAMESPACE
class QOpenVGContext;
class QSGOpenVGRenderLoop : public QSGRenderLoop
{
public:
QSGOpenVGRenderLoop();
~QSGOpenVGRenderLoop();
void show(QQuickWindow *window) override;
void hide(QQuickWindow *window) override;
void windowDestroyed(QQuickWindow *window) override;
void renderWindow(QQuickWindow *window);
void exposureChanged(QQuickWindow *window) override;
QImage grab(QQuickWindow *window) override;
void maybeUpdate(QQuickWindow *window) override;
void update(QQuickWindow *window) override;
void handleUpdateRequest(QQuickWindow *window) override;
void releaseResources(QQuickWindow *) override;
QSurface::SurfaceType windowSurfaceType() const override;
QAnimationDriver *animationDriver() const override;
QSGContext *sceneGraphContext() const override;
QSGRenderContext *createRenderContext(QSGContext *) const override;
struct WindowData {
bool updatePending : 1;
bool grabOnly : 1;
};
QHash<QQuickWindow *, WindowData> m_windows;
QSGContext *sg;
QSGRenderContext *rc;
QOpenVGContext *vg;
QImage grabContent;
};
QT_END_NAMESPACE
#endif // QSGOPENVGRENDERLOOP_H

View File

@ -0,0 +1,153 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsgopenvgspritenode.h"
#include "qsgopenvgtexture.h"
QT_BEGIN_NAMESPACE
QSGOpenVGSpriteNode::QSGOpenVGSpriteNode()
: m_time(0.0f)
{
// Set Dummy material and geometry to avoid asserts
setMaterial((QSGMaterial*)1);
setGeometry((QSGGeometry*)1);
}
QSGOpenVGSpriteNode::~QSGOpenVGSpriteNode()
{
}
void QSGOpenVGSpriteNode::setTexture(QSGTexture *texture)
{
m_texture = static_cast<QSGOpenVGTexture*>(texture);
markDirty(DirtyMaterial);
}
void QSGOpenVGSpriteNode::setTime(float time)
{
if (m_time != time) {
m_time = time;
markDirty(DirtyMaterial);
}
}
void QSGOpenVGSpriteNode::setSourceA(const QPoint &source)
{
if (m_sourceA != source) {
m_sourceA = source;
markDirty(DirtyMaterial);
}
}
void QSGOpenVGSpriteNode::setSourceB(const QPoint &source)
{
if (m_sourceB != source) {
m_sourceB = source;
markDirty(DirtyMaterial);
}
}
void QSGOpenVGSpriteNode::setSpriteSize(const QSize &size)
{
if (m_spriteSize != size) {
m_spriteSize = size;
markDirty(DirtyMaterial);
}
}
void QSGOpenVGSpriteNode::setSheetSize(const QSize &size)
{
if (m_sheetSize != size) {
m_sheetSize = size;
markDirty(DirtyMaterial);
}
}
void QSGOpenVGSpriteNode::setSize(const QSizeF &size)
{
if (m_size != size) {
m_size = size;
markDirty(DirtyGeometry);
}
}
void QSGOpenVGSpriteNode::setFiltering(QSGTexture::Filtering)
{
}
void QSGOpenVGSpriteNode::update()
{
}
void QSGOpenVGSpriteNode::render()
{
if (!m_texture)
return;
VGImage image = static_cast<VGImage>(m_texture->textureId());
QRectF sourceRect(m_sourceA, m_spriteSize);
QRectF targetRect(0, 0, m_size.width(), m_size.height());
VGImage sourceImage = vgChildImage(image, sourceRect.x(), sourceRect.y(), sourceRect.width(), sourceRect.height());
// Set Draw Mode
if (opacity() < 1.0) {
//Transparent
vgSetPaint(opacityPaint(), VG_FILL_PATH);
vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_MULTIPLY);
} else {
vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL);
}
if (sourceRect != targetRect) {
// Scale
float scaleX = targetRect.width() / sourceRect.width();
float scaleY = targetRect.height() / sourceRect.height();
vgScale(scaleX, scaleY);
}
vgDrawImage(sourceImage);
vgDestroyImage(sourceImage);
}
QT_END_NAMESPACE

View File

@ -0,0 +1,78 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSGOPENVGSPRITENODE_H
#define QSGOPENVGSPRITENODE_H
#include <private/qsgadaptationlayer_p.h>
#include "qsgopenvgrenderable.h"
QT_BEGIN_NAMESPACE
class QSGOpenVGTexture;
class QSGOpenVGSpriteNode : public QSGSpriteNode, public QSGOpenVGRenderable
{
public:
QSGOpenVGSpriteNode();
~QSGOpenVGSpriteNode();
void setTexture(QSGTexture *texture) override;
void setTime(float time) override;
void setSourceA(const QPoint &source) override;
void setSourceB(const QPoint &source) override;
void setSpriteSize(const QSize &size) override;
void setSheetSize(const QSize &size) override;
void setSize(const QSizeF &size) override;
void setFiltering(QSGTexture::Filtering filtering) override;
void update() override;
void render() override;
private:
QSGOpenVGTexture *m_texture;
float m_time;
QPoint m_sourceA;
QPoint m_sourceB;
QSize m_spriteSize;
QSize m_sheetSize;
QSizeF m_size;
};
QT_END_NAMESPACE
#endif // QSGOPENVGSPRITENODE_H

View File

@ -0,0 +1,123 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsgopenvgtexture.h"
#include "qsgopenvghelpers.h"
QT_BEGIN_NAMESPACE
QSGOpenVGTexture::QSGOpenVGTexture(const QImage &image, uint flags)
{
Q_UNUSED(flags)
VGImageFormat format = QSGOpenVGHelpers::qImageFormatToVGImageFormat(image.format());
m_image = vgCreateImage(format, image.width(), image.height(), VG_IMAGE_QUALITY_BETTER);
// Do Texture Upload
vgImageSubData(m_image, image.constBits(), image.bytesPerLine(), format, 0, 0, image.width(), image.height());
}
QSGOpenVGTexture::~QSGOpenVGTexture()
{
vgDestroyImage(m_image);
}
int QSGOpenVGTexture::textureId() const
{
return static_cast<int>(m_image);
}
QSize QSGOpenVGTexture::textureSize() const
{
VGint imageWidth = vgGetParameteri(m_image, VG_IMAGE_WIDTH);
VGint imageHeight = vgGetParameteri(m_image, VG_IMAGE_HEIGHT);
return QSize(imageWidth, imageHeight);
}
bool QSGOpenVGTexture::hasAlphaChannel() const
{
VGImageFormat format = static_cast<VGImageFormat>(vgGetParameteri(m_image, VG_IMAGE_FORMAT));
switch (format) {
case VG_sRGBA_8888:
case VG_sRGBA_8888_PRE:
case VG_sRGBA_5551:
case VG_sRGBA_4444:
case VG_lRGBA_8888:
case VG_lRGBA_8888_PRE:
case VG_A_8:
case VG_A_1:
case VG_A_4:
case VG_sARGB_8888:
case VG_sARGB_8888_PRE:
case VG_sARGB_1555:
case VG_sARGB_4444:
case VG_lARGB_8888:
case VG_lARGB_8888_PRE:
case VG_sBGRA_8888:
case VG_sBGRA_8888_PRE:
case VG_sBGRA_5551:
case VG_sBGRA_4444:
case VG_lBGRA_8888:
case VG_lBGRA_8888_PRE:
case VG_sABGR_8888:
case VG_sABGR_8888_PRE:
case VG_sABGR_1555:
case VG_sABGR_4444:
case VG_lABGR_8888:
case VG_lABGR_8888_PRE:
return true;
break;
default:
break;
}
return false;
}
bool QSGOpenVGTexture::hasMipmaps() const
{
return false;
}
void QSGOpenVGTexture::bind()
{
// No need to bind
}
QT_END_NAMESPACE

View File

@ -0,0 +1,67 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSGOPENVGTEXTURE_H
#define QSGOPENVGTEXTURE_H
#include <private/qsgtexture_p.h>
#include <VG/openvg.h>
QT_BEGIN_NAMESPACE
class QSGOpenVGTexture : public QSGTexture
{
public:
QSGOpenVGTexture(const QImage &image, uint flags);
~QSGOpenVGTexture();
int textureId() const override;
QSize textureSize() const override;
bool hasAlphaChannel() const override;
bool hasMipmaps() const override;
void bind() override;
private:
VGImage m_image;;
};
QT_END_NAMESPACE
#endif // QSGOPENVGTEXTURE_H

View File

@ -1,3 +1,5 @@
TEMPLATE = subdirs
QT_FOR_CONFIG += quick
qtConfig(d3d12): SUBDIRS += d3d12
qtConfig(openvg): SUBDIRS += openvg

View File

@ -58,6 +58,8 @@ The supported backends are the following
\li Direct3D 12 - Requested by the string \c{"d3d12"} or the enum value QSGRendererInterface::Direct3D12.
\li OpenVG - Requested by the string \c{"openvg"} or the enum value QSGRendererInterface::OpenVG.
\endlist
When in doubt which backend is in use, enable basic scenegraph information
@ -92,6 +94,14 @@ running on Windows 10, both for Win32 and UWP applications. The details for
this adaptation are available here:
\l{qtquick-visualcanvas-adaptations-d3d12.html}{Direct3D 12 Adaptation}
\section1 OpenVG
The OpenVG adaptation is an alternative renderer for \l {Qt Quick} 2 that will
renderer the contents of the scene graph using OpenVG commands to provide
hardware-acclerated 2D vector and raster graphics. The details for this
adaptation are available here:
\l{qtquick-visualcanvas-scenegraph-openvg.html}{OpenVG Adaptation}
*/
@ -387,3 +397,73 @@ between the frames). By default blocking present is disabled.
\endlist
*/
/*!
\title Qt Quick OpenVG Adaptation
\page qtquick-visualcanvas-adaptations-openvg.html
The OpenVG adaptation is an alternative renderer for \l {Qt Quick} 2 that will
renderer the contents of the scene graph using OpenVG commands to provide
hardware-acclerated 2D vector and raster graphics. Much like the Software
adaptation, some features and optimizations are no longer available. Most
Qt Quick 2 applications will run without modification though any attempts to
use unsupported features will be ignored.
\section2 EGL Requirement
Unlike the defualt OpenGL Renderer, there is no built in support for acquiring
an OpenVG context. This means that the renderer has the responsbility of
requesting and managing the the current context. To do this EGL has to be used
directly in the OpenVG renderer. This means that the OpenVG renderer is only
usable with platform plugins that support creating QWindows with support for
QSurfaceFormat::OpenVG. From this window, the renderer can get an EGLSurface
which can be used with an EGLContext to render OpenVG content.
\section2 Renderer
The OpenVG Renderer works by using the OpenVG API to send commands and data to
a Vector GPU which will render the scenegraph in an accelerated manner, offloading
graphics rendering from the CPU. Many operations like the rendering of rectangles
and fonts glyphs ideal for OpenVG because these can be represented as paths which
are stroked and filled. Rendering scenegraph items that would typically involve
textures are handled in the OpenVG renderer by using VGImage. In addition when
rendering to offscreen surfaces (like when using Layers), the scene subtree is
rendered to a VGImage which can be reused in the scene.
\section2 Render Loop
The OpenVG Renderer mirrors the behavior of the Basic render loop and will execute
all OpenVG commands in a single thread.
See the \l{qtquick-visualcanvas-scenegraph.html}{Scene Graph page} for more
information on render loops
\section2 Shader Effects
ShaderEffect components in QtQuick 2 can not be rendered by the OpenVG adaptation.
While it is possible to user ShaderEffectSource and QML Item Layers (which are both
offscreen surfaces), it is not actually possible to apply shader effects to them
via the ShaderEffect item. This is because OpenVG lacks an API for applying per
vertex and per fragment shader operations. It may be possible however to take
advantage of Image Filter operations in the OpenVG API to get similar effects to
what is provided by ShaderEffects in custom items. To integrate custom OpenVG
rendering, use QSGRenderNode in combination with QSGRendererInterface.
\section2 Qt Graphical Effects Module
\l {Qt Graphical Effects} uses ShaderEffect items to render effects. If you use
graphical effects from this module, then you should not hide the source
item so that the original item can still be rendered.
\section2 Particle Effects
It is not possible to render particle effects with the OpenVG adaptation. Whenever
possible, remove particles completely from the scene. Otherwise they will still
require some processing, even though they are not visible.
\section2 Rendering Text
The text rendering with the OpenVG adaptation is based on rendering the glpyh
paths, and does not use the distance fields technique used by the OpenGL backend.
\section2 Perspective Transforms
The OpenVG API does not allow paths to be transformed with non-affine transforms,
while it is possible with Qt Quick. This means that rendering components using
paths like Rectangles and Text, when applying perspective transforms the OpenVG
backend will first render to a VGImage before applying transformations. This uses
more memory at runtime and is a slower path so avoid doing this if necessary.
*/

View File

@ -77,6 +77,7 @@ QT_BEGIN_NAMESPACE
\value Software The Qt Quick 2D Renderer is in use
\value OpenGL OpenGL ES 2.0 or higher
\value Direct3D12 Direct3D 12
\value OpenVG OpenVG via EGL
*/
/*!

View File

@ -53,7 +53,8 @@ public:
Unknown,
Software,
OpenGL,
Direct3D12
Direct3D12,
OpenVG
};
enum Resource {