mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-30 22:20:21 +00:00
profile: remove need for MainWindow when rendering the profile
Very annoyingly, to render the profile for printing / export, the profile still had to be show()n, thus requiring a parent window. Analysis of qmlprofile.c showed that this was due to the transformation matrix not being properly set up on non-show()n scenes. Instead, we can simply render via the QGraphicsScene (circumventing the QGraphicsView). The code was factored out into the ProfileWidget2::draw() function. This will hopefully make it easier to change the size-code of the profile. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
13d4f595cb
commit
b39e88b8c6
5 changed files with 51 additions and 48 deletions
|
@ -34,32 +34,27 @@ bool ExportCallback::canceled() const
|
|||
|
||||
#if !defined(SUBSURFACE_MOBILE)
|
||||
|
||||
#include "desktop-widgets/mainwindow.h" // Currently needed for profile printing. TODO: remove.
|
||||
// Let's say that 800x600 is a "reasonable" profile size. Use four times that for printing.
|
||||
static constexpr int profileScale = 4;
|
||||
static constexpr int profileWidth = 800 * profileScale;
|
||||
static constexpr int profileHeight = 600 * profileScale;
|
||||
|
||||
static void exportProfile(ProfileWidget2 *profile, const struct dive *dive, const QString &filename)
|
||||
{
|
||||
profile->setProfileState(dive, 0);
|
||||
profile->plotDive(dive, 0, false, true);
|
||||
QImage image = QImage(profile->size(), QImage::Format_RGB32);
|
||||
QImage image = QImage(QSize(profileWidth, profileHeight), QImage::Format_RGB32);
|
||||
QPainter paint;
|
||||
paint.begin(&image);
|
||||
profile->render(&paint);
|
||||
profile->draw(&paint, QRect(0, 0, profileWidth, profileHeight));
|
||||
image.save(filename);
|
||||
}
|
||||
|
||||
static std::unique_ptr<ProfileWidget2> getPrintProfile()
|
||||
{
|
||||
// Let's say that 800x600 is a "reasonable" profile size. Use four times that for printing.
|
||||
const int scale = 4;
|
||||
QSize size(800 * scale, 600 * scale);
|
||||
|
||||
// TODO: Annoyingly, this still needs a parent window? Otherwise,
|
||||
// the profile is shown as its own window, when calling show() below.
|
||||
auto profile = std::make_unique<ProfileWidget2>(nullptr, MainWindow::instance());
|
||||
profile->resize(size);
|
||||
profile->show(); // Ominous: if the scene isn't shown, parts of the plot are missing. Needs investigation.
|
||||
auto profile = std::make_unique<ProfileWidget2>(nullptr, nullptr);
|
||||
profile->setPrintMode(true);
|
||||
profile->setFontPrintScale((double)scale);
|
||||
profile->setFontPrintScale((double)profileScale);
|
||||
return profile;
|
||||
}
|
||||
|
||||
|
|
|
@ -609,15 +609,11 @@ void PlannerWidgets::printDecoPlan()
|
|||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
|
||||
// TODO: Annoyingly, this still needs a parent window? Otherwise,
|
||||
// the profile is shown as its own window, when calling show() below.
|
||||
auto profile = std::make_unique<ProfileWidget2>(DivePlannerPointsModel::instance(), MainWindow::instance());
|
||||
profile->show(); // Ominous: if the scene isn't shown, parts of the plot are missing. Needs investigation.
|
||||
profile->resize(renderSize.toSize());
|
||||
auto profile = std::make_unique<ProfileWidget2>(DivePlannerPointsModel::instance(), nullptr);
|
||||
profile->setPlanState(&displayed_dive, 0);
|
||||
profile->plotDive(&displayed_dive, 0, true, true);
|
||||
profile->setPrintMode(true);
|
||||
profile->render(&painter);
|
||||
profile->draw(&painter, QRect(0, 0, pixmap.width(), pixmap.height()));
|
||||
|
||||
QByteArray byteArray;
|
||||
QBuffer buffer(&byteArray);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "printer.h"
|
||||
#include "mainwindow.h"
|
||||
#include "templatelayout.h"
|
||||
#include "core/statistics.h"
|
||||
#include "core/qthelper.h"
|
||||
|
@ -36,31 +35,10 @@ void Printer::putProfileImage(const QRect &profilePlaceholder, const QRect &view
|
|||
int y = profilePlaceholder.y() - viewPort.y();
|
||||
// use the placeHolder and the viewPort position to calculate the relative position of the dive profile.
|
||||
QRect pos(x, y, profilePlaceholder.width(), profilePlaceholder.height());
|
||||
|
||||
profile->setProfileState(dive, 0);
|
||||
profile->plotDive(dive, 0, true);
|
||||
|
||||
if (!printOptions.color_selected) {
|
||||
QImage image(pos.width(), pos.height(), QImage::Format_ARGB32);
|
||||
QPainter imgPainter(&image);
|
||||
imgPainter.setRenderHint(QPainter::Antialiasing);
|
||||
imgPainter.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
profile->render(&imgPainter, QRect(0, 0, pos.width(), pos.height()));
|
||||
imgPainter.end();
|
||||
|
||||
// convert QImage to grayscale before rendering
|
||||
for (int i = 0; i < image.height(); i++) {
|
||||
QRgb *pixel = reinterpret_cast<QRgb *>(image.scanLine(i));
|
||||
QRgb *end = pixel + image.width();
|
||||
for (; pixel != end; pixel++) {
|
||||
int gray_val = qGray(*pixel);
|
||||
*pixel = QColor(gray_val, gray_val, gray_val).rgb();
|
||||
}
|
||||
}
|
||||
|
||||
painter->drawImage(pos, image);
|
||||
} else {
|
||||
profile->render(painter, pos);
|
||||
}
|
||||
profile->draw(painter, pos);
|
||||
}
|
||||
|
||||
void Printer::flowRender()
|
||||
|
@ -124,9 +102,7 @@ void Printer::flowRender()
|
|||
|
||||
void Printer::render(int pages)
|
||||
{
|
||||
// TODO: Annoyingly, this still needs a parent window? Otherwise,
|
||||
// the profile is shown as its own window, when calling show() below.
|
||||
auto profile = std::make_unique<ProfileWidget2>(nullptr, MainWindow::instance());
|
||||
auto profile = std::make_unique<ProfileWidget2>(nullptr, nullptr);
|
||||
double printFontScale = 1.0;
|
||||
|
||||
// apply printing settings to profile
|
||||
|
@ -149,8 +125,6 @@ void Printer::render(int pages)
|
|||
// This is arbitrary, but it seems to work reasonably.
|
||||
QSize size = collection[0].geometry().size();
|
||||
printFontScale = size.height() / 600.0;
|
||||
profile->show(); // Ominous: if the scene isn't shown, parts of the plot are missing. Needs investigation.
|
||||
profile->resize(size);
|
||||
}
|
||||
profile->setFontPrintScale(printFontScale);
|
||||
|
||||
|
|
|
@ -2161,3 +2161,39 @@ struct dive *ProfileWidget2::mutable_dive() const
|
|||
{
|
||||
return const_cast<dive *>(d);
|
||||
}
|
||||
|
||||
QImage ProfileWidget2::toImage(QSize size)
|
||||
{
|
||||
// The size of chart with respect to the scene is fixed - by convention - to 100.0.
|
||||
// We add 2% to the height so that the dive computer name is not cut off.
|
||||
QRectF sceneRect(0.0, 0.0, 100.0, 102.0);
|
||||
|
||||
QImage image(size, QImage::Format_ARGB32);
|
||||
image.fill(getColor(::BACKGROUND, isGrayscale));
|
||||
|
||||
QPainter imgPainter(&image);
|
||||
imgPainter.setRenderHint(QPainter::Antialiasing);
|
||||
imgPainter.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
scene()->render(&imgPainter, QRect(QPoint(), size), sceneRect, Qt::IgnoreAspectRatio);
|
||||
imgPainter.end();
|
||||
|
||||
if (isGrayscale) {
|
||||
// convert QImage to grayscale before rendering
|
||||
for (int i = 0; i < image.height(); i++) {
|
||||
QRgb *pixel = reinterpret_cast<QRgb *>(image.scanLine(i));
|
||||
QRgb *end = pixel + image.width();
|
||||
for (; pixel != end; pixel++) {
|
||||
int gray_val = qGray(*pixel);
|
||||
*pixel = QColor(gray_val, gray_val, gray_val).rgb();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
void ProfileWidget2::draw(QPainter *painter, const QRect &pos)
|
||||
{
|
||||
QImage img = toImage(pos.size());
|
||||
painter->drawImage(pos, img);
|
||||
}
|
||||
|
|
|
@ -79,6 +79,8 @@ public:
|
|||
bool isPlanner() const;
|
||||
double getFontPrintScale() const;
|
||||
void setFontPrintScale(double scale);
|
||||
void draw(QPainter *painter, const QRect &pos);
|
||||
QImage toImage(QSize size);
|
||||
#ifndef SUBSURFACE_MOBILE
|
||||
bool eventFilter(QObject *, QEvent *) override;
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue