diff options
author | Berthold Stoeger <bstoeger@mail.tuwien.ac.at> | 2021-01-15 22:48:32 +0100 |
---|---|---|
committer | bstoeger <32835590+bstoeger@users.noreply.github.com> | 2021-01-20 08:47:18 +0100 |
commit | b42e19e36b4d80716059011581851c8600338cbb (patch) | |
tree | e752618c95a6ab4dcb980209800d3c3bbf292a0e /stats/chartitem.cpp | |
parent | 20088576604a3159cc9891bcfea888c15b096a96 (diff) | |
download | subsurface-b42e19e36b4d80716059011581851c8600338cbb.tar.gz |
statistics: convert bar series to QSGNodes
To this end, two new ChartItems were added: A "bar" (a rectangle
with a border) and a "text" (multiple lines of text).
It turns out that the text on the bars now looks atrocious.
The reason appears to be that the antialiasing of the font-rendering
does not blend into the alpha channel, but into a supposed
background color? This will have to be investigated.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Diffstat (limited to 'stats/chartitem.cpp')
-rw-r--r-- | stats/chartitem.cpp | 119 |
1 files changed, 117 insertions, 2 deletions
diff --git a/stats/chartitem.cpp b/stats/chartitem.cpp index aeb395d41..bb01c6e2c 100644 --- a/stats/chartitem.cpp +++ b/stats/chartitem.cpp @@ -6,6 +6,7 @@ #include <QQuickWindow> #include <QSGFlatColorMaterial> #include <QSGImageNode> +#include <QSGRectangleNode> #include <QSGTexture> static int round_up(double f) @@ -116,6 +117,40 @@ void ChartRectItem::resize(QSizeF size) painter->drawRoundedRect(rect, radius, radius, Qt::AbsoluteSize); } +ChartTextItem::ChartTextItem(StatsView &v, ChartZValue z, const QFont &f, const std::vector<QString> &text, bool center) : + ChartPixmapItem(v, z), f(f), center(center) +{ + QFontMetrics fm(f); + double totalWidth = 1.0; + fontHeight = static_cast<double>(fm.height()); + double totalHeight = std::max(1.0, static_cast<double>(text.size()) * fontHeight); + + items.reserve(text.size()); + for (const QString &s: text) { + double w = fm.size(Qt::TextSingleLine, s).width(); + items.push_back({ s, w }); + if (w > totalWidth) + totalWidth = w; + } + resize(QSizeF(totalWidth, totalHeight)); +} + +void ChartTextItem::setColor(const QColor &c) +{ + img->fill(Qt::transparent); + double y = 0.0; + painter->setPen(QPen(c)); + painter->setFont(f); + double totalWidth = getRect().width(); + for (const auto &[s, w]: items) { + double x = center ? round((totalWidth - w) / 2.0) : 0.0; + QRectF rect(x, y, w, fontHeight); + painter->drawText(rect, s); + y += fontHeight; + } + setTextureDirty(); +} + ChartLineItem::ChartLineItem(StatsView &v, ChartZValue z, QColor color, double width) : ChartItem(v, z), color(color), width(width), positionDirty(false), materialDirty(false) { @@ -125,6 +160,12 @@ ChartLineItem::~ChartLineItem() { } +// Helper function to set points +void setPoint(QSGGeometry::Point2D &v, const QPointF &p) +{ + v.set(static_cast<float>(p.x()), static_cast<float>(p.y())); +} + void ChartLineItem::render() { if (!node) { @@ -142,8 +183,8 @@ void ChartLineItem::render() // Attention: width is a geometry property and therefore handled by position dirty! geometry->setLineWidth(static_cast<float>(width)); auto vertices = geometry->vertexDataAsPoint2D(); - vertices[0].set(static_cast<float>(from.x()), static_cast<float>(from.y())); - vertices[1].set(static_cast<float>(to.x()), static_cast<float>(to.y())); + setPoint(vertices[0], from); + setPoint(vertices[1], to); node->markDirty(QSGNode::DirtyGeometry); } @@ -162,3 +203,77 @@ void ChartLineItem::setLine(QPointF fromIn, QPointF toIn) positionDirty = true; view.registerDirtyChartItem(*this); } + +ChartBarItem::ChartBarItem(StatsView &v, ChartZValue z, double borderWidth, bool horizontal) : ChartItem(v, z), + borderWidth(borderWidth), horizontal(horizontal), + positionDirty(false), colorDirty(false) +{ +} + +ChartBarItem::~ChartBarItem() +{ +} + +void ChartBarItem::render() +{ + if (!node) { + node.reset(view.w()->createRectangleNode()); + + borderGeometry.reset(new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 4)); + borderGeometry->setDrawingMode(QSGGeometry::DrawLineLoop); + borderGeometry->setLineWidth(static_cast<float>(borderWidth)); + borderMaterial.reset(new QSGFlatColorMaterial); + borderNode.reset(new QSGGeometryNode); + borderNode->setGeometry(borderGeometry.get()); + borderNode->setMaterial(borderMaterial.get()); + + node->appendChildNode(borderNode.get()); + view.addQSGNode(node.get(), zValue); + positionDirty = colorDirty = true; + } + + if (colorDirty) { + node->setColor(color); + borderMaterial->setColor(borderColor); + borderNode->markDirty(QSGNode::DirtyMaterial); + } + + if (positionDirty) { + node->setRect(rect); + auto vertices = borderGeometry->vertexDataAsPoint2D(); + if (horizontal) { + setPoint(vertices[0], rect.topLeft()); + setPoint(vertices[1], rect.topRight()); + setPoint(vertices[2], rect.bottomRight()); + setPoint(vertices[3], rect.bottomLeft()); + } else { + setPoint(vertices[0], rect.bottomLeft()); + setPoint(vertices[1], rect.topLeft()); + setPoint(vertices[2], rect.topRight()); + setPoint(vertices[3], rect.bottomRight()); + } + borderNode->markDirty(QSGNode::DirtyGeometry); + } + + positionDirty = colorDirty = false; +} + +void ChartBarItem::setColor(QColor colorIn, QColor borderColorIn) +{ + color = colorIn; + borderColor = borderColorIn; + colorDirty = true; + view.registerDirtyChartItem(*this); +} + +void ChartBarItem::setRect(const QRectF &rectIn) +{ + rect = rectIn; + positionDirty = true; + view.registerDirtyChartItem(*this); +} + +QRectF ChartBarItem::getRect() const +{ + return rect; +} |