QPainterPath: Add option to cache calculations
Speeds up repeated calls to length and percentage functions. Change-Id: I357732e35de648e7da07ad492e58d5b94c2c0870 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
This commit is contained in:
parent
76b1424048
commit
90247966a7
@ -2821,6 +2821,44 @@ QPolygonF QPainterPath::toFillPolygon(const QTransform &matrix) const
|
|||||||
return polygon;
|
return polygon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns true if caching is enabled; otherwise returns false.
|
||||||
|
|
||||||
|
\since 6.10
|
||||||
|
\sa setCachingEnabled()
|
||||||
|
*/
|
||||||
|
bool QPainterPath::isCachingEnabled() const
|
||||||
|
{
|
||||||
|
Q_D(QPainterPath);
|
||||||
|
return d && d->cacheEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Enables or disables length caching according to the value of \a enabled.
|
||||||
|
|
||||||
|
Enabling caching speeds up repeated calls to the member functions involving path length
|
||||||
|
and percentage values, such as length(), percentAtLength(), pointAtPercent() etc., at the cost
|
||||||
|
of some extra memory usage for storage of intermediate calculations. By default it is disabled.
|
||||||
|
|
||||||
|
Disabling caching will release any allocated cache memory.
|
||||||
|
|
||||||
|
\since 6.10
|
||||||
|
\sa isCachingEnabled(), length(), percentAtLength(), pointAtPercent()
|
||||||
|
*/
|
||||||
|
void QPainterPath::setCachingEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
ensureData();
|
||||||
|
if (d_func()->cacheEnabled == enabled)
|
||||||
|
return;
|
||||||
|
detach();
|
||||||
|
QPainterPathPrivate *d = d_func();
|
||||||
|
d->cacheEnabled = enabled;
|
||||||
|
if (!enabled) {
|
||||||
|
d->m_runLengths.clear();
|
||||||
|
d->m_runLengths.squeeze();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//derivative of the equation
|
//derivative of the equation
|
||||||
static inline qreal slopeAt(qreal t, qreal a, qreal b, qreal c, qreal d)
|
static inline qreal slopeAt(qreal t, qreal a, qreal b, qreal c, qreal d)
|
||||||
{
|
{
|
||||||
@ -2835,6 +2873,11 @@ qreal QPainterPath::length() const
|
|||||||
Q_D(QPainterPath);
|
Q_D(QPainterPath);
|
||||||
if (isEmpty())
|
if (isEmpty())
|
||||||
return 0;
|
return 0;
|
||||||
|
if (d->cacheEnabled) {
|
||||||
|
if (d->dirtyRunLengths)
|
||||||
|
d->computeRunLengths();
|
||||||
|
return d->m_runLengths.last();
|
||||||
|
}
|
||||||
|
|
||||||
qreal len = 0;
|
qreal len = 0;
|
||||||
for (int i=1; i<d->elements.size(); ++i) {
|
for (int i=1; i<d->elements.size(); ++i) {
|
||||||
@ -2883,6 +2926,32 @@ qreal QPainterPath::percentAtLength(qreal len) const
|
|||||||
if (len > totalLength)
|
if (len > totalLength)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
if (d->cacheEnabled) {
|
||||||
|
const int ei = qMax(d->elementAtT(len / totalLength), 1); // Skip initial MoveTo
|
||||||
|
qreal res = 0;
|
||||||
|
const QPainterPath::Element &e = d->elements[ei];
|
||||||
|
switch (e.type) {
|
||||||
|
case QPainterPath::LineToElement:
|
||||||
|
res = len / totalLength;
|
||||||
|
break;
|
||||||
|
case CurveToElement:
|
||||||
|
{
|
||||||
|
QBezier b = QBezier::fromPoints(d->elements.at(ei-1),
|
||||||
|
e,
|
||||||
|
d->elements.at(ei+1),
|
||||||
|
d->elements.at(ei+2));
|
||||||
|
qreal prevLen = d->m_runLengths[ei - 1];
|
||||||
|
qreal blen = d->m_runLengths[ei] - prevLen;
|
||||||
|
qreal elemRes = b.tAtLength(len - prevLen);
|
||||||
|
res = (elemRes * blen + prevLen) / totalLength;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
Q_UNREACHABLE();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
qreal curLen = 0;
|
qreal curLen = 0;
|
||||||
for (int i=1; i<d->elements.size(); ++i) {
|
for (int i=1; i<d->elements.size(); ++i) {
|
||||||
const Element &e = d->elements.at(i);
|
const Element &e = d->elements.at(i);
|
||||||
@ -2927,7 +2996,8 @@ qreal QPainterPath::percentAtLength(qreal len) const
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline QBezier bezierAtT(const QPainterPath &path, qreal t, qreal *startingLength, qreal *bezierLength)
|
static inline QBezier uncached_bezierAtT(const QPainterPath &path, qreal t, qreal *startingLength,
|
||||||
|
qreal *bezierLength)
|
||||||
{
|
{
|
||||||
*startingLength = 0;
|
*startingLength = 0;
|
||||||
if (t > 1)
|
if (t > 1)
|
||||||
@ -2981,6 +3051,35 @@ static inline QBezier bezierAtT(const QPainterPath &path, qreal t, qreal *starti
|
|||||||
return QBezier();
|
return QBezier();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QBezier QPainterPathPrivate::bezierAtT(const QPainterPath &path, qreal t, qreal *startingLength,
|
||||||
|
qreal *bezierLength) const
|
||||||
|
{
|
||||||
|
Q_ASSERT(t >= 0 && t <= 1);
|
||||||
|
QPainterPathPrivate *d = path.d_func();
|
||||||
|
if (!path.isEmpty() && d->cacheEnabled) {
|
||||||
|
const int ei = qMax(d->elementAtT(t), 1); // Avoid the initial MoveTo element
|
||||||
|
const qreal prevRunLength = d->m_runLengths[ei - 1];
|
||||||
|
*startingLength = prevRunLength;
|
||||||
|
*bezierLength = d->m_runLengths[ei] - prevRunLength;
|
||||||
|
const QPointF prev = d->elements[ei - 1];
|
||||||
|
const QPainterPath::Element &e = d->elements[ei];
|
||||||
|
switch (e.type) {
|
||||||
|
case QPainterPath::LineToElement:
|
||||||
|
{
|
||||||
|
QPointF delta = (e - prev) / 3;
|
||||||
|
return QBezier::fromPoints(prev, prev + delta, prev + 2 * delta, e);
|
||||||
|
}
|
||||||
|
case QPainterPath::CurveToElement:
|
||||||
|
return QBezier::fromPoints(prev, e, elements[ei + 1], elements[ei + 2]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Q_UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return uncached_bezierAtT(path, t, startingLength, bezierLength);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns the point at at the percentage \a t of the current path.
|
Returns the point at at the percentage \a t of the current path.
|
||||||
The argument \a t has to be between 0 and 1.
|
The argument \a t has to be between 0 and 1.
|
||||||
@ -3006,7 +3105,7 @@ QPointF QPainterPath::pointAtPercent(qreal t) const
|
|||||||
qreal totalLength = length();
|
qreal totalLength = length();
|
||||||
qreal curLen = 0;
|
qreal curLen = 0;
|
||||||
qreal bezierLen = 0;
|
qreal bezierLen = 0;
|
||||||
QBezier b = bezierAtT(*this, t, &curLen, &bezierLen);
|
QBezier b = d_ptr->bezierAtT(*this, t, &curLen, &bezierLen);
|
||||||
qreal realT = (totalLength * t - curLen) / bezierLen;
|
qreal realT = (totalLength * t - curLen) / bezierLen;
|
||||||
|
|
||||||
return b.pointAt(qBound(qreal(0), realT, qreal(1)));
|
return b.pointAt(qBound(qreal(0), realT, qreal(1)));
|
||||||
@ -3034,7 +3133,7 @@ qreal QPainterPath::angleAtPercent(qreal t) const
|
|||||||
qreal totalLength = length();
|
qreal totalLength = length();
|
||||||
qreal curLen = 0;
|
qreal curLen = 0;
|
||||||
qreal bezierLen = 0;
|
qreal bezierLen = 0;
|
||||||
QBezier bez = bezierAtT(*this, t, &curLen, &bezierLen);
|
QBezier bez = d_ptr->bezierAtT(*this, t, &curLen, &bezierLen);
|
||||||
qreal realT = (totalLength * t - curLen) / bezierLen;
|
qreal realT = (totalLength * t - curLen) / bezierLen;
|
||||||
|
|
||||||
qreal m1 = slopeAt(realT, bez.x1, bez.x2, bez.x3, bez.x4);
|
qreal m1 = slopeAt(realT, bez.x1, bez.x2, bez.x3, bez.x4);
|
||||||
@ -3063,7 +3162,7 @@ qreal QPainterPath::slopeAtPercent(qreal t) const
|
|||||||
qreal totalLength = length();
|
qreal totalLength = length();
|
||||||
qreal curLen = 0;
|
qreal curLen = 0;
|
||||||
qreal bezierLen = 0;
|
qreal bezierLen = 0;
|
||||||
QBezier bez = bezierAtT(*this, t, &curLen, &bezierLen);
|
QBezier bez = d_ptr->bezierAtT(*this, t, &curLen, &bezierLen);
|
||||||
qreal realT = (totalLength * t - curLen) / bezierLen;
|
qreal realT = (totalLength * t - curLen) / bezierLen;
|
||||||
|
|
||||||
qreal m1 = slopeAt(realT, bez.x1, bez.x2, bez.x3, bez.x4);
|
qreal m1 = slopeAt(realT, bez.x1, bez.x2, bez.x3, bez.x4);
|
||||||
@ -3283,9 +3382,10 @@ bool QPainterPath::contains(const QPainterPath &p) const
|
|||||||
|
|
||||||
void QPainterPath::setDirty(bool dirty)
|
void QPainterPath::setDirty(bool dirty)
|
||||||
{
|
{
|
||||||
|
d_func()->pathConverter.reset();
|
||||||
d_func()->dirtyBounds = dirty;
|
d_func()->dirtyBounds = dirty;
|
||||||
d_func()->dirtyControlBounds = dirty;
|
d_func()->dirtyControlBounds = dirty;
|
||||||
d_func()->pathConverter.reset();
|
d_func()->dirtyRunLengths = dirty;
|
||||||
d_func()->convex = false;
|
d_func()->convex = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3358,6 +3458,43 @@ void QPainterPath::computeControlPointRect() const
|
|||||||
d->controlBounds = QRectF(minx, miny, maxx - minx, maxy - miny);
|
d->controlBounds = QRectF(minx, miny, maxx - minx, maxy - miny);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QPainterPathPrivate::computeRunLengths()
|
||||||
|
{
|
||||||
|
Q_ASSERT(!elements.isEmpty());
|
||||||
|
|
||||||
|
m_runLengths.clear();
|
||||||
|
const int numElems = elements.size();
|
||||||
|
m_runLengths.reserve(numElems);
|
||||||
|
|
||||||
|
QPointF runPt = elements[0];
|
||||||
|
qreal runLen = 0.0;
|
||||||
|
for (int i = 0; i < numElems; i++) {
|
||||||
|
QPainterPath::Element e = elements[i];
|
||||||
|
switch (e.type) {
|
||||||
|
case QPainterPath::LineToElement:
|
||||||
|
runLen += QLineF(runPt, e).length();
|
||||||
|
runPt = e;
|
||||||
|
break;
|
||||||
|
case QPainterPath::CurveToElement: {
|
||||||
|
Q_ASSERT(i < numElems - 2);
|
||||||
|
QPainterPath::Element ee = elements[i + 2];
|
||||||
|
runLen += QBezier::fromPoints(runPt, e, elements[i + 1], ee).length();
|
||||||
|
runPt = ee;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QPainterPath::MoveToElement:
|
||||||
|
runPt = e;
|
||||||
|
break;
|
||||||
|
case QPainterPath::CurveToDataElement:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
m_runLengths.append(runLen);
|
||||||
|
}
|
||||||
|
Q_ASSERT(m_runLengths.size() == elements.size());
|
||||||
|
|
||||||
|
dirtyRunLengths = false;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_DEBUG_STREAM
|
#ifndef QT_NO_DEBUG_STREAM
|
||||||
QDebug operator<<(QDebug s, const QPainterPath &p)
|
QDebug operator<<(QDebug s, const QPainterPath &p)
|
||||||
{
|
{
|
||||||
|
@ -134,8 +134,10 @@ public:
|
|||||||
QPainterPath::Element elementAt(int i) const;
|
QPainterPath::Element elementAt(int i) const;
|
||||||
void setElementPositionAt(int i, qreal x, qreal y);
|
void setElementPositionAt(int i, qreal x, qreal y);
|
||||||
|
|
||||||
|
bool isCachingEnabled() const;
|
||||||
|
void setCachingEnabled(bool enabled);
|
||||||
qreal length() const;
|
qreal length() const;
|
||||||
qreal percentAtLength(qreal t) const;
|
qreal percentAtLength(qreal len) const;
|
||||||
QPointF pointAtPercent(qreal t) const;
|
QPointF pointAtPercent(qreal t) const;
|
||||||
qreal angleAtPercent(qreal t) const;
|
qreal angleAtPercent(qreal t) const;
|
||||||
qreal slopeAtPercent(qreal t) const;
|
qreal slopeAtPercent(qreal t) const;
|
||||||
@ -174,6 +176,7 @@ private:
|
|||||||
|
|
||||||
friend class QPainterPathStroker;
|
friend class QPainterPathStroker;
|
||||||
friend class QPainterPathStrokerPrivate;
|
friend class QPainterPathStrokerPrivate;
|
||||||
|
friend class QPainterPathPrivate;
|
||||||
friend class QTransform;
|
friend class QTransform;
|
||||||
friend class QVectorPath;
|
friend class QVectorPath;
|
||||||
friend Q_GUI_EXPORT const QVectorPath &qtVectorPathForPath(const QPainterPath &);
|
friend Q_GUI_EXPORT const QVectorPath &qtVectorPathForPath(const QPainterPath &);
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include <private/qvectorpath_p.h>
|
#include <private/qvectorpath_p.h>
|
||||||
#include <private/qstroker_p.h>
|
#include <private/qstroker_p.h>
|
||||||
|
#include <private/qbezier_p.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@ -111,7 +112,8 @@ public:
|
|||||||
dirtyBounds(false),
|
dirtyBounds(false),
|
||||||
dirtyControlBounds(false),
|
dirtyControlBounds(false),
|
||||||
convex(false),
|
convex(false),
|
||||||
hasWindingFill(false)
|
hasWindingFill(false),
|
||||||
|
cacheEnabled(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,21 +126,25 @@ public:
|
|||||||
dirtyBounds(false),
|
dirtyBounds(false),
|
||||||
dirtyControlBounds(false),
|
dirtyControlBounds(false),
|
||||||
convex(false),
|
convex(false),
|
||||||
hasWindingFill(false)
|
hasWindingFill(false),
|
||||||
|
cacheEnabled(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QPainterPathPrivate(const QPainterPathPrivate &other) noexcept
|
QPainterPathPrivate(const QPainterPathPrivate &other) noexcept
|
||||||
: QSharedData(other),
|
: QSharedData(other),
|
||||||
elements(other.elements),
|
elements(other.elements),
|
||||||
|
m_runLengths(other.m_runLengths),
|
||||||
bounds(other.bounds),
|
bounds(other.bounds),
|
||||||
controlBounds(other.controlBounds),
|
controlBounds(other.controlBounds),
|
||||||
cStart(other.cStart),
|
cStart(other.cStart),
|
||||||
require_moveTo(false),
|
require_moveTo(false),
|
||||||
dirtyBounds(other.dirtyBounds),
|
dirtyBounds(other.dirtyBounds),
|
||||||
dirtyControlBounds(other.dirtyControlBounds),
|
dirtyControlBounds(other.dirtyControlBounds),
|
||||||
|
dirtyRunLengths(other.dirtyRunLengths),
|
||||||
convex(other.convex),
|
convex(other.convex),
|
||||||
hasWindingFill(other.hasWindingFill)
|
hasWindingFill(other.hasWindingFill),
|
||||||
|
cacheEnabled(other.cacheEnabled)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,6 +155,10 @@ public:
|
|||||||
inline void close();
|
inline void close();
|
||||||
inline void maybeMoveTo();
|
inline void maybeMoveTo();
|
||||||
inline void clear();
|
inline void clear();
|
||||||
|
void computeRunLengths();
|
||||||
|
int elementAtT(qreal t);
|
||||||
|
QBezier bezierAtT(const QPainterPath &path, qreal t, qreal *startingLength,
|
||||||
|
qreal *bezierLength) const;
|
||||||
|
|
||||||
const QVectorPath &vectorPath() {
|
const QVectorPath &vectorPath() {
|
||||||
if (!pathConverter)
|
if (!pathConverter)
|
||||||
@ -159,6 +169,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
QList<QPainterPath::Element> elements;
|
QList<QPainterPath::Element> elements;
|
||||||
std::unique_ptr<QVectorPathConverter> pathConverter;
|
std::unique_ptr<QVectorPathConverter> pathConverter;
|
||||||
|
QList<qreal> m_runLengths;
|
||||||
QRectF bounds;
|
QRectF bounds;
|
||||||
QRectF controlBounds;
|
QRectF controlBounds;
|
||||||
|
|
||||||
@ -167,8 +178,10 @@ private:
|
|||||||
bool require_moveTo : 1;
|
bool require_moveTo : 1;
|
||||||
bool dirtyBounds : 1;
|
bool dirtyBounds : 1;
|
||||||
bool dirtyControlBounds : 1;
|
bool dirtyControlBounds : 1;
|
||||||
|
bool dirtyRunLengths : 1;
|
||||||
bool convex : 1;
|
bool convex : 1;
|
||||||
bool hasWindingFill : 1;
|
bool hasWindingFill : 1;
|
||||||
|
bool cacheEnabled : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QPainterPathStrokerPrivate
|
class QPainterPathStrokerPrivate
|
||||||
@ -257,6 +270,7 @@ inline void QPainterPathPrivate::clear()
|
|||||||
Q_ASSERT(ref.loadRelaxed() == 1);
|
Q_ASSERT(ref.loadRelaxed() == 1);
|
||||||
|
|
||||||
elements.clear();
|
elements.clear();
|
||||||
|
m_runLengths.clear();
|
||||||
|
|
||||||
cStart = 0;
|
cStart = 0;
|
||||||
bounds = {};
|
bounds = {};
|
||||||
@ -265,12 +279,23 @@ inline void QPainterPathPrivate::clear()
|
|||||||
require_moveTo = false;
|
require_moveTo = false;
|
||||||
dirtyBounds = false;
|
dirtyBounds = false;
|
||||||
dirtyControlBounds = false;
|
dirtyControlBounds = false;
|
||||||
|
dirtyRunLengths = false;
|
||||||
convex = false;
|
convex = false;
|
||||||
|
|
||||||
pathConverter.reset();
|
pathConverter.reset();
|
||||||
}
|
}
|
||||||
#define KAPPA qreal(0.5522847498)
|
|
||||||
|
|
||||||
|
inline int QPainterPathPrivate::elementAtT(qreal t)
|
||||||
|
{
|
||||||
|
Q_ASSERT(cacheEnabled);
|
||||||
|
if (dirtyRunLengths)
|
||||||
|
computeRunLengths();
|
||||||
|
qreal len = t * m_runLengths.constLast();
|
||||||
|
const auto it = std::lower_bound(m_runLengths.constBegin(), m_runLengths.constEnd(), len);
|
||||||
|
return (it == m_runLengths.constEnd()) ? m_runLengths.size() - 1 : int(it - m_runLengths.constBegin());
|
||||||
|
}
|
||||||
|
|
||||||
|
#define KAPPA qreal(0.5522847498)
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
@ -1145,10 +1145,16 @@ void tst_QPainterPath::pointAtPercent()
|
|||||||
QFETCH(qreal, percent);
|
QFETCH(qreal, percent);
|
||||||
QFETCH(QPointF, point);
|
QFETCH(QPointF, point);
|
||||||
|
|
||||||
|
QVERIFY(!path.isCachingEnabled());
|
||||||
QPointF result = path.pointAtPercent(percent);
|
QPointF result = path.pointAtPercent(percent);
|
||||||
|
|
||||||
QVERIFY(pathFuzzyCompare(point.x() , result.x()));
|
QVERIFY(pathFuzzyCompare(point.x() , result.x()));
|
||||||
QVERIFY(pathFuzzyCompare(point.y() , result.y()));
|
QVERIFY(pathFuzzyCompare(point.y() , result.y()));
|
||||||
|
|
||||||
|
path.setCachingEnabled(true);
|
||||||
|
QVERIFY(path.isCachingEnabled());
|
||||||
|
result = path.pointAtPercent(percent);
|
||||||
|
QVERIFY2(pathFuzzyCompare(point.x() , result.x()), "caching");
|
||||||
|
QVERIFY2(pathFuzzyCompare(point.y() , result.y()), "caching");
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QPainterPath::lengths_data()
|
void tst_QPainterPath::lengths_data()
|
||||||
@ -1190,11 +1196,20 @@ void tst_QPainterPath::lengths()
|
|||||||
QFETCH(qreal, lenAt50);
|
QFETCH(qreal, lenAt50);
|
||||||
QFETCH(qreal, lenAt75);
|
QFETCH(qreal, lenAt75);
|
||||||
|
|
||||||
|
QVERIFY(!path.isCachingEnabled());
|
||||||
QVERIFY(pathFuzzyCompare(path.length() / 1000, length / 1000));
|
QVERIFY(pathFuzzyCompare(path.length() / 1000, length / 1000));
|
||||||
QVERIFY(pathFuzzyCompare(path.percentAtLength(lenAt25), qreal(0.25)));
|
QVERIFY(pathFuzzyCompare(path.percentAtLength(lenAt25), qreal(0.25)));
|
||||||
QVERIFY(pathFuzzyCompare(path.percentAtLength(lenAt50), qreal(0.50)));
|
QVERIFY(pathFuzzyCompare(path.percentAtLength(lenAt50), qreal(0.50)));
|
||||||
QVERIFY(pathFuzzyCompare(path.percentAtLength(lenAt75), qreal(0.75)));
|
QVERIFY(pathFuzzyCompare(path.percentAtLength(lenAt75), qreal(0.75)));
|
||||||
QVERIFY(pathFuzzyCompare(path.percentAtLength(length), qreal(1)));
|
QVERIFY(pathFuzzyCompare(path.percentAtLength(length), qreal(1)));
|
||||||
|
|
||||||
|
path.setCachingEnabled(true);
|
||||||
|
QVERIFY(path.isCachingEnabled());
|
||||||
|
QVERIFY2(pathFuzzyCompare(path.length() / 1000, length / 1000), "caching");
|
||||||
|
QVERIFY2(pathFuzzyCompare(path.percentAtLength(lenAt25), qreal(0.25)), "caching");
|
||||||
|
QVERIFY2(pathFuzzyCompare(path.percentAtLength(lenAt50), qreal(0.50)), "caching");
|
||||||
|
QVERIFY2(pathFuzzyCompare(path.percentAtLength(lenAt75), qreal(0.75)), "caching");
|
||||||
|
QVERIFY2(pathFuzzyCompare(path.percentAtLength(length), qreal(1)), "caching");
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QPainterPath::setElementPositionAt()
|
void tst_QPainterPath::setElementPositionAt()
|
||||||
@ -1226,6 +1241,11 @@ void tst_QPainterPath::angleAtPercent()
|
|||||||
path.moveTo(line.p1());
|
path.moveTo(line.p1());
|
||||||
path.lineTo(line.p2());
|
path.lineTo(line.p2());
|
||||||
|
|
||||||
|
QVERIFY(!path.isCachingEnabled());
|
||||||
|
QCOMPARE(path.angleAtPercent(0.5), line.angle());
|
||||||
|
|
||||||
|
path.setCachingEnabled(true);
|
||||||
|
QVERIFY(path.isCachingEnabled());
|
||||||
QCOMPARE(path.angleAtPercent(0.5), line.angle());
|
QCOMPARE(path.angleAtPercent(0.5), line.angle());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,8 +15,12 @@ public:
|
|||||||
private slots:
|
private slots:
|
||||||
void initTestCase_data();
|
void initTestCase_data();
|
||||||
|
|
||||||
|
void general_data();
|
||||||
|
void length_data() { general_data(); }
|
||||||
void length();
|
void length();
|
||||||
|
void percentAtLength_data() { general_data(); }
|
||||||
void percentAtLength();
|
void percentAtLength();
|
||||||
|
void pointAtPercent_data() { general_data(); }
|
||||||
void pointAtPercent();
|
void pointAtPercent();
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -62,11 +66,19 @@ void tst_QPainterPath::initTestCase_data()
|
|||||||
QTest::newRow("2k_text") << p;
|
QTest::newRow("2k_text") << p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QPainterPath::general_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<bool>("caching");
|
||||||
|
|
||||||
|
QTest::newRow("Uncached") << false;
|
||||||
|
QTest::newRow("Cached") << true;
|
||||||
|
}
|
||||||
|
|
||||||
void tst_QPainterPath::length()
|
void tst_QPainterPath::length()
|
||||||
{
|
{
|
||||||
QFETCH_GLOBAL(QPainterPath, path);
|
QFETCH_GLOBAL(QPainterPath, path);
|
||||||
|
QFETCH(bool, caching);
|
||||||
//const qreal len = path.length() * 0.72;
|
path.setCachingEnabled(caching);
|
||||||
|
|
||||||
QBENCHMARK {
|
QBENCHMARK {
|
||||||
path.length();
|
path.length();
|
||||||
@ -76,6 +88,8 @@ void tst_QPainterPath::length()
|
|||||||
void tst_QPainterPath::percentAtLength()
|
void tst_QPainterPath::percentAtLength()
|
||||||
{
|
{
|
||||||
QFETCH_GLOBAL(QPainterPath, path);
|
QFETCH_GLOBAL(QPainterPath, path);
|
||||||
|
QFETCH(bool, caching);
|
||||||
|
path.setCachingEnabled(caching);
|
||||||
|
|
||||||
const qreal len = path.length() * 0.72;
|
const qreal len = path.length() * 0.72;
|
||||||
|
|
||||||
@ -87,6 +101,8 @@ void tst_QPainterPath::percentAtLength()
|
|||||||
void tst_QPainterPath::pointAtPercent()
|
void tst_QPainterPath::pointAtPercent()
|
||||||
{
|
{
|
||||||
QFETCH_GLOBAL(QPainterPath, path);
|
QFETCH_GLOBAL(QPainterPath, path);
|
||||||
|
QFETCH(bool, caching);
|
||||||
|
path.setCachingEnabled(caching);
|
||||||
|
|
||||||
const qreal t = 0.72;
|
const qreal t = 0.72;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user