profile: for printing/mobile access ProfileScene directly

Instead of using the interactive ProfileWidget2, just
use the ProfileScene to render the profile for printing,
export and mobile. One layer (QWidget) less.

This removes all the kludges for handling DPR on mobile.
Thus, the rendering will now be off and have to be fixed
by redoing the scaling code.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2021-08-04 07:27:41 +02:00 committed by Dirk Hohndel
parent 84ebd1d67a
commit 51dc5113c2
10 changed files with 70 additions and 136 deletions

View file

@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
#include "qmlprofile.h"
#include "profilescene.h"
#include "mobile-widgets/qmlmanager.h"
#include "core/errorhelper.h"
#include "core/subsurface-string.h"
@ -26,11 +27,13 @@ QMLProfile::QMLProfile(QQuickItem *parent) :
setDevicePixelRatio(QMLManager::instance()->lastDevicePixelRatio());
}
QMLProfile::~QMLProfile()
{
}
void QMLProfile::createProfileView()
{
m_profileWidget.reset(new ProfileWidget2(nullptr, fontScale * m_devicePixelRatio, nullptr));
m_profileWidget->setProfileState(nullptr, 0);
m_profileWidget->setPrintMode();
m_profileWidget.reset(new ProfileScene(fontScale * m_devicePixelRatio, true, false));
}
// we need this so we can connect update() to the scaleChanged() signal - which the connect above cannot do
@ -51,75 +54,7 @@ void QMLProfile::paint(QPainter *painter)
// let's look at the intended size of the content and scale our scene accordingly
QRect painterRect = painter->viewport();
QRect profileRect = m_profileWidget->viewport()->rect();
// qDebug() << "profile viewport and painter viewport" << profileRect << painterRect;
qreal sceneSize = 104; // that should give us 2% margin all around (100x100 scene)
qreal dprComp = devicePixelRatio() * painterRect.width() / profileRect.width();
qreal sx = painterRect.width() / sceneSize / dprComp;
qreal sy = painterRect.height() / sceneSize / dprComp;
// next figure out the weird magic by which we need to shift the painter so the profile is shown
double dpr = devicePixelRatio();
double magicValues[] = { 0.0, 0.1, 0.25, 0.33, 0.375, 0.40, 0.42};
qreal magicShiftFactor = 0.0;
if (dpr < 1.3) {
magicShiftFactor = magicValues[0];
} else if (dpr > 6.0) {
magicShiftFactor = magicValues[6];
} else if (IS_FP_SAME(dpr, rint(dpr))) {
magicShiftFactor = magicValues[lrint(dpr)];
} else {
int lower = (int)dpr;
magicShiftFactor = (magicValues[lower] * (lower + 1 - dpr) + magicValues[lower + 1] * (dpr - lower));
if (dpr < 1.45)
magicShiftFactor -= 0.03;
}
// now set up the transformations scale the profile and
// shift the painter (taking its existing transformation into account)
QTransform profileTransform = QTransform();
profileTransform.scale(sx, sy);
// this is a bit complex because of the interaction with the Qt widget scaling
// logic. We use the default setup where the scale happens with the center of the
// widget as transformation center.
// The QML code *should* already ensure that we don't shrink the profile, but for
// the math below to work, let's make sure
qreal profileScale = scale();
if (profileScale < 1.0) {
profileScale = 1.0;
setScale(profileScale);
}
// When zooming and panning we want to ensure that we always show a subset of the
// profile and not the "empty space" around the profile.
// a bit of math on a piece of paper shows that our offsets need to stay within +/- dx and dy
qreal dx = width() * (profileScale - 1) / (2 * dpr * profileScale);
qreal dy = height() * (profileScale - 1) / (2 * dpr * profileScale);
m_xOffset = std::max(-dx, std::min(m_xOffset, dx));
m_yOffset = std::max(-dy, std::min(m_yOffset, dy));
QTransform painterTransform = painter->transform();
painterTransform.translate(dpr * m_xOffset - painterRect.width() * magicShiftFactor, dpr * m_yOffset - painterRect.height() * magicShiftFactor);
#if defined(PROFILE_SCALING_DEBUG)
// some debugging messages to help adjust this in case the magic above is insufficient
qDebug() << QString("dpr %1 profile viewport %2 %3 painter viewport %4 %5").arg(dpr).arg(profileRect.width()).arg(profileRect.height())
.arg(painterRect.width()).arg(painterRect.height());
qDebug() << QString("profile matrix %1 %2 %3 %4 %5 %6 %7 %8 %9").arg(profileTransform.m11()).arg(profileTransform.m12()).arg(profileTransform.m13())
.arg(profileTransform.m21()).arg(profileTransform.m22()).arg(profileTransform.m23())
.arg(profileTransform.m31()).arg(profileTransform.m32()).arg(profileTransform.m33()));
qDebug() << QString("painter matrix %1 %2 %3 %4 %5 %6 %7 %8 %9").arg(painterTransform.m11()).arg(painterTransform.m12()).arg(painterTransform.m13())
.arg(painterTransform.m21()).arg(painterTransform.m22()).arg(painterTransform.m23())
.arg(painterTransform.m31()).arg(painterTransform.m32()).arg(painterTransform.m33()));
qDebug() << "exist profile transform" << m_profileWidget->transform() << "painter transform" << painter->transform();
#endif
// apply the transformation
painter->setTransform(painterTransform);
m_profileWidget->setTransform(profileTransform);
// finally, render the profile
m_profileWidget->render(painter);
if (verbose)
qDebug() << "finished rendering profile with offset" << QString::number(m_xOffset, 'f', 1) << "/" << QString::number(m_yOffset, 'f', 1) << "in" << timer.elapsed() << "ms";
m_profileWidget->draw(painter, painterRect);
}
void QMLProfile::setMargin(int margin)