print: QPageLayout: Fix pt unit conversion
This patch corrects the miscalculation in point unit conversion, ensuring correct margin updates. Previously, non-pt units were rounded to two decimal places. When converting back to pt, rounding was to zero decimals, making the result always less than the original. This could result in margins falling below the minimum allowed. Example: original_points = 8.4 multiplier = 2.83464566929 mm: qRound(8.4 / multiplier * 100) / 100 = 2.96 new_points: qRound(2.96 * multiplier) = 8 // wrong! The fix rounds back-converted values up to two decimals, ensuring they are never less than the original and thus stay above minimum margins. new_points: qCeil(2.96 * multiplier * 100) / 100 = 8.4 Also, remove unused function qt_convertPoint. Pick-to: 6.6 Change-Id: I6109f8d381aec96db1ce04cc167f7b73c1c0b9a8 Reviewed-by: David Faure <david.faure@kdab.com>
This commit is contained in:
parent
5fb2d50e42
commit
d420c1e25a
@ -39,41 +39,19 @@ Q_GUI_EXPORT qreal qt_pointMultiplier(QPageLayout::Unit unit)
|
||||
// Multiplier for converting pixels to points.
|
||||
extern qreal qt_pixelMultiplier(int resolution);
|
||||
|
||||
QPointF qt_convertPoint(const QPointF &xy, QPageLayout::Unit fromUnits, QPageLayout::Unit toUnits)
|
||||
{
|
||||
// If the size have the same units, or are all 0, then don't need to convert
|
||||
if (fromUnits == toUnits || xy.isNull())
|
||||
return xy;
|
||||
|
||||
// If converting to points then convert and round to 0 decimal places
|
||||
if (toUnits == QPageLayout::Point) {
|
||||
const qreal multiplier = qt_pointMultiplier(fromUnits);
|
||||
return QPointF(qRound(xy.x() * multiplier),
|
||||
qRound(xy.y() * multiplier));
|
||||
}
|
||||
|
||||
// If converting to other units, need to convert to unrounded points first
|
||||
QPointF pointXy = (fromUnits == QPageLayout::Point) ? xy : xy * qt_pointMultiplier(fromUnits);
|
||||
|
||||
// Then convert from points to required units rounded to 2 decimal places
|
||||
const qreal multiplier = qt_pointMultiplier(toUnits);
|
||||
return QPointF(qRound(pointXy.x() * 100 / multiplier) / 100.0,
|
||||
qRound(pointXy.y() * 100 / multiplier) / 100.0);
|
||||
}
|
||||
|
||||
Q_GUI_EXPORT QMarginsF qt_convertMargins(const QMarginsF &margins, QPageLayout::Unit fromUnits, QPageLayout::Unit toUnits)
|
||||
{
|
||||
// If the margins have the same units, or are all 0, then don't need to convert
|
||||
if (fromUnits == toUnits || margins.isNull())
|
||||
return margins;
|
||||
|
||||
// If converting to points then convert and round to 0 decimal places
|
||||
// If converting to points then convert and round up to 2 decimal places
|
||||
if (toUnits == QPageLayout::Point) {
|
||||
const qreal multiplier = qt_pointMultiplier(fromUnits);
|
||||
return QMarginsF(qRound(margins.left() * multiplier),
|
||||
qRound(margins.top() * multiplier),
|
||||
qRound(margins.right() * multiplier),
|
||||
qRound(margins.bottom() * multiplier));
|
||||
const qreal multiplierX100 = qt_pointMultiplier(fromUnits) * 100;
|
||||
return QMarginsF(qCeil(margins.left() * multiplierX100) / 100.0,
|
||||
qCeil(margins.top() * multiplierX100) / 100.0,
|
||||
qCeil(margins.right() * multiplierX100) / 100.0,
|
||||
qCeil(margins.bottom() * multiplierX100) / 100.0);
|
||||
}
|
||||
|
||||
// If converting to other units, need to convert to unrounded points first
|
||||
|
@ -12,6 +12,8 @@ private slots:
|
||||
void invalid();
|
||||
void basics();
|
||||
void setGetMargins();
|
||||
void setUnits_data();
|
||||
void setUnits();
|
||||
};
|
||||
|
||||
void tst_QPageLayout::invalid()
|
||||
@ -238,6 +240,54 @@ void tst_QPageLayout::setGetMargins()
|
||||
QCOMPARE(fullPage.maximumMargins(), max);
|
||||
}
|
||||
|
||||
void tst_QPageLayout::setUnits_data()
|
||||
{
|
||||
QTest::addColumn<QPageLayout::Unit>("units");
|
||||
QTest::newRow("Millimeter") << QPageLayout::Millimeter;
|
||||
QTest::newRow("Point") << QPageLayout::Point;
|
||||
QTest::newRow("Inch") << QPageLayout::Inch;
|
||||
QTest::newRow("Pica") << QPageLayout::Pica;
|
||||
QTest::newRow("Didot") << QPageLayout::Didot;
|
||||
QTest::newRow("Cicero") << QPageLayout::Cicero;
|
||||
}
|
||||
|
||||
void tst_QPageLayout::setUnits()
|
||||
{
|
||||
QFETCH(QPageLayout::Unit, units);
|
||||
QPageLayout pageLayout = QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(), units);
|
||||
int maxLeftX100 = qFloor(pageLayout.maximumMargins().left() * 100);
|
||||
QVERIFY(maxLeftX100 > 0);
|
||||
for (int i = 1; i <= maxLeftX100; ++i) {
|
||||
const qreal margin = i / 100.;
|
||||
const QMarginsF unitsMargins = QMarginsF(margin, margin, margin, margin);
|
||||
pageLayout.setMargins(unitsMargins);
|
||||
pageLayout.setUnits(QPageLayout::Point);
|
||||
const QMarginsF pointsMargins = pageLayout.margins();
|
||||
if (units == QPageLayout::Point) {
|
||||
QCOMPARE(pointsMargins, unitsMargins);
|
||||
} else {
|
||||
QCOMPARE_GT(pointsMargins.left(), unitsMargins.left());
|
||||
QCOMPARE_GT(pointsMargins.top(), unitsMargins.top());
|
||||
QCOMPARE_GT(pointsMargins.right(), unitsMargins.right());
|
||||
QCOMPARE_GT(pointsMargins.bottom(), unitsMargins.bottom());
|
||||
}
|
||||
pageLayout.setUnits(units);
|
||||
const QMarginsF convertedUnitsMargins = pageLayout.margins();
|
||||
if (units == QPageLayout::Didot) {
|
||||
// When using Didot units, the small multiplier and ceiling function in conversion
|
||||
// may cause the converted units to not match the original exactly. However, we
|
||||
// can verify that the converted margins are always greater than or equal to the
|
||||
// original.
|
||||
QCOMPARE_GE(convertedUnitsMargins.left(), unitsMargins.left());
|
||||
QCOMPARE_GE(convertedUnitsMargins.top(), unitsMargins.top());
|
||||
QCOMPARE_GE(convertedUnitsMargins.right(), unitsMargins.right());
|
||||
QCOMPARE_GE(convertedUnitsMargins.bottom(), unitsMargins.bottom());
|
||||
} else {
|
||||
QCOMPARE(convertedUnitsMargins, unitsMargins);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QTEST_APPLESS_MAIN(tst_QPageLayout)
|
||||
|
||||
#include "tst_qpagelayout.moc"
|
||||
|
Loading…
x
Reference in New Issue
Block a user