diff options
author | Yoann Lopes <yoann.lopes@nokia.com> | 2010-11-18 15:19:13 +0100 |
---|---|---|
committer | Yoann Lopes <yoann.lopes@nokia.com> | 2010-11-18 15:20:03 +0100 |
commit | fcd388b3436bea4d5289832699329294c744a0ac (patch) | |
tree | 9d1862de228ecb64bd8d28ddfc2cbf9739f73641 | |
parent | 4969d36d1bad2a856c0d9db03d739310f9852797 (diff) |
Implemented rounded clip.
-rw-r--r-- | src/canvas/qxclipnode.cpp | 87 | ||||
-rw-r--r-- | src/canvas/qxclipnode_p.h | 6 | ||||
-rw-r--r-- | src/graphicsitems/qxrectangle.cpp | 6 | ||||
-rw-r--r-- | tests/rrClip.qml | 15 |
4 files changed, 63 insertions, 51 deletions
diff --git a/src/canvas/qxclipnode.cpp b/src/canvas/qxclipnode.cpp index a954b62..aded473 100644 --- a/src/canvas/qxclipnode.cpp +++ b/src/canvas/qxclipnode.cpp @@ -44,83 +44,80 @@ #include "qxclipnode_p.h" #include "utilities.h" +#include <QtGui/QVector2D> #include <QtCore/qmath.h> QxClipNode::QxClipNode(const QRectF &rect) : m_rect(rect), m_radius(0) { - updateGeometry(); + updateGeometryDescription(Utilities::getRectGeometryDescription(), GL_UNSIGNED_SHORT); + Utilities::setupRectGeometry(geometry(), m_rect); setFlag(ClipIsRectangular, true); } void QxClipNode::setRect(const QRectF &rect) { m_rect = rect; - updateGeometry(); + setUpdateFlag(UpdateGeometry); } void QxClipNode::setRadius(qreal radius) { m_radius = radius; - updateGeometry(); + setUpdateFlag(UpdateGeometry); setFlag(ClipIsRectangular, radius == 0); } +void QxClipNode::update(uint updateFlags) +{ + if (updateFlags & UpdateGeometry) + updateGeometry(); +} + void QxClipNode::updateGeometry() { if (qFuzzyIsNull(m_radius)) { updateGeometryDescription(Utilities::getRectGeometryDescription(), GL_UNSIGNED_SHORT); Utilities::setupRectGeometry(geometry(), m_rect); } else { - // ### Fix. - updateGeometryDescription(Utilities::getRectGeometryDescription(), GL_UNSIGNED_SHORT); - Utilities::setupRectGeometry(geometry(), m_rect); - /* - //XXX copy of what is in QxRectangle (we should reuse the geometry generated there if possible) + struct Vertex + { + QVector2D position; + }; + + Geometry *g = geometry(); + int vertexCount = 0; + QRectF rect = m_rect; - qreal radius = m_radius; - - QArray<QVector2D> vertices; - QGLVertexBuffer v; - - qreal zero = 0. * M_PI/180.; - qreal ninety = 90. * M_PI/180.; - qreal oneeighty = 180. * M_PI/180.; - qreal twoseventy = 270. * M_PI/180.; - qreal nninety = -90. * M_PI/180.; - qreal step = -1.5708/radius; - - //upper left - QPointF cp(rect.x() + radius, rect.y() + radius); - for (qreal angle = twoseventy; angle >= oneeighty; angle += step) { - vertices.append(QVector2D(cp.x() + qFastSin(angle) * radius, cp.y() + qFastCos(angle) * radius)); - } + rect.adjust(m_radius, m_radius, -m_radius, -m_radius); - //upper right - cp = QPointF(rect.x() + rect.width() - radius, rect.y() + radius); - for (qreal angle = oneeighty; angle >= ninety; angle += step) { - vertices.append(QVector2D(cp.x() + qFastSin(angle) * radius, cp.y() + qFastCos(angle) * radius)); - } + int segments = qMin(15, qCeil(m_radius)); // Number of segments per corner. - //lower right - cp = QPointF(rect.x() + rect.width() - radius, rect.y() + rect.height() - radius); - for (qreal angle = ninety; angle >= zero; angle += step) { - vertices.append(QVector2D(cp.x() + qFastSin(angle) * radius, cp.y() + qFastCos(angle) * radius)); - } + // Overestimate the number of vertices and indices, reduce afterwards when the actual numbers are known. + g->setVertexCount((segments + 1) * 4); + g->setIndexCount(0); + + Vertex *vertices = (Vertex *)g->vertexData(); + + for (int part = 0; part < 2; ++part) { + for (int i = 0; i <= segments; ++i) { + //### Should change to calculate sin/cos only once. + qreal angle = qreal(0.5 * M_PI) * (part + i / qreal(segments)); + qreal s = qFastSin(angle); + qreal c = qFastCos(angle); + qreal y = (part ? rect.bottom() : rect.top()) - m_radius * c; // current inner y-coordinate. + qreal lx = rect.left() - m_radius * s; // current inner left x-coordinate. + qreal rx = rect.right() + m_radius * s; // current inner right x-coordinate. - //lower left - cp = QPointF(rect.x() + radius, rect.y() + rect.height() - radius); - for (qreal angle = zero; angle >= nninety; angle += step) { - vertices.append(QVector2D(cp.x() + qFastSin(angle) * radius, cp.y() + qFastCos(angle) * radius)); + vertices[vertexCount++].position = QVector2D(rx, y); + vertices[vertexCount++].position = QVector2D(lx, y); + } } - vertices.append(QVector2D(rect.x(), rect.y() + radius)); - v.addAttribute(QGL::Position, vertices); + g->setDrawingMode(QGL::TriangleStrip); + g->setVertexCount(vertexCount); - setDrawingMode(QGL::TriangleFan); - setVertexBuffer(v); - setIndexBuffer(Utilities::createIndexBuffer(vertices.count())); - */ + markDirty(DirtyGeometry); } setBoundingRect(m_rect); } diff --git a/src/canvas/qxclipnode_p.h b/src/canvas/qxclipnode_p.h index 76d7bbf..0754897 100644 --- a/src/canvas/qxclipnode_p.h +++ b/src/canvas/qxclipnode_p.h @@ -49,6 +49,10 @@ class QxClipNode : public ClipNode { public: + enum UpdateFlag { + UpdateGeometry = 1 + }; + QxClipNode(const QRectF &); void setRect(const QRectF &); @@ -57,6 +61,8 @@ public: void setRadius(qreal radius); qreal radius() const { return m_radius; } + virtual void update(uint updateFlags); + private: void updateGeometry(); QRectF m_rect; diff --git a/src/graphicsitems/qxrectangle.cpp b/src/graphicsitems/qxrectangle.cpp index ff3b174..6d240c5 100644 --- a/src/graphicsitems/qxrectangle.cpp +++ b/src/graphicsitems/qxrectangle.cpp @@ -41,6 +41,7 @@ #include "qxrectangle_p.h" #include "qxrectangle_p_p.h" +#include "qxclipnode_p.h" #include "geometry.h" #include "vertexcolormaterial.h" @@ -177,10 +178,9 @@ void QxRectangle::setRadius(qreal radius) if (d->node) d->node->setRadius(radius); -#ifdef ROUNDEDRECT_CLIP if (d->clipNode) d->clipNode->setRadius(d->radius); -#endif + emit radiusChanged(); } @@ -247,6 +247,8 @@ void QxRectangle::componentComplete() d->updateGradient(); d->updateBorderWidth(); d->updateBorderColor(); + if (d->clipNode) + d->clipNode->setRadius(d->radius); setPaintNode(d->node); // Must call setRect() before calling setPaintNode() for clipping to be correct. } diff --git a/tests/rrClip.qml b/tests/rrClip.qml index 7105ba0..ece7605 100644 --- a/tests/rrClip.qml +++ b/tests/rrClip.qml @@ -46,14 +46,21 @@ Rectangle { height: 480 Rectangle { - width: 400; height: 400 + width: 400; height: 400; anchors.centerIn: parent - radius: 100 + radius: 200 + color: "transparent" clip: true Rectangle { - anchors.fill: parent - color: "green" + anchors.centerIn: parent + width: 400; height: 400 + gradient: Gradient { + GradientStop { position: 0.0; color: "white" } + GradientStop { position: 1.0; color: "green" } + } + + NumberAnimation on rotation { to: 360; duration: 3000; loops: -1 } } } } |