From ff7221c6770bd14518c24681f6cf5f690c67eb3f Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Thu, 29 Aug 2024 11:46:33 +0200 Subject: [PATCH] QPainterPath: Extend autotests for length and percentage functions Also add a benchmark test for them. Change-Id: Icc44f54786048550d0a96fd0d1acd3801eaca132 Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../qpainterpath/tst_qpainterpath.cpp | 81 ++++++++++++++- .../gui/painting/qpainterpath/CMakeLists.txt | 16 +++ .../qpainterpath/tst_bench_qpainterpath.cpp | 99 +++++++++++++++++++ 3 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 tests/benchmarks/gui/painting/qpainterpath/CMakeLists.txt create mode 100644 tests/benchmarks/gui/painting/qpainterpath/tst_bench_qpainterpath.cpp diff --git a/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp b/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp index c00dc3a78a5..cd343445490 100644 --- a/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp +++ b/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp @@ -55,7 +55,8 @@ private slots: void pointAtPercent_data(); void pointAtPercent(); - + void lengths_data(); + void lengths(); void angleAtPercent(); void arcWinding_data(); @@ -1105,6 +1106,37 @@ void tst_QPainterPath::pointAtPercent_data() path.moveTo(100, 100); QTest::newRow("Case 18") << path << qreal(0.0) << QPointF(100, 100); QTest::newRow("Case 19") << path << qreal(1.0) << QPointF(100, 100); + + path.clear(); + path.lineTo(100, 0); + path.moveTo(0, 100); + path.lineTo(100, 100); + QTest::newRow("Case 20") << path << qreal(0.25) << QPointF(50, 0); + QTest::newRow("Case 21") << path << qreal(0.5) << QPointF(100, 0); + QTest::newRow("Case 22") << path << qreal(0.75) << QPointF(50, 100); + QTest::newRow("Case 23") << path << qreal(1.0) << QPointF(100, 100); + + path.clear(); + path.moveTo(100, 100); + path.lineTo(0, 100); + path.moveTo(100, 0); + path.lineTo(0, 0); + QTest::newRow("Case 24") << path << qreal(0.25) << QPointF(50, 100); + QTest::newRow("Case 25") << path << qreal(0.5) << QPointF(0, 100); + QTest::newRow("Case 26") << path << qreal(0.75) << QPointF(50, 0); + QTest::newRow("Case 27") << path << qreal(1.0) << QPointF(0, 0); + + path.clear(); + path.lineTo(0, 100); + path.cubicTo(QPointF(5, 0), QPointF(90, 100), QPointF(100, 100)); + path.cubicTo(QPointF(80, 80), QPointF(80, 80), QPointF(100, 20)); + path.closeSubpath(); + path.addPath(path); + QTest::newRow("Case 28") << path << qreal(0.5) << QPointF(0, 0); + QTest::newRow("Case 29") << path << qreal(0.05) << path.pointAtPercent(0.5 + 0.05); + QTest::newRow("Case 30") << path << qreal(0.2) << path.pointAtPercent(0.5 + 0.2); + QTest::newRow("Case 31") << path << qreal(0.4) << path.pointAtPercent(0.5 + 0.4); + QTest::newRow("Case 32") << path << qreal(0.45) << path.pointAtPercent(0.5 + 0.45); } void tst_QPainterPath::pointAtPercent() @@ -1114,10 +1146,57 @@ void tst_QPainterPath::pointAtPercent() QFETCH(QPointF, point); QPointF result = path.pointAtPercent(percent); + QVERIFY(pathFuzzyCompare(point.x() , result.x())); QVERIFY(pathFuzzyCompare(point.y() , result.y())); } +void tst_QPainterPath::lengths_data() +{ + QTest::addColumn("path"); + QTest::addColumn("length"); + QTest::addColumn("lenAt25"); + QTest::addColumn("lenAt50"); + QTest::addColumn("lenAt75"); + + QPainterPath p; + p.addRect(50, 50, 200, 100); + qreal len = 2 * 200 + 2 * 100; + QTest::newRow("rect") << p << len << len * 0.25 << len * 0.5 << len * 0.75; + + p.clear(); + p.addEllipse(50, 50, 100, 100); + len = M_PI * 100; + QTest::newRow("circle") << p << len << len * 0.25 << len * 0.5 << len * 0.75; + + p.addEllipse(60, 60, 100, 100); + p.addEllipse(70, 70, 100, 100); + len *= 3; + QTest::newRow("three_circles") << p << len << len * 0.25 << len * 0.5 << len * 0.75; + + p.clear(); + p.lineTo(0, 100); + p.cubicTo(QPointF(5, 0), QPointF(90, 100), QPointF(100, 100)); + p.cubicTo(QPointF(80, 80), QPointF(80, 80), QPointF(100, 20)); + len = 332.113; + QTest::newRow("asymmetric") << p << len << len * 0.25 << 173.85 << 248.77; +} + +void tst_QPainterPath::lengths() +{ + QFETCH(QPainterPath, path); + QFETCH(qreal, length); + QFETCH(qreal, lenAt25); + QFETCH(qreal, lenAt50); + QFETCH(qreal, lenAt75); + + QVERIFY(pathFuzzyCompare(path.length() / 1000, length / 1000)); + QVERIFY(pathFuzzyCompare(path.percentAtLength(lenAt25), qreal(0.25))); + QVERIFY(pathFuzzyCompare(path.percentAtLength(lenAt50), qreal(0.50))); + QVERIFY(pathFuzzyCompare(path.percentAtLength(lenAt75), qreal(0.75))); + QVERIFY(pathFuzzyCompare(path.percentAtLength(length), qreal(1))); +} + void tst_QPainterPath::setElementPositionAt() { QPainterPath path(QPointF(42., 42.)); diff --git a/tests/benchmarks/gui/painting/qpainterpath/CMakeLists.txt b/tests/benchmarks/gui/painting/qpainterpath/CMakeLists.txt new file mode 100644 index 00000000000..31cdaedd315 --- /dev/null +++ b/tests/benchmarks/gui/painting/qpainterpath/CMakeLists.txt @@ -0,0 +1,16 @@ +# Copyright (C) 2025 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_bench_qpainterpath LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_benchmark(tst_bench_qpainterpath + SOURCES + tst_bench_qpainterpath.cpp + LIBRARIES + Qt::Gui + Qt::Test +) diff --git a/tests/benchmarks/gui/painting/qpainterpath/tst_bench_qpainterpath.cpp b/tests/benchmarks/gui/painting/qpainterpath/tst_bench_qpainterpath.cpp new file mode 100644 index 00000000000..ab861d63585 --- /dev/null +++ b/tests/benchmarks/gui/painting/qpainterpath/tst_bench_qpainterpath.cpp @@ -0,0 +1,99 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include +#include +#include + +class tst_QPainterPath : public QObject +{ + Q_OBJECT + +public: + tst_QPainterPath(); + +private slots: + void initTestCase_data(); + + void length(); + void percentAtLength(); + void pointAtPercent(); + +}; + +tst_QPainterPath::tst_QPainterPath() +{ +} + +void tst_QPainterPath::initTestCase_data() +{ + QTest::addColumn("path"); + + QPainterPath p; + QTest::newRow("null") << p; + + p.moveTo(100, 100); + QTest::newRow("only_move") << p; + + p.lineTo(0, 0); + QTest::newRow("single_line") << p; + + p.clear(); + p.cubicTo(QPointF(100, 25), QPointF(0, 75), QPointF(100, 100)); + QTest::newRow("single_curve") << p; + + p.clear(); + for (int i = 0; i < 10; i++) + p.addRect(i * 10, i * 10, 100, 100); + QTest::newRow("40_lines") << p; + + p.clear(); + for (int i = 0; i < 10; i++) + p.addEllipse(i * 10, i * 10, 100, 100); + QTest::newRow("40_curves") << p; + + p.clear(); + for (int i = 0; i < 10; i++) + p.addRoundedRect(QRectF(i * 10, i * 10, 100, 100), 10, 20); + QTest::newRow("80_mixed") << p; + + p.clear(); + p.addText(QPoint(), QFont(), "Dommarane skal velja det som er best for domfelte."); + QTest::newRow("2k_text") << p; +} + +void tst_QPainterPath::length() +{ + QFETCH_GLOBAL(QPainterPath, path); + + //const qreal len = path.length() * 0.72; + + QBENCHMARK { + path.length(); + } +} + +void tst_QPainterPath::percentAtLength() +{ + QFETCH_GLOBAL(QPainterPath, path); + + const qreal len = path.length() * 0.72; + + QBENCHMARK { + path.percentAtLength(len); + } +} + +void tst_QPainterPath::pointAtPercent() +{ + QFETCH_GLOBAL(QPainterPath, path); + + const qreal t = 0.72; + + QBENCHMARK { + path.pointAtPercent(t); + } +} + +QTEST_MAIN(tst_QPainterPath) +#include "tst_bench_qpainterpath.moc"