Revision control
Copy as Markdown
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsgopenvgpublicnodes.h"
#include "qsgopenvghelpers.h"
#include <VG/openvg.h>
#include <QtGui/QPixmap>
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);
}
QRectF QSGOpenVGRectangleNode::rect() const
{
return m_rect;
}
void QSGOpenVGRectangleNode::setColor(const QColor &color)
{
m_color = color;
m_paintDirty = true;
markDirty(DirtyMaterial);
}
QColor QSGOpenVGRectangleNode::color() const
{
return m_color;
}
void QSGOpenVGRectangleNode::setTransform(const QOpenVGMatrix &transform)
{
// if there transform matrix is not affine, regenerate the path
if (transform.isAffine())
m_pathDirty = true;
markDirty(DirtyGeometry);
QSGOpenVGRenderable::setTransform(transform);
}
void QSGOpenVGRectangleNode::render()
{
// Set Transform
if (transform().isAffine()) {
// Use current transform matrix
vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
vgLoadMatrix(transform().constData());
} else {
// map the path's to handle the perspective matrix
vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
vgLoadIdentity();
}
if (m_pathDirty) {
vgClearPath(m_rectPath, VG_PATH_CAPABILITY_APPEND_TO);
if (transform().isAffine()) {
// 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
QList<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());
} else {
// Pre-transform path
static const VGubyte rectCommands[] = {
VG_MOVE_TO_ABS,
VG_LINE_TO_ABS,
VG_LINE_TO_ABS,
VG_LINE_TO_ABS,
VG_CLOSE_PATH
};
QList<VGfloat> coordinates(8);
const QPointF topLeft = transform().map(m_rect.topLeft());
const QPointF topRight = transform().map(m_rect.topRight());
const QPointF bottomLeft = transform().map(m_rect.bottomLeft());
const QPointF bottomRight = transform().map(m_rect.bottomRight());
coordinates[0] = bottomLeft.x();
coordinates[1] = bottomLeft.y();
coordinates[2] = bottomRight.x();
coordinates[3] = bottomRight.y();
coordinates[4] = topRight.x();
coordinates[5] = topRight.y();
coordinates[6] = topLeft.x();
coordinates[7] = topLeft.y();
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() : m_texture(nullptr), m_owns(false)
{
// Set Dummy material and geometry to avoid asserts
setMaterial((QSGMaterial*)1);
setGeometry((QSGGeometry*)1);
}
QSGOpenVGImageNode::~QSGOpenVGImageNode()
{
if (m_owns)
delete m_texture;
}
void QSGOpenVGImageNode::setRect(const QRectF &rect)
{
m_rect = rect;
markDirty(DirtyMaterial);
}
QRectF QSGOpenVGImageNode::rect() const
{
return m_rect;
}
void QSGOpenVGImageNode::setSourceRect(const QRectF &r)
{
m_sourceRect = r;
}
QRectF QSGOpenVGImageNode::sourceRect() const
{
return m_sourceRect;
}
void QSGOpenVGImageNode::setTexture(QSGTexture *texture)
{
if (m_owns)
delete m_texture;
m_texture = texture;
markDirty(DirtyMaterial);
}
QSGTexture *QSGOpenVGImageNode::texture() const
{
return m_texture;
}
void QSGOpenVGImageNode::setFiltering(QSGTexture::Filtering filtering)
{
m_filtering = filtering;
markDirty(DirtyMaterial);
}
QSGTexture::Filtering QSGOpenVGImageNode::filtering() const
{
return m_filtering;
}
void QSGOpenVGImageNode::setMipmapFiltering(QSGTexture::Filtering)
{
}
QSGTexture::Filtering QSGOpenVGImageNode::mipmapFiltering() const
{
return QSGTexture::None;
}
void QSGOpenVGImageNode::setAnisotropyLevel(QSGTexture::AnisotropyLevel)
{
}
QSGTexture::AnisotropyLevel QSGOpenVGImageNode::anisotropyLevel() const
{
return QSGTexture::AnisotropyNone;
}
void QSGOpenVGImageNode::setTextureCoordinatesTransform(QSGImageNode::TextureCoordinatesTransformMode transformNode)
{
if (m_transformMode == transformNode)
return;
m_transformMode = transformNode;
markDirty(DirtyGeometry);
}
QSGImageNode::TextureCoordinatesTransformMode QSGOpenVGImageNode::textureCoordinatesTransform() const
{
return m_transformMode;
}
void QSGOpenVGImageNode::setOwnsTexture(bool owns)
{
m_owns = owns;
}
bool QSGOpenVGImageNode::ownsTexture() const
{
return m_owns;
}
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);
}
// Set Transform
vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
vgLoadMatrix(transform().constData());
VGImage image = static_cast<VGImage>(m_texture->comparisonKey());
//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() : m_texture(nullptr)
{
// Set Dummy material and geometry to avoid asserts
setMaterial((QSGMaterial*)1);
setGeometry((QSGGeometry*)1);
}
QSGOpenVGNinePatchNode::~QSGOpenVGNinePatchNode()
{
delete m_texture;
}
void QSGOpenVGNinePatchNode::setTexture(QSGTexture *texture)
{
delete m_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);
}
// Set Transform
vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
vgLoadMatrix(transform().constData());
VGImage image = static_cast<VGImage>(m_texture->comparisonKey());
//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