File indexing completed on 2024-05-05 04:35:20

0001 // This file is part of Washi Pad
0002 // SPDX-FileCopyrightText: 2018 Kevin Ottens <ervin@kde.org>
0003 // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004 
0005 #include <QtTest>
0006 
0007 #include <memory>
0008 
0009 #include "sketchmodel.h"
0010 
0011 class SketchModelTest : public QObject
0012 {
0013     Q_OBJECT
0014 private slots:
0015     void shouldHaveDefaultState()
0016     {
0017         // GIVEN
0018         const auto model = std::make_unique<SketchModel>();
0019 
0020         // THEN
0021         QVERIFY(model->strokes(Stroke::Type::Fill).isEmpty());
0022         QVERIFY(model->strokes(Stroke::Type::Outline).isEmpty());
0023     }
0024 
0025     void shouldAddStrokes()
0026     {
0027         // GIVEN
0028         const auto model = std::make_unique<SketchModel>();
0029         const auto fillStroke1 = [] {
0030             auto stroke = Stroke{};
0031             stroke.setType(Stroke::Type::Fill);
0032             stroke.setColor(Qt::green);
0033             return stroke;
0034         }();
0035         const auto fillStroke2 = [] {
0036             auto stroke = Stroke{};
0037             stroke.setType(Stroke::Type::Fill);
0038             stroke.setColor(Qt::blue);
0039             return stroke;
0040         }();
0041         const auto outlineStroke1 = [] {
0042             auto stroke = Stroke{};
0043             stroke.setType(Stroke::Type::Outline);
0044             stroke.setColor(Qt::cyan);
0045             return stroke;
0046         }();
0047         const auto outlineStroke2 = [] {
0048             auto stroke = Stroke{};
0049             stroke.setType(Stroke::Type::Outline);
0050             stroke.setColor(Qt::magenta);
0051             return stroke;
0052         }();
0053 
0054         // WHEN
0055         model->addStroke(fillStroke1);
0056         model->addStroke(outlineStroke1);
0057         model->addStroke(outlineStroke2);
0058         model->addStroke(fillStroke2);
0059 
0060         // THEN
0061         QCOMPARE(model->strokes(Stroke::Type::Fill).size(), 2);
0062         QCOMPARE(model->strokes(Stroke::Type::Fill).at(0).type(), Stroke::Type::Fill);
0063         QCOMPARE(model->strokes(Stroke::Type::Fill).at(0).color(), fillStroke1.color());
0064         QCOMPARE(model->strokes(Stroke::Type::Fill).at(1).type(), Stroke::Type::Fill);
0065         QCOMPARE(model->strokes(Stroke::Type::Fill).at(1).color(), fillStroke2.color());
0066 
0067         QCOMPARE(model->strokes(Stroke::Type::Outline).size(), 2);
0068         QCOMPARE(model->strokes(Stroke::Type::Outline).at(0).type(), Stroke::Type::Outline);
0069         QCOMPARE(model->strokes(Stroke::Type::Outline).at(0).color(), outlineStroke1.color());
0070         QCOMPARE(model->strokes(Stroke::Type::Outline).at(1).type(), Stroke::Type::Outline);
0071         QCOMPARE(model->strokes(Stroke::Type::Outline).at(1).color(), outlineStroke2.color());
0072 
0073         QCOMPARE(model->strokes().size(), 4);
0074         QCOMPARE(model->strokes().at(0).type(), Stroke::Type::Fill);
0075         QCOMPARE(model->strokes().at(0).color(), fillStroke1.color());
0076         QCOMPARE(model->strokes().at(1).type(), Stroke::Type::Fill);
0077         QCOMPARE(model->strokes().at(1).color(), fillStroke2.color());
0078         QCOMPARE(model->strokes().at(2).type(), Stroke::Type::Outline);
0079         QCOMPARE(model->strokes().at(2).color(), outlineStroke1.color());
0080         QCOMPARE(model->strokes().at(3).type(), Stroke::Type::Outline);
0081         QCOMPARE(model->strokes().at(3).color(), outlineStroke2.color());
0082     }
0083 
0084 
0085     void shouldEraseAreas_data()
0086     {
0087         QTest::addColumn<Stroke>("input");
0088         QTest::addColumn<Stroke::Type>("inputType");
0089         QTest::addColumn<Stroke::Type>("otherType");
0090         QTest::addColumn<QVector2D>("center");
0091         QTest::addColumn<float>("radius");
0092         QTest::addColumn<QVector<QVector<StrokeSample>>>("expectedSamples");
0093 
0094         auto straightLine = [] {
0095             auto stroke = Stroke{};
0096             stroke.setType(Stroke::Type::Outline);
0097             stroke.setColor(Qt::blue);
0098             stroke.addSample({{0.0f, 0.0f}, 0.5f});
0099             stroke.addSample({{0.125f, 0.125f}, 0.5f});
0100             stroke.addSample({{0.25f, 0.25f}, 0.5f});
0101             stroke.addSample({{0.375f, 0.375f}, 0.5f});
0102             stroke.addSample({{0.5f, 0.5f}, 0.5f});
0103             stroke.addSample({{0.625f, 0.625f}, 0.5f});
0104             stroke.addSample({{0.75f, 0.75f}, 0.5f});
0105             stroke.addSample({{0.875f, 0.875f}, 0.5f});
0106             stroke.addSample({{1.0f, 1.0f}, 0.5f});
0107             return stroke;
0108         }();
0109 
0110         QTest::newRow("straight outline, no hit")
0111                 << straightLine << straightLine.type() << Stroke::Type::Fill
0112                 << QVector2D{-1.0f, -1.0f} << 0.5f
0113                 << QVector<QVector<StrokeSample>>{straightLine.samples()};
0114 
0115         QTest::newRow("straight outline, all hits")
0116                 << straightLine << straightLine.type() << Stroke::Type::Fill
0117                 << QVector2D{0.5f, 0.5f} << 1.5f
0118                 << QVector<QVector<StrokeSample>>{};
0119 
0120         QTest::newRow("straight outline, begin hits with isolated sample")
0121                 << straightLine << straightLine.type() << Stroke::Type::Fill
0122                 << QVector2D{0.1875f, 0.1875f} << 0.125f
0123                 << QVector<QVector<StrokeSample>>{
0124                        {{{0.375f, 0.375f}, 0.5f}, {{0.5f, 0.5f}, 0.5f},
0125                         {{0.625f, 0.625f}, 0.5f}, {{0.75f, 0.75f}, 0.5f},
0126                         {{0.875f, 0.875f}, 0.5f}, {{1.0f, 1.0f}, 0.5f}}
0127                    };
0128 
0129         QTest::newRow("straight outline, begin hits")
0130                 << straightLine << straightLine.type() << Stroke::Type::Fill
0131                 << QVector2D{0.0f, 0.0f} << 0.25f
0132                 << QVector<QVector<StrokeSample>>{
0133                        {{{0.25f, 0.25f}, 0.5f}, {{0.375f, 0.375f}, 0.5f},
0134                         {{0.5f, 0.5f}, 0.5f}, {{0.625f, 0.625f}, 0.5f},
0135                         {{0.75f, 0.75f}, 0.5f}, {{0.875f, 0.875f}, 0.5f},
0136                         {{1.0f, 1.0f}, 0.5f}}
0137                    };
0138 
0139         QTest::newRow("straight outline, middle hits")
0140                 << straightLine << straightLine.type() << Stroke::Type::Fill
0141                 << QVector2D{0.375f, 0.375f} << 0.2f
0142                 << QVector<QVector<StrokeSample>>{
0143                        {{{0.0f, 0.0f}, 0.5f}, {{0.125f, 0.125f}, 0.5f}},
0144                        {{{0.625f, 0.625f}, 0.5f}, {{0.75f, 0.75f}, 0.5f}, {{0.875f, 0.875f}, 0.5f}, {{1.0f, 1.0f}, 0.5f}}
0145                    };
0146 
0147         QTest::newRow("straight outline, end hits")
0148                 << straightLine << straightLine.type() << Stroke::Type::Fill
0149                 << QVector2D{1.0f, 1.0f} << 0.25f
0150                 << QVector<QVector<StrokeSample>>{
0151                        {{{0.0f, 0.0f}, 0.5f}, {{0.125f, 0.125f}, 0.5f},
0152                         {{0.25f, 0.25f}, 0.5f}, {{0.375f, 0.375f}, 0.5f},
0153                         {{0.5f, 0.5f}, 0.5f}, {{0.625f, 0.625f}, 0.5f},
0154                         {{0.75f, 0.75f}, 0.5f}}
0155                    };
0156 
0157 
0158         straightLine.setType(Stroke::Type::Fill);
0159 
0160         QTest::newRow("straight fill, no hit")
0161                 << straightLine << straightLine.type() << Stroke::Type::Outline
0162                 << QVector2D{-1.0f, -1.0f} << 0.5f
0163                 << QVector<QVector<StrokeSample>>{straightLine.samples()};
0164 
0165         QTest::newRow("straight fill, all hits")
0166                 << straightLine << straightLine.type() << Stroke::Type::Outline
0167                 << QVector2D{0.5f, 0.5f} << 1.5f
0168                 << QVector<QVector<StrokeSample>>{};
0169 
0170         QTest::newRow("straight fill, begin hits with isolated sample")
0171                 << straightLine << straightLine.type() << Stroke::Type::Outline
0172                 << QVector2D{0.1875f, 0.1875f} << 0.125f
0173                 << QVector<QVector<StrokeSample>>{
0174                        {{{0.375f, 0.375f}, 0.5f}, {{0.5f, 0.5f}, 0.5f},
0175                         {{0.625f, 0.625f}, 0.5f}, {{0.75f, 0.75f}, 0.5f},
0176                         {{0.875f, 0.875f}, 0.5f}, {{1.0f, 1.0f}, 0.5f}}
0177                    };
0178 
0179         QTest::newRow("straight fill, begin hits")
0180                 << straightLine << straightLine.type() << Stroke::Type::Outline
0181                 << QVector2D{0.0f, 0.0f} << 0.25f
0182                 << QVector<QVector<StrokeSample>>{
0183                        {{{0.25f, 0.25f}, 0.5f}, {{0.375f, 0.375f}, 0.5f},
0184                         {{0.5f, 0.5f}, 0.5f}, {{0.625f, 0.625f}, 0.5f},
0185                         {{0.75f, 0.75f}, 0.5f}, {{0.875f, 0.875f}, 0.5f},
0186                         {{1.0f, 1.0f}, 0.5f}}
0187                    };
0188 
0189         QTest::newRow("straight fill, middle hits")
0190                 << straightLine << straightLine.type() << Stroke::Type::Outline
0191                 << QVector2D{0.375f, 0.375f} << 0.2f
0192                 << QVector<QVector<StrokeSample>>{
0193                        {{{0.0f, 0.0f}, 0.5f}, {{0.125f, 0.125f}, 0.5f}},
0194                        {{{0.625f, 0.625f}, 0.5f}, {{0.75f, 0.75f}, 0.5f}, {{0.875f, 0.875f}, 0.5f}, {{1.0f, 1.0f}, 0.5f}}
0195                    };
0196 
0197         QTest::newRow("straight fill, end hits")
0198                 << straightLine << straightLine.type() << Stroke::Type::Outline
0199                 << QVector2D{1.0f, 1.0f} << 0.25f
0200                 << QVector<QVector<StrokeSample>>{
0201                        {{{0.0f, 0.0f}, 0.5f}, {{0.125f, 0.125f}, 0.5f},
0202                         {{0.25f, 0.25f}, 0.5f}, {{0.375f, 0.375f}, 0.5f},
0203                         {{0.5f, 0.5f}, 0.5f}, {{0.625f, 0.625f}, 0.5f},
0204                         {{0.75f, 0.75f}, 0.5f}}
0205                    };
0206 
0207 
0208         auto complexLine = [] {
0209             auto stroke = Stroke{};
0210             stroke.setType(Stroke::Type::Outline);
0211             stroke.setColor(Qt::red);
0212             stroke.addSample({{0.0f, 0.0f}, 0.5f});
0213             stroke.addSample({{0.125f, 0.125f}, 0.5f});
0214             stroke.addSample({{0.25f, 0.25f}, 0.5f});
0215             stroke.addSample({{0.375f, 0.25f}, 0.5f});
0216             stroke.addSample({{0.5f, 0.125f}, 0.5f});
0217             stroke.addSample({{0.625f, 0.125f}, 0.5f});
0218             stroke.addSample({{0.75f, 0.25f}, 0.5f});
0219             stroke.addSample({{0.875f, 0.375f}, 0.5f});
0220             stroke.addSample({{1.0f, 0.25f}, 0.5f});
0221             stroke.addSample({{1.125f, 0.125f}, 0.5f});
0222             return stroke;
0223         }();
0224 
0225         QTest::newRow("complex outline, multiple hits")
0226                 << complexLine << complexLine.type() << Stroke::Type::Fill
0227                 << QVector2D{0.5625f, 0.4375f} << 0.27f
0228                 << QVector<QVector<StrokeSample>>{
0229                        {{{0.0f, 0.0f}, 0.5f}, {{0.125f, 0.125f}, 0.5f}, {{0.25f, 0.25f}, 0.5f}},
0230                        {{{0.5f, 0.125f}, 0.5f}, {{0.625f, 0.125f}, 0.5f}},
0231                        {{{0.875f, 0.375f}, 0.5f}, {{1.0f, 0.25f}, 0.5f}, {{1.125f, 0.125f}, 0.5f}}
0232                    };
0233 
0234         complexLine.setType(Stroke::Type::Fill);
0235 
0236         QTest::newRow("complex fill, multiple hits")
0237                 << complexLine << complexLine.type() << Stroke::Type::Outline
0238                 << QVector2D{0.5625f, 0.4375f} << 0.27f
0239                 << QVector<QVector<StrokeSample>>{
0240                        {{{0.0f, 0.0f}, 0.5f}, {{0.125f, 0.125f}, 0.5f}, {{0.25f, 0.25f}, 0.5f}},
0241                        {{{0.5f, 0.125f}, 0.5f}, {{0.625f, 0.125f}, 0.5f}},
0242                        {{{0.875f, 0.375f}, 0.5f}, {{1.0f, 0.25f}, 0.5f}, {{1.125f, 0.125f}, 0.5f}}
0243                    };
0244     }
0245 
0246     void shouldEraseAreas()
0247     {
0248         // GIVEN
0249         QFETCH(Stroke, input);
0250         QFETCH(Stroke::Type, inputType);
0251         QFETCH(Stroke::Type, otherType);
0252         QFETCH(QVector2D, center);
0253         QFETCH(float, radius);
0254 
0255         const auto model = std::make_unique<SketchModel>();
0256         model->addStroke([=] {
0257             auto stroke = Stroke{};
0258             stroke.setType(inputType);
0259             stroke.addSample({{-10.0f, -10.0f}, 0.5f});
0260             stroke.addSample({{-11.0f, -11.0f}, 0.5f});
0261             return stroke;
0262         }());
0263 
0264         model->addStroke(input);
0265 
0266         model->addStroke([=] {
0267             auto stroke = Stroke{};
0268             stroke.setType(inputType);
0269             stroke.addSample({{10.0f, 10.0f}, 0.5f});
0270             stroke.addSample({{11.0f, 11.0f}, 0.5f});
0271             return stroke;
0272         }());
0273 
0274         model->addStroke([=] {
0275             auto stroke = Stroke{};
0276             stroke.setType(otherType);
0277             stroke.addSample({center, 0.5f});
0278             stroke.addSample({{center.x() + radius / 2.0f, center.y()}, 0.5f});
0279             return stroke;
0280         }());
0281 
0282         // WHEN
0283         model->eraseArea(inputType, center, radius);
0284 
0285         // THEN
0286         QCOMPARE(model->strokes(otherType).size(), 1);
0287 
0288         QFETCH(QVector<QVector<StrokeSample>>, expectedSamples);
0289         QCOMPARE(model->strokes(inputType).size(), expectedSamples.size() + 2);
0290         for (int i = 0; i < expectedSamples.size(); i++) {
0291             const auto stroke = model->strokes(inputType).at(i + 1);
0292             QCOMPARE(stroke.type(), input.type());
0293             QCOMPARE(stroke.color(), input.color());
0294             QCOMPARE(stroke.samples(), expectedSamples.at(i));
0295         }
0296     }
0297 };
0298 
0299 QTEST_APPLESS_MAIN(SketchModelTest)
0300 
0301 #include "sketchmodeltest.moc"