QBezier: replace out parameters by return-by-value in split()
At least QBezier itself is calling the old function with *this aliased to one of the arguments. Consequently, the implementation looks rather ... shuffled, to avoid writing into members that it will read once more later. Fix by returning a std::pair<QBezier, QBezier> instead. This simplifies the code that doesn't actually pass existing objects in, and avoids aliasing problems cropping up under seemingly innocuous reorderings of statements in the implementation going forward. While I'm usually vehemently against use std::pair or std::tuple in APIs, preferring simple structs with aptly-named members instead, this is one case where the .first and .second actually fit, and pair allows us to use std::tie, which was handy in qbezier.cpp. This patch preserves the body of the function as much as possible. A follow-up patch will clean it up. Change-Id: I017dfee4a0e69a2e171ce21b89ba04654772c33d Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>bb10
parent
5b2dfbc649
commit
d1b099c3e3
|
|
@ -47,6 +47,8 @@
|
|||
|
||||
#include <private/qnumeric_p.h>
|
||||
|
||||
#include <tuple> // for std::tie()
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
//#define QDEBUG_BEZIER
|
||||
|
|
@ -128,7 +130,7 @@ void QBezier::addToPolygon(QPolygonF *polygon, qreal bezier_flattening_threshold
|
|||
--lvl;
|
||||
} else {
|
||||
// split, second half of the polygon goes lower into the stack
|
||||
b->split(b+1, b);
|
||||
std::tie(b[1], b[0]) = b->split();
|
||||
lvl[1] = --lvl[0];
|
||||
++b;
|
||||
++lvl;
|
||||
|
|
@ -166,7 +168,7 @@ void QBezier::addToPolygon(QDataBuffer<QPointF> &polygon, qreal bezier_flattenin
|
|||
--lvl;
|
||||
} else {
|
||||
// split, second half of the polygon goes lower into the stack
|
||||
b->split(b+1, b);
|
||||
std::tie(b[1], b[0]) = b->split();
|
||||
lvl[1] = --lvl[0];
|
||||
++b;
|
||||
++lvl;
|
||||
|
|
@ -422,7 +424,7 @@ redo:
|
|||
o += 2;
|
||||
--b;
|
||||
} else {
|
||||
b->split(b+1, b);
|
||||
std::tie(b[1], b[0]) = b->split();
|
||||
++b;
|
||||
}
|
||||
}
|
||||
|
|
@ -464,8 +466,6 @@ qreal QBezier::length(qreal error) const
|
|||
|
||||
void QBezier::addIfClose(qreal *length, qreal error) const
|
||||
{
|
||||
QBezier left, right; /* bez poly splits */
|
||||
|
||||
qreal len = qreal(0.0); /* arc length */
|
||||
qreal chord; /* chord length */
|
||||
|
||||
|
|
@ -476,9 +476,9 @@ void QBezier::addIfClose(qreal *length, qreal error) const
|
|||
chord = QLineF(QPointF(x1, y1),QPointF(x4, y4)).length();
|
||||
|
||||
if((len-chord) > error) {
|
||||
split(&left, &right); /* split in two */
|
||||
left.addIfClose(length, error); /* try left side */
|
||||
right.addIfClose(length, error); /* try right side */
|
||||
const auto halves = split(); /* split in two */
|
||||
halves.first.addIfClose(length, error); /* try left side */
|
||||
halves.second.addIfClose(length, error); /* try right side */
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ public:
|
|||
inline QLineF endTangent() const;
|
||||
|
||||
inline void parameterSplitLeft(qreal t, QBezier *left);
|
||||
inline void split(QBezier *firstHalf, QBezier *secondHalf) const;
|
||||
inline std::pair<QBezier, QBezier> split() const;
|
||||
|
||||
int shifted(QBezier *curveSegments, int maxSegmets,
|
||||
qreal offset, float threshold) const;
|
||||
|
|
@ -223,10 +223,11 @@ inline QPointF QBezier::secondDerivedAt(qreal t) const
|
|||
a * y1 + b * y2 + c * y3 + d * y4);
|
||||
}
|
||||
|
||||
inline void QBezier::split(QBezier *firstHalf, QBezier *secondHalf) const
|
||||
std::pair<QBezier, QBezier> QBezier::split() const
|
||||
{
|
||||
Q_ASSERT(firstHalf);
|
||||
Q_ASSERT(secondHalf);
|
||||
std::pair<QBezier, QBezier> r;
|
||||
auto firstHalf = &r.first;
|
||||
auto secondHalf = &r.second;
|
||||
|
||||
qreal c = (x2 + x3)*.5;
|
||||
firstHalf->x2 = (x1 + x2)*.5;
|
||||
|
|
@ -245,6 +246,8 @@ inline void QBezier::split(QBezier *firstHalf, QBezier *secondHalf) const
|
|||
firstHalf->y3 = (firstHalf->y2 + c)*.5;
|
||||
secondHalf->y2 = (secondHalf->y3 + c)*.5;
|
||||
firstHalf->y4 = secondHalf->y1 = (firstHalf->y3 + secondHalf->y2)*.5;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
inline void QBezier::parameterSplitLeft(qreal t, QBezier *left)
|
||||
|
|
|
|||
|
|
@ -1855,10 +1855,9 @@ static void qt_painterpath_isect_curve(const QBezier &bezier, const QPointF &pt,
|
|||
}
|
||||
|
||||
// split curve and try again...
|
||||
QBezier first_half, second_half;
|
||||
bezier.split(&first_half, &second_half);
|
||||
qt_painterpath_isect_curve(first_half, pt, winding, depth + 1);
|
||||
qt_painterpath_isect_curve(second_half, pt, winding, depth + 1);
|
||||
const auto halves = bezier.split();
|
||||
qt_painterpath_isect_curve(halves.first, pt, winding, depth + 1);
|
||||
qt_painterpath_isect_curve(halves.second, pt, winding, depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2013,10 +2012,9 @@ static bool qt_isect_curve_horizontal(const QBezier &bezier, qreal y, qreal x1,
|
|||
if (depth == 32 || (bounds.width() < lower_bound && bounds.height() < lower_bound))
|
||||
return true;
|
||||
|
||||
QBezier first_half, second_half;
|
||||
bezier.split(&first_half, &second_half);
|
||||
if (qt_isect_curve_horizontal(first_half, y, x1, x2, depth + 1)
|
||||
|| qt_isect_curve_horizontal(second_half, y, x1, x2, depth + 1))
|
||||
const auto halves = bezier.split();
|
||||
if (qt_isect_curve_horizontal(halves.first, y, x1, x2, depth + 1)
|
||||
|| qt_isect_curve_horizontal(halves.second, y, x1, x2, depth + 1))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -2032,10 +2030,9 @@ static bool qt_isect_curve_vertical(const QBezier &bezier, qreal x, qreal y1, qr
|
|||
if (depth == 32 || (bounds.width() < lower_bound && bounds.height() < lower_bound))
|
||||
return true;
|
||||
|
||||
QBezier first_half, second_half;
|
||||
bezier.split(&first_half, &second_half);
|
||||
if (qt_isect_curve_vertical(first_half, x, y1, y2, depth + 1)
|
||||
|| qt_isect_curve_vertical(second_half, x, y1, y2, depth + 1))
|
||||
const auto halves = bezier.split();
|
||||
if (qt_isect_curve_vertical(halves.first, x, y1, y2, depth + 1)
|
||||
|| qt_isect_curve_vertical(halves.second, x, y1, y2, depth + 1))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
Loading…
Reference in New Issue