From ba0d8e93d8525bb459e9b6cb384f2fe0701d5a02 Mon Sep 17 00:00:00 2001 From: Andy Nichols Date: Mon, 1 Sep 2014 16:49:58 +0200 Subject: Reformat project to be a Qt Module Change-Id: I2fe8df530a687247a9cd7ea12c1d8de79fef506e Reviewed-by: Simon Hausmann --- .../scenegraph/softwarecontext/rectanglenode.cpp | 219 +++++++++++++++++++++ 1 file changed, 219 insertions(+) create mode 100644 src/plugins/scenegraph/softwarecontext/rectanglenode.cpp (limited to 'src/plugins/scenegraph/softwarecontext/rectanglenode.cpp') diff --git a/src/plugins/scenegraph/softwarecontext/rectanglenode.cpp b/src/plugins/scenegraph/softwarecontext/rectanglenode.cpp new file mode 100644 index 0000000000..054ffd3ecf --- /dev/null +++ b/src/plugins/scenegraph/softwarecontext/rectanglenode.cpp @@ -0,0 +1,219 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt SceneGraph Raster Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "rectanglenode.h" +#include + +#include + + +RectangleNode::RectangleNode() + : m_penWidth(0) + , m_radius(0) + , m_cornerPixmapIsDirty(true) +{ + setMaterial((QSGMaterial*)1); + setGeometry((QSGGeometry*)1); +} + +void RectangleNode::setRect(const QRectF &rect) +{ + if (m_rect != rect) { + m_rect = rect; + } +} + +void RectangleNode::setColor(const QColor &color) +{ + if (m_color != color) { + m_color = color; + m_cornerPixmapIsDirty = true; + } +} + +void RectangleNode::setPenColor(const QColor &color) +{ + if (m_penColor != color) { + m_penColor = color; + m_cornerPixmapIsDirty = true; + } +} + +void RectangleNode::setPenWidth(qreal width) +{ + if (m_penWidth != width) { + m_penWidth = width; + m_cornerPixmapIsDirty = true; + } +} + +void RectangleNode::setGradientStops(const QGradientStops &stops) +{ + m_stops = stops; + m_cornerPixmapIsDirty = true; +} + +void RectangleNode::setRadius(qreal radius) +{ + if (m_radius != radius) { + m_radius = radius; + m_cornerPixmapIsDirty = true; + } +} + +void RectangleNode::setAligned(bool /*aligned*/) +{ +} + +void RectangleNode::update() +{ + if (!m_penWidth || m_penColor == Qt::transparent) { + m_pen = Qt::NoPen; + } else { + m_pen = QPen(m_penColor); + m_pen.setWidthF(m_penWidth); + } + + if (!m_stops.isEmpty()) { + QLinearGradient gradient(QPoint(0,0), QPoint(0,1)); + gradient.setStops(m_stops); + gradient.setCoordinateMode(QGradient::ObjectBoundingMode); + m_brush = QBrush(gradient); + } else { + m_brush = QBrush(m_color); + } + + if (m_cornerPixmapIsDirty) { + //Generate new corner Pixmap + int radius = qRound(qMin(qMin(m_rect.width(), m_rect.height()) * 0.5f, m_radius)); + + m_cornerPixmap = QPixmap(radius * 2, radius * 2); + m_cornerPixmap.fill(Qt::transparent); + + if (radius > 0) { + QPainter cornerPainter(&m_cornerPixmap); + cornerPainter.setRenderHint(QPainter::Antialiasing); + cornerPainter.setCompositionMode(QPainter::CompositionMode_Source); + + //Paint outer cicle + if (m_penWidth > 0) { + cornerPainter.setPen(Qt::NoPen); + cornerPainter.setBrush(m_penColor); + cornerPainter.drawRoundedRect(QRectF(0, 0, radius * 2, radius *2), radius, radius); + } + + //Paint inner circle + if (radius > m_penWidth) { + cornerPainter.setPen(Qt::NoPen); + if (m_stops.isEmpty()) + cornerPainter.setBrush(m_brush); + else + cornerPainter.setBrush(Qt::transparent); + + QMarginsF adjustmentMargins(m_penWidth, m_penWidth, m_penWidth, m_penWidth); + QRectF cornerCircleRect = QRectF(0, 0, radius * 2, radius * 2).marginsRemoved(adjustmentMargins); + cornerPainter.drawRoundedRect(cornerCircleRect, radius, radius); + } + cornerPainter.end(); + } + m_cornerPixmapIsDirty = false; + } +} + +void RectangleNode::paint(QPainter *painter) +{ + //Radius should never exceeds half of the width or half of the height + int radius = qRound(qMin(qMin(m_rect.width(), m_rect.height()) * 0.5, m_radius)); + + QPainter::RenderHints previousRenderHints = painter->renderHints(); + painter->setRenderHint(QPainter::Antialiasing, false); + + if (m_penWidth > 0) { + //Borders can not be more than half the height/width of a rect + double borderWidth = qMin(m_penWidth, m_rect.width() * 0.5); + double borderHeight = qMin(m_penWidth, m_rect.height() * 0.5); + + //Fill 4 border Rects + QRectF borderTop(QPointF(m_rect.x() + radius, m_rect.y()), + QPointF(m_rect.x() + m_rect.width() - radius, m_rect.y() + borderHeight)); + painter->fillRect(borderTop, m_penColor); + QRectF borderBottom(QPointF(m_rect.x() + radius, m_rect.y() + m_rect.height() - borderHeight), + QPointF(m_rect.x() + m_rect.width() - radius, m_rect.y() + m_rect.height())); + painter->fillRect(borderBottom, m_penColor); + QRectF borderLeft(QPointF(m_rect.x(), m_rect.y() + radius), + QPointF(m_rect.x() + borderWidth, m_rect.y() + m_rect.height() - radius)); + painter->fillRect(borderLeft, m_penColor); + QRectF borderRight(QPointF(m_rect.x() + m_rect.width() - borderWidth, m_rect.y() + radius), + QPointF(m_rect.x() + m_rect.width(), m_rect.y() + m_rect.height() - radius)); + painter->fillRect(borderRight, m_penColor); + } + + if (radius > 0) { + //blit 4 corners to border + QRectF topLeftCorner(QPointF(m_rect.x(), m_rect.y()), + QPointF(m_rect.x() + radius, m_rect.y() + radius)); + painter->drawPixmap(topLeftCorner, m_cornerPixmap, QRectF(0, 0, radius, radius)); + QRectF topRightCorner(QPointF(m_rect.x() + m_rect.width() - radius, m_rect.y()), + QPointF(m_rect.x() + m_rect.width(), m_rect.y() + radius)); + painter->drawPixmap(topRightCorner, m_cornerPixmap, QRectF(radius, 0, radius, radius)); + QRectF bottomLeftCorner(QPointF(m_rect.x(), m_rect.y() + m_rect.height() - radius), + QPointF(m_rect.x() + radius, m_rect.y() + m_rect.height())); + painter->drawPixmap(bottomLeftCorner, m_cornerPixmap, QRectF(0, radius, radius, radius)); + QRectF bottomRightCorner(QPointF(m_rect.x() + m_rect.width() - radius, m_rect.y() + m_rect.height() - radius), + QPointF(m_rect.x() + m_rect.width(), m_rect.y() + m_rect.height())); + painter->drawPixmap(bottomRightCorner, m_cornerPixmap, QRectF(radius, radius, radius, radius)); + + } + + QRectF brushRect = m_rect.marginsRemoved(QMarginsF(m_penWidth, m_penWidth, m_penWidth, m_penWidth)); + if (brushRect.width() < 0) + brushRect.setWidth(0); + if (brushRect.height() < 0) + brushRect.setHeight(0); + double innerRectRadius = qMax(0.0, radius - m_penWidth); + + //If not completely transparent or has a gradient + if (m_color.alpha() > 0 || !m_stops.empty()) { + if (innerRectRadius > 0) { + //Rounded Rect + if (m_stops.empty()) { + //Rounded Rects without gradient need 3 blits + QRectF centerRect(QPointF(brushRect.x() + innerRectRadius, brushRect.y()), + QPointF(brushRect.x() + brushRect.width() - innerRectRadius, brushRect.y() + brushRect.height())); + painter->fillRect(centerRect, m_color); + QRectF leftRect(QPointF(brushRect.x(), brushRect.y() + innerRectRadius), + QPointF(brushRect.x() + innerRectRadius, brushRect.y() + brushRect.height() - innerRectRadius)); + painter->fillRect(leftRect, m_color); + QRectF rightRect(QPointF(brushRect.x() + brushRect.width() - innerRectRadius, brushRect.y() + innerRectRadius), + QPointF(brushRect.x() + brushRect.width(), brushRect.y() + brushRect.height() - innerRectRadius)); + painter->fillRect(rightRect, m_color); + } else { + //Rounded Rect with gradient (slow) + painter->setPen(Qt::NoPen); + painter->setBrush(m_brush); + painter->drawRoundedRect(brushRect, innerRectRadius, innerRectRadius); + } + } else { + //non-rounded rects only need 1 blit + painter->fillRect(brushRect, m_brush); + } + } + + painter->setRenderHints(previousRenderHints); +} -- cgit v1.2.3