Change QLineF::setLength() to work whenever length() is non-zero
Previously it only worked when isNull() was false, which is true for very short lines, even though length() may be non-zero. [ChangeLog][QtCore][QLineF] QLineF::setLength() will now set the length if the line's length() is non-zero. Previously, it was documented to only set the length if isNull() was false; this is a fuzzy check, so isNull() could be true for a line with non-zero length(). Fixes: QTBUG-89569 Change-Id: I803e622ad09c85815dde25df8dd3ba6dfcba0714 Reviewed-by: Lars Knoll <lars.knoll@qt.io> (cherry picked from commit 6974737695eae5a41bc8a3f344a4f1f199006f21) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
636fcc4bb2
commit
28ba7ac178
@ -517,12 +517,13 @@ QDataStream &operator>>(QDataStream &stream, QLine &line)
|
||||
\fn void QLineF::setLength(qreal length)
|
||||
|
||||
Sets the length of the line to the given \a length. QLineF will
|
||||
move the end point - p2() - of the line to give the line its new length.
|
||||
move the end point - p2() - of the line to give the line its new
|
||||
length, unless length() was previously zero, in which case no
|
||||
scaling is attempted. For lines with very short lengths
|
||||
(represented by denormal floating-point values), results may be
|
||||
imprecise.
|
||||
|
||||
A null line will not be rescaled. For non-null lines with very short lengths
|
||||
(represented by denormal floating-point values), results may be imprecise.
|
||||
|
||||
\sa length(), isNull(), unitVector()
|
||||
\sa length(), unitVector()
|
||||
*/
|
||||
|
||||
/*!
|
||||
|
@ -372,12 +372,11 @@ constexpr inline QPointF QLineF::center() const
|
||||
|
||||
inline void QLineF::setLength(qreal len)
|
||||
{
|
||||
if (isNull())
|
||||
return;
|
||||
Q_ASSERT(length() > 0);
|
||||
const QLineF v = unitVector();
|
||||
len /= v.length(); // In case it's not quite exactly 1.
|
||||
pt2 = QPointF(pt1.x() + len * v.dx(), pt1.y() + len * v.dy());
|
||||
const qreal oldLength = length();
|
||||
// Scale len by dx() / length() and dy() / length(), two O(1) quantities,
|
||||
// rather than scaling dx() and dy() by len / length(), which might overflow.
|
||||
if (oldLength > 0)
|
||||
pt2 = QPointF(pt1.x() + len * (dx() / oldLength), pt1.y() + len * (dy() / oldLength));
|
||||
}
|
||||
|
||||
constexpr inline QPointF QLineF::pointAt(qreal t) const
|
||||
|
@ -247,8 +247,8 @@ void tst_QLine::testLength_data()
|
||||
<< -(tiny * .5) << -(tiny * .5) << (tiny * .5) << (tiny * .5)
|
||||
<< (tiny * M_SQRT2) << (2 * M_SQRT2) << 2.0 << 2.0;
|
||||
QTest::newRow("[1+3e-13,1+4e-13]|1895| (1, 1)")
|
||||
<< 1.0 << 1.0 << (1 + 3e-13) << (1 + 4e-13) // isNull(), so ignores setLength()
|
||||
<< 5e-13 << 1895.0 << 3e-13 << 4e-13;
|
||||
<< 1.0 << 1.0 << (1 + 3e-13) << (1 + 4e-13)
|
||||
<< 5e-13 << 1895.0 << 1137.0 << 1516.0;
|
||||
QTest::newRow("[4e-323,5e-324]|1892|") // Unavoidable underflow: denormals
|
||||
<< 0.0 << 0.0 << 4e-323 << 5e-324
|
||||
<< 4e-323 << 1892.0 << 4e-323 << 5e-324; // vx, vy values ignored
|
||||
@ -266,14 +266,14 @@ void tst_QLine::testLength()
|
||||
QFETCH(double, vy);
|
||||
|
||||
QLineF l(x1, y1, x2, y2);
|
||||
const bool wasNull = l.isNull();
|
||||
if (!wasNull)
|
||||
QCOMPARE(l.length(), qreal(length));
|
||||
QCOMPARE(l.length(), qreal(length));
|
||||
|
||||
l.setLength(lengthToSet);
|
||||
QCOMPARE(l.length(), wasNull ? qreal(length) : qreal(lengthToSet));
|
||||
// Scaling tiny values up to big can be imprecise: don't try to test vx, vy
|
||||
if (wasNull || !qFuzzyIsNull(length)) {
|
||||
if (length > 0 && qFuzzyIsNull(length)) {
|
||||
QVERIFY(l.length() > lengthToSet / 2 && l.length() < lengthToSet * 2);
|
||||
} else {
|
||||
QCOMPARE(l.length(), length > 0 ? qreal(lengthToSet) : qreal(length));
|
||||
QCOMPARE(l.dx(), qreal(vx));
|
||||
QCOMPARE(l.dy(), qreal(vy));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user