diff options
author | Berthold Stoeger <bstoeger@mail.tuwien.ac.at> | 2021-02-06 12:26:54 +0100 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2021-02-06 10:05:41 -0800 |
commit | 5b6f4685475be7f7b68375fcab465c1626950296 (patch) | |
tree | 5321de5a6baff8d6e41e6919a52bae724c300518 | |
parent | f1203d365a4a890410038943cdd4aaaaf6ab558c (diff) | |
download | subsurface-5b6f4685475be7f7b68375fcab465c1626950296.tar.gz |
statistics: don't place labels at half-integer values
Placing labels at half-integer values gives horrible
rendering artifacts. Therefore, always round to integer
values. The easiest way to do this is right before setting
the position. Introduce a helper function to round QPointF
in such scenarios.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
-rw-r--r-- | Subsurface-mobile.pro | 2 | ||||
-rw-r--r-- | stats/CMakeLists.txt | 2 | ||||
-rw-r--r-- | stats/barseries.cpp | 12 | ||||
-rw-r--r-- | stats/pieseries.cpp | 7 | ||||
-rw-r--r-- | stats/statshelper.cpp | 10 | ||||
-rw-r--r-- | stats/statshelper.h | 6 | ||||
-rw-r--r-- | stats/statsview.cpp | 4 |
7 files changed, 31 insertions, 12 deletions
diff --git a/Subsurface-mobile.pro b/Subsurface-mobile.pro index 8e35c835d..a67ab8e72 100644 --- a/Subsurface-mobile.pro +++ b/Subsurface-mobile.pro @@ -143,6 +143,7 @@ SOURCES += subsurface-mobile-main.cpp \ stats/statsaxis.cpp \ stats/statscolors.cpp \ stats/statsgrid.cpp \ + stats/statshelper.cpp \ stats/statsseries.cpp \ stats/statsstate.cpp \ mobile-widgets/qmlinterface.cpp \ @@ -295,6 +296,7 @@ HEADERS += \ stats/statsaxis.h \ stats/statscolors.h \ stats/statsgrid.h \ + stats/statshelper.h \ stats/statsseries.h \ stats/statsstate.h \ stats/statstranslations.h \ diff --git a/stats/CMakeLists.txt b/stats/CMakeLists.txt index daeb22146..1381797da 100644 --- a/stats/CMakeLists.txt +++ b/stats/CMakeLists.txt @@ -34,6 +34,8 @@ set(SUBSURFACE_STATS_SRCS statscolors.cpp statsgrid.h statsgrid.cpp + statshelper.h + statshelper.cpp statsseries.h statsseries.cpp statsstate.h diff --git a/stats/barseries.cpp b/stats/barseries.cpp index 766843703..252f05af6 100644 --- a/stats/barseries.cpp +++ b/stats/barseries.cpp @@ -118,7 +118,7 @@ void BarSeries::BarLabel::updatePosition(bool horizontal, bool center, const QRe return; } QPointF pos = rect.center(); - pos.rx() -= round(itemSize.width() / 2.0); + pos.rx() -= itemSize.width() / 2.0; // Heuristics: if the label fits nicely into the bar (bar height is at least twice the label height), // then put the label in the middle of the bar. Otherwise, put it at the top of the bar. @@ -130,29 +130,29 @@ void BarSeries::BarLabel::updatePosition(bool horizontal, bool center, const QRe setVisible(false); return; } - pos.ry() -= round(itemSize.height() / 2.0); + pos.ry() -= itemSize.height() / 2.0; } - item->setPos(pos); + item->setPos(roundPos(pos)); // Round to integer to avoid ugly artifacts. } else { if (itemSize.height() > rect.height()) { setVisible(false); return; } QPointF pos = rect.center(); - pos.ry() -= round(itemSize.height() / 2.0); + pos.ry() -= itemSize.height() / 2.0; // Heuristics: if the label fits nicely into the bar (bar width is at least twice the label height), // then put the label in the middle of the bar. Otherwise, put it to the right of the bar. isOutside = !center && rect.width() < 2.0 * itemSize.width(); if (isOutside) { - pos.rx() = round(rect.right() + 2.0); // Leave two pixels(?) space + pos.rx() = rect.right() + 2.0; // Leave two pixels(?) space } else { if (itemSize.width() > rect.width()) { setVisible(false); return; } } - item->setPos(pos); + item->setPos(roundPos(pos)); // Round to integer to avoid ugly artifacts. } setVisible(true); // If label changed from inside to outside, or vice-versa, the color might change. diff --git a/stats/pieseries.cpp b/stats/pieseries.cpp index 8db3bdbe3..d837abe5a 100644 --- a/stats/pieseries.cpp +++ b/stats/pieseries.cpp @@ -44,8 +44,9 @@ void PieSeries::Item::updatePositions(const QPointF ¢er, double radius) // because half-integer values gives horrible aliasing artifacts. if (innerLabel) { QRectF labelRect = innerLabel->getRect(); - innerLabel->setPos(QPointF(round(center.x() + innerLabelPos.x() * radius - labelRect.width() / 2.0), - round(center.y() + innerLabelPos.y() * radius - labelRect.height() / 2.0))); + QPointF pos(center.x() + innerLabelPos.x() * radius - labelRect.width() / 2.0, + center.y() + innerLabelPos.y() * radius - labelRect.height() / 2.0); + innerLabel->setPos(roundPos(pos)); } if (outerLabel) { QRectF labelRect = outerLabel->getRect(); @@ -59,7 +60,7 @@ void PieSeries::Item::updatePositions(const QPointF ¢er, double radius) pos.ry() -= labelRect.height(); } - outerLabel->setPos(QPointF(round(pos.x()), round(pos.y()))); + outerLabel->setPos(roundPos(pos)); } } diff --git a/stats/statshelper.cpp b/stats/statshelper.cpp new file mode 100644 index 000000000..d84ce20cf --- /dev/null +++ b/stats/statshelper.cpp @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include "statshelper.h" + +#include <cmath> + +QPointF roundPos(const QPointF &p) +{ + return QPointF(round(p.x()), round(p.y())); +} diff --git a/stats/statshelper.h b/stats/statshelper.h index 6b4a30ab5..45d58d022 100644 --- a/stats/statshelper.h +++ b/stats/statshelper.h @@ -1,12 +1,16 @@ // SPDX-License-Identifier: GPL-2.0 -// Helper functions to render the stats. Currently contains +// Helper functions to render the stats. Includes // QSGNode template jugglery to overcome API flaws. #ifndef STATSHELPER_H #define STATSHELPER_H #include <memory> +#include <QPointF> #include <QSGNode> +// Round positions to integer values to avoid ugly artifacts +QPointF roundPos(const QPointF &p); + // A stupid pointer class that initializes to null and can be copy // assigned. This is for historical reasons: unique_ptrs to ChartItems // were replaced by plain pointers. Instead of nulling the plain pointers diff --git a/stats/statsview.cpp b/stats/statsview.cpp index 5514aa35d..eec7b4ba5 100644 --- a/stats/statsview.cpp +++ b/stats/statsview.cpp @@ -397,8 +397,8 @@ void StatsView::updateTitlePos() { if (!title) return; - title->setPos(QPointF(round(sceneBorder + (boundingRect().width() - title->getRect().width()) / 2.0), - round(sceneBorder))); + QPointF pos(sceneBorder + (boundingRect().width() - title->getRect().width()) / 2.0, sceneBorder); + title->setPos(roundPos(pos)); } template <typename T, class... Args> |