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 /src/canvas | |
| parent | 4969d36d1bad2a856c0d9db03d739310f9852797 (diff) | |
Implemented rounded clip.
Diffstat (limited to 'src/canvas')
| -rw-r--r-- | src/canvas/qxclipnode.cpp | 87 | ||||
| -rw-r--r-- | src/canvas/qxclipnode_p.h | 6 |
2 files changed, 48 insertions, 45 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; |
