aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndy Nichols <andy.nichols@digia.com>2014-09-08 15:43:28 +0200
committerAndy Nichols <andy.nichols@digia.com>2014-09-09 14:35:18 +0300
commit11640a314bfe42ef767f668d5bae687f7419942e (patch)
tree4c88e6229cd2caa93b6d70010951f00d4b788cbc /src
parent363830db7b14e53ce3c976c142da8edf1b648c69 (diff)
Improve rendering quality of Rectangles
The existing implementation has both inaccurate drawing of borders as well as many alignment issues. Much of these alignment issues are due to our use of floating point sizes and the integer based nature of blitter hardware. So now for the Rectangle node we force alignment via the use of whole numbers. This should be a better compromise of speed vs accuracy than previously. Change-Id: I9d8e9d1b3347a99bf0c2ae65ec66c935d8017817 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/scenegraph/softwarecontext/rectanglenode.cpp95
-rw-r--r--src/plugins/scenegraph/softwarecontext/rectanglenode.h2
2 files changed, 69 insertions, 28 deletions
diff --git a/src/plugins/scenegraph/softwarecontext/rectanglenode.cpp b/src/plugins/scenegraph/softwarecontext/rectanglenode.cpp
index 39710bb736..c0eebb3bcd 100644
--- a/src/plugins/scenegraph/softwarecontext/rectanglenode.cpp
+++ b/src/plugins/scenegraph/softwarecontext/rectanglenode.cpp
@@ -34,8 +34,9 @@ RectangleNode::RectangleNode()
void RectangleNode::setRect(const QRectF &rect)
{
- if (m_rect != rect) {
- m_rect = rect;
+ QRect alignedRect = rect.toAlignedRect();
+ if (m_rect != alignedRect) {
+ m_rect = alignedRect;
}
}
@@ -188,7 +189,7 @@ void RectangleNode::update()
if (m_cornerPixmapIsDirty) {
//Generate new corner Pixmap
- int radius = qRound(qMin(qMin(m_rect.width(), m_rect.height()) * 0.5f, m_radius));
+ int radius = qFloor(qMin(qMin(m_rect.width(), m_rect.height()) * 0.5, m_radius));
m_cornerPixmap = QPixmap(radius * 2, radius * 2);
m_cornerPixmap.fill(Qt::transparent);
@@ -226,49 +227,89 @@ void RectangleNode::update()
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));
+ int radius = qFloor(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) {
+ //Fill border Rects
+
//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);
+
+
+ if (borderWidth > radius) {
+ //4 Rects
+ QRectF borderTopOutside(QPointF(m_rect.x() + radius, m_rect.y()),
+ QPointF(m_rect.x() + m_rect.width() - radius, m_rect.y() + radius));
+ QRectF borderTopInside(QPointF(m_rect.x() + borderWidth, m_rect.y() + radius),
+ QPointF(m_rect.x() + m_rect.width() - borderWidth, m_rect.y() + borderHeight));
+ QRectF borderBottomOutside(QPointF(m_rect.x() + radius, m_rect.y() + m_rect.height() - radius),
+ QPointF(m_rect.x() + m_rect.width() - radius, m_rect.y() + m_rect.height()));
+ QRectF borderBottomInside(QPointF(m_rect.x() + borderWidth, m_rect.y() + m_rect.height() - borderHeight),
+ QPointF(m_rect.x() + m_rect.width() - borderWidth, m_rect.y() + m_rect.height() - radius));
+
+ if (borderTopOutside.isValid())
+ painter->fillRect(borderTopOutside, m_penColor);
+ if (borderTopInside.isValid())
+ painter->fillRect(borderTopInside, m_penColor);
+ if (borderBottomOutside.isValid())
+ painter->fillRect(borderBottomOutside, m_penColor);
+ if (borderBottomInside.isValid())
+ painter->fillRect(borderBottomInside, m_penColor);
+
+ } else {
+ //2 Rects
+ QRectF borderTop(QPointF(m_rect.x() + radius, m_rect.y()),
+ QPointF(m_rect.x() + m_rect.width() - radius, m_rect.y() + borderHeight));
+ 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()));
+ if (borderTop.isValid())
+ painter->fillRect(borderTop, m_penColor);
+ if (borderBottom.isValid())
+ 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 (borderLeft.isValid())
+ painter->fillRect(borderLeft, m_penColor);
+ if (borderRight.isValid())
+ 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));
+
+ if (radius * 2 >= m_rect.width() && radius * 2 >= m_rect.height()) {
+ //Blit whole pixmap for circles
+ painter->drawPixmap(m_rect, m_cornerPixmap, m_cornerPixmap.rect());
+ } else {
+
+ //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));
+ int penWidth = qRound(m_penWidth);
+ QRectF brushRect = m_rect.marginsRemoved(QMargins(penWidth, penWidth, penWidth, penWidth));
if (brushRect.width() < 0)
brushRect.setWidth(0);
if (brushRect.height() < 0)
diff --git a/src/plugins/scenegraph/softwarecontext/rectanglenode.h b/src/plugins/scenegraph/softwarecontext/rectanglenode.h
index 74c0971c82..f4c7cb3dcf 100644
--- a/src/plugins/scenegraph/softwarecontext/rectanglenode.h
+++ b/src/plugins/scenegraph/softwarecontext/rectanglenode.h
@@ -45,7 +45,7 @@ public:
void paint(QPainter *);
private:
- QRectF m_rect;
+ QRect m_rect;
QColor m_color;
QColor m_penColor;
double m_penWidth;