tdesktop/Telegram/SourceFiles/statistics/linear_chart_view.cpp

121 lines
3.6 KiB
C++
Raw Normal View History

/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "statistics/linear_chart_view.h"
#include "data/data_statistics.h"
#include "statistics/chart_line_view_context.h"
#include "statistics/statistics_common.h"
#include "ui/effects/animation_value_f.h"
#include "ui/painter.h"
#include "styles/style_boxes.h"
#include "styles/style_statistics.h"
namespace Statistic {
void PaintLinearChartView(
QPainter &p,
const Data::StatisticalChart &chartData,
const Limits &xIndices,
const Limits &xPercentageLimits,
const Limits &heightLimits,
const QRect &rect,
ChartLineViewContext &lineViewContext,
DetailsPaintContext &detailsPaintContext) {
const auto currentMinHeight = rect.y(); //
const auto currentMaxHeight = rect.height() + rect.y(); //
const auto cacheToken = ChartLineViewContext::CacheToken(
xIndices,
xPercentageLimits,
heightLimits,
rect.size());
for (const auto &line : chartData.lines) {
p.setOpacity(lineViewContext.alpha(line.id));
if (!p.opacity()) {
continue;
}
const auto additionalP = (chartData.xPercentage.size() < 2)
? 0.
: (chartData.xPercentage.front() * rect.width());
////
const auto &cache = lineViewContext.cache(line.id);
const auto isSameToken = (cache.lastToken == cacheToken);
if (isSameToken && cache.hq) {
p.drawImage(rect.topLeft(), cache.image);
continue;
}
const auto kRatio = lineViewContext.factor;//0.5;
lineViewContext.setCacheHQ(line.id, isSameToken);
auto image = QImage();
image = QImage(
rect.size() * style::DevicePixelRatio() * (isSameToken ? 1. : kRatio),
QImage::Format_ARGB32_Premultiplied);
image.setDevicePixelRatio(style::DevicePixelRatio());
image.fill(Qt::transparent);
// image.fill(Qt::darkRed);
auto imagePainter = QPainter(&image);
imagePainter.setRenderHint(QPainter::Antialiasing, true);
if (isSameToken) {
// PainterHighQualityEnabler hp(imagePainter);
} else {
imagePainter.scale(kRatio, kRatio);
}
////
auto first = true;
auto chartPath = QPainterPath();
const auto localStart = std::max(0, int(xIndices.min));
const auto localEnd = std::min(
int(chartData.xPercentage.size() - 1),
int(xIndices.max));
for (auto i = localStart; i <= localEnd; i++) {
if (line.y[i] < 0) {
continue;
}
const auto xPoint = rect.width()
* ((chartData.xPercentage[i] - xPercentageLimits.min)
/ (xPercentageLimits.max - xPercentageLimits.min));
const auto yPercentage = (line.y[i] - heightLimits.min)
/ float64(heightLimits.max - heightLimits.min);
const auto yPoint = rect.y() + (1. - yPercentage) * rect.height();
if (i == detailsPaintContext.xIndex) {
detailsPaintContext.dots.push_back({
QPointF(xPoint, yPoint),
line.color,
p.opacity(),
});
}
if (first) {
first = false;
chartPath.moveTo(xPoint, yPoint);
}
chartPath.lineTo(xPoint, yPoint);
}
imagePainter.translate(-rect.topLeft());
imagePainter.setPen(QPen(line.color, st::statisticsChartLineWidth));
imagePainter.setBrush(Qt::NoBrush);
imagePainter.drawPath(chartPath);
if (!isSameToken) {
image = image.scaled(rect.size() * style::DevicePixelRatio(), Qt::IgnoreAspectRatio, Qt::FastTransformation);
}
p.drawImage(rect.topLeft(), image);
lineViewContext.setCacheImage(line.id, std::move(image));
lineViewContext.setCacheLastToken(line.id, cacheToken);
}
p.setPen(st::boxTextFg);
p.setOpacity(1.);
}
} // namespace Statistic