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"