File indexing completed on 2024-05-19 15:26:47
0001 /* 0002 * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best> 0003 * 0004 * SPDX-License-Identifier: GPL-3.0-or-later 0005 */ 0006 0007 #include <QtTest/QtTest> 0008 0009 #include <vector> 0010 #include <cstring> 0011 #include "io/aep/gradient_xml.hpp" 0012 0013 using namespace glaxnimate::io::aep; 0014 0015 0016 #define COS_VALUE(val, type_index, expected) \ 0017 QCOMPARE(val.type(), CosValue::Index::type_index); \ 0018 QCOMPARE(val.get<CosValue::Index::type_index>(), (expected)); 0019 0020 0021 class TestCase: public QObject 0022 { 0023 Q_OBJECT 0024 0025 void compare(QString error) 0026 { 0027 QCOMPARE(error, "0:0: "); 0028 } 0029 0030 QDomDocument xml(QString xml, int local_line = 0) 0031 { 0032 QDomDocument dom; 0033 QString error; 0034 int line = 0, col = 0; 0035 dom.setContent(xml.trimmed(), false, &error, &line, &col); 0036 if ( error != "" ) 0037 { 0038 auto msg = QString("%1:%2: %3").arg(line).arg(col).arg(error); 0039 auto lines = xml.split("\n"); 0040 int li = line - 1; 0041 if ( li >= 0 && li < lines.size() ) 0042 { 0043 msg += "\n" + lines[li]; 0044 msg += "\n" + QString(col-2, ' ') + '^'; 0045 } 0046 std::string stdmsg = msg.toStdString(); 0047 QTest::qFail(stdmsg.c_str(), line == 0 ? "xml" : __FILE__, line + local_line); 0048 } 0049 return dom; 0050 } 0051 0052 QDomElement element(QString xml, int local_line = 0) 0053 { 0054 return this->xml(xml, local_line).documentElement(); 0055 } 0056 0057 #define Element(xml) element(xml, __LINE__) 0058 0059 0060 private Q_SLOTS: 0061 void test_xml_value_scalar() 0062 { 0063 COS_VALUE(xml_value(Element("<float>2.5</float>")), Number, 2.5); 0064 COS_VALUE(xml_value(Element("<int>25</int>")), Number, 25); 0065 COS_VALUE(xml_value(Element("<string>2.5</string>")), String, "2.5"); 0066 } 0067 0068 void test_xml_array() 0069 { 0070 auto arr = xml_array(Element(R"( 0071 <array> 0072 <array.type> 0073 <int/> 0074 </array.type> 0075 <int>1</int> 0076 <int>2</int> 0077 <int>3</int> 0078 </array> 0079 )")); 0080 QCOMPARE(arr->size(), 3); 0081 COS_VALUE(arr->at(0), Number, 1); 0082 COS_VALUE(get_value(arr, 1), Number, 2); 0083 COS_VALUE(get_value(arr, 2), Number, 3); 0084 0085 CosValue val(std::move(arr)); 0086 COS_VALUE(get(val, 0), Number, 1); 0087 COS_VALUE(get_value(val, 1), Number, 2); 0088 COS_VALUE(get(val, 2), Number, 3); 0089 } 0090 0091 void test_xml_list() 0092 { 0093 0094 auto list = xml_list(Element(R"( 0095 <prop.list> 0096 <prop.pair><key>a</key><int>1</int></prop.pair> 0097 <prop.pair><key>b</key><int>2</int></prop.pair> 0098 <prop.pair><key>c</key><int>3</int></prop.pair> 0099 <prop.pair><key>d</key><int>4</int></prop.pair> 0100 </prop.list> 0101 )")); 0102 QCOMPARE(list->size(), 4); 0103 COS_VALUE(list->at("a"), Number, 1); 0104 COS_VALUE(list->at("b"), Number, 2); 0105 COS_VALUE(get_value(list, "c"), Number, 3); 0106 COS_VALUE(get_value(list, "d"), Number, 4); 0107 0108 CosValue list_val(std::move(list)); 0109 COS_VALUE(get(list_val, "a"), Number, 1); 0110 COS_VALUE(get_value(list_val, "b"), Number, 2); 0111 COS_VALUE(get(list_val, "c"), Number, 3); 0112 COS_VALUE(get_value(list_val, "d"), Number, 4); 0113 } 0114 0115 void test_xml_value_array() 0116 { 0117 auto val = xml_value(Element(R"( 0118 <array> 0119 <array.type> 0120 <int/> 0121 </array.type> 0122 <int>1</int> 0123 <int>2</int> 0124 <int>3</int> 0125 </array> 0126 )")); 0127 0128 QCOMPARE(val.type(), CosValue::Index::Array); 0129 COS_VALUE(get(val, 0), Number, 1); 0130 COS_VALUE(get_value(val, 1), Number, 2); 0131 COS_VALUE(get(val, 2), Number, 3); 0132 } 0133 0134 void test_xml_value_list() 0135 { 0136 auto list = xml_value(Element(R"( 0137 <prop.list> 0138 <prop.pair><key>a</key><int>1</int></prop.pair> 0139 <prop.pair><key>b</key><int>2</int></prop.pair> 0140 <prop.pair><key>c</key><int>3</int></prop.pair> 0141 <prop.pair><key>d</key><int>4</int></prop.pair> 0142 </prop.list> 0143 )")); 0144 QCOMPARE(list.type(), CosValue::Index::Object); 0145 COS_VALUE(get(list, "a"), Number, 1); 0146 COS_VALUE(get_value(list, "b"), Number, 2); 0147 COS_VALUE(get(list, "c"), Number, 3); 0148 COS_VALUE(get_value(list, "d"), Number, 4); 0149 } 0150 0151 void test_xml_value_map() 0152 { 0153 auto val = xml_value(Element(R"( 0154 <prop.map> 0155 <prop.list> 0156 <prop.pair> 0157 <key>array</key> 0158 <array> 0159 <array.type> 0160 <int/> 0161 </array.type> 0162 <int>1</int> 0163 <int>2</int> 0164 <int>3</int> 0165 </array> 0166 </prop.pair> 0167 <prop.pair> 0168 <key>foo</key> 0169 <prop.list> 0170 <prop.pair> 0171 <key>bar</key> 0172 <prop.list> 0173 <prop.pair> 0174 <key>array</key> 0175 <array> 0176 <array.type> 0177 <int/> 0178 </array.type> 0179 <int>1</int> 0180 <int>2</int> 0181 <int>3</int> 0182 </array> 0183 </prop.pair> 0184 </prop.list> 0185 </prop.pair> 0186 </prop.list> 0187 </prop.pair> 0188 </prop.list> 0189 </prop.map> 0190 )")); 0191 QCOMPARE(val.type(), CosValue::Index::Object); 0192 COS_VALUE(get(val, "array", 1), Number, 2); 0193 COS_VALUE(get(val, "foo", "bar", "array", 2), Number, 3); 0194 } 0195 0196 void test_gradient_structure() 0197 { 0198 auto val = xml_value(Element(R"( 0199 <?xml version='1.0'?> 0200 <prop.map version='4'> 0201 <prop.list> 0202 <prop.pair> 0203 <key>Gradient Color Data</key> 0204 <prop.list> 0205 <prop.pair> 0206 <key>Alpha Stops</key> 0207 <prop.list> 0208 <prop.pair> 0209 <key>Stops List</key> 0210 <prop.list> 0211 <prop.pair> 0212 <key>Stop-0</key> 0213 <prop.list> 0214 <prop.pair> 0215 <key>Stops Alpha</key> 0216 <array> 0217 <array.type> 0218 <float/> 0219 </array.type> 0220 <float>0</float> 0221 <float>0.5</float> 0222 <float>1</float> 0223 </array> 0224 </prop.pair> 0225 </prop.list> 0226 </prop.pair> 0227 <prop.pair> 0228 <key>Stop-1</key> 0229 <prop.list> 0230 <prop.pair> 0231 <key>Stops Alpha</key> 0232 <array> 0233 <array.type> 0234 <float/> 0235 </array.type> 0236 <float>1</float> 0237 <float>0.5</float> 0238 <float>0</float> 0239 </array> 0240 </prop.pair> 0241 </prop.list> 0242 </prop.pair> 0243 </prop.list> 0244 </prop.pair> 0245 <prop.pair> 0246 <key>Stops Size</key> 0247 <int type='unsigned' size='32'>2</int> 0248 </prop.pair> 0249 </prop.list> 0250 </prop.pair> 0251 <prop.pair> 0252 <key>Color Stops</key> 0253 <prop.list> 0254 <prop.pair> 0255 <key>Stops List</key> 0256 <prop.list> 0257 <prop.pair> 0258 <key>Stop-0</key> 0259 <prop.list> 0260 <prop.pair> 0261 <key>Stops Color</key> 0262 <array> 0263 <array.type> 0264 <float/> 0265 </array.type> 0266 <float>0</float> 0267 <float>0.5</float> 0268 <float>1</float> 0269 <float>0</float> 0270 <float>0</float> 0271 <float>1</float> 0272 </array> 0273 </prop.pair> 0274 </prop.list> 0275 </prop.pair> 0276 <prop.pair> 0277 <key>Stop-1</key> 0278 <prop.list> 0279 <prop.pair> 0280 <key>Stops Color</key> 0281 <array> 0282 <array.type> 0283 <float/> 0284 </array.type> 0285 <float>1</float> 0286 <float>0.5</float> 0287 <float>0</float> 0288 <float>1</float> 0289 <float>0</float> 0290 <float>1</float> 0291 </array> 0292 </prop.pair> 0293 </prop.list> 0294 </prop.pair> 0295 </prop.list> 0296 </prop.pair> 0297 <prop.pair> 0298 <key>Stops Size</key> 0299 <int type='unsigned' size='32'>2</int> 0300 </prop.pair> 0301 </prop.list> 0302 </prop.pair> 0303 </prop.list> 0304 </prop.pair> 0305 <prop.pair> 0306 <key>Gradient Colors</key> 0307 <string>1.0</string> 0308 </prop.pair> 0309 </prop.list> 0310 </prop.map> 0311 )")); 0312 0313 QCOMPARE(int(val.type()), int(CosValue::Index::Object)); 0314 COS_VALUE(get(val, "Gradient Colors"), String, "1.0"); 0315 COS_VALUE(get(val, "Gradient Color Data", "Alpha Stops", "Stops List", "Stop-0", "Stops Alpha", 1), Number, 0.5); 0316 auto& data = get(val, "Gradient Color Data"); 0317 QCOMPARE(int(data.type()), int(CosValue::Index::Object)); 0318 } 0319 0320 void test_get_gradient_stops_color() 0321 { 0322 auto data = xml_value(Element(R"( 0323 <prop.list> 0324 <prop.pair> 0325 <key>Color Stops</key> 0326 <prop.list> 0327 <prop.pair> 0328 <key>Stops List</key> 0329 <prop.list> 0330 <prop.pair> 0331 <key>Stop-0</key> 0332 <prop.list> 0333 <prop.pair> 0334 <key>Stops Color</key> 0335 <array> 0336 <array.type> 0337 <float/> 0338 </array.type> 0339 <float>0.4</float> 0340 <float>0.5</float> 0341 <float>0.1</float> 0342 <float>0.2</float> 0343 <float>0.3</float> 0344 <float>0.23</float> 0345 </array> 0346 </prop.pair> 0347 </prop.list> 0348 </prop.pair> 0349 <prop.pair> 0350 <key>Stop-1</key> 0351 <prop.list> 0352 <prop.pair> 0353 <key>Stops Color</key> 0354 <array> 0355 <array.type> 0356 <float/> 0357 </array.type> 0358 <float>0.6</float> 0359 <float>0.5</float> 0360 <float>0.7</float> 0361 <float>0.8</float> 0362 <float>0.9</float> 0363 <float>0.34</float> 0364 </array> 0365 </prop.pair> 0366 </prop.list> 0367 </prop.pair> 0368 </prop.list> 0369 </prop.pair> 0370 <prop.pair> 0371 <key>Stops Size</key> 0372 <int type='unsigned' size='32'>2</int> 0373 </prop.pair> 0374 </prop.list> 0375 </prop.pair> 0376 </prop.list> 0377 )")); 0378 0379 QCOMPARE(int(data.type()), int(CosValue::Index::Object)); 0380 QCOMPARE(int(get(data, "Color Stops").type()), int(CosValue::Index::Object)); 0381 QCOMPARE(int(get(data, "Color Stops", "Stops List").type()), int(CosValue::Index::Object)); 0382 auto& stop = get_as<CosValue::Index::Object>(data, "Color Stops", "Stops List", "Stop-0"); 0383 auto& color_arr = get_as<CosValue::Index::Array>(stop, "Stops Color"); 0384 COS_VALUE(get(color_arr, 0), Number, 0.4); 0385 auto stops = get_gradient_stops<GradientStopColor>(data); 0386 QCOMPARE(stops.size(), 2); 0387 QCOMPARE(stops[0].offset, 0.4); 0388 QCOMPARE(stops[0].value, QColor::fromRgbF(0.1, 0.2, 0.3)); 0389 } 0390 0391 void test_get_gradient_stops_alpha() 0392 { 0393 auto data = xml_value(Element(R"( 0394 <prop.list> 0395 <prop.pair> 0396 <key>Alpha Stops</key> 0397 <prop.list> 0398 <prop.pair> 0399 <key>Stops List</key> 0400 <prop.list> 0401 <prop.pair> 0402 <key>Stop-0</key> 0403 <prop.list> 0404 <prop.pair> 0405 <key>Stops Alpha</key> 0406 <array> 0407 <array.type> 0408 <float/> 0409 </array.type> 0410 <float>0</float> 0411 <float>0.5</float> 0412 <float>0.6</float> 0413 </array> 0414 </prop.pair> 0415 </prop.list> 0416 </prop.pair> 0417 <prop.pair> 0418 <key>Stop-1</key> 0419 <prop.list> 0420 <prop.pair> 0421 <key>Stops Alpha</key> 0422 <array> 0423 <array.type> 0424 <float/> 0425 </array.type> 0426 <float>1</float> 0427 <float>0.5</float> 0428 <float>0.5</float> 0429 </array> 0430 </prop.pair> 0431 </prop.list> 0432 </prop.pair> 0433 </prop.list> 0434 </prop.pair> 0435 <prop.pair> 0436 <key>Stops Size</key> 0437 <int type='unsigned' size='32'>2</int> 0438 </prop.pair> 0439 </prop.list> 0440 </prop.pair> 0441 </prop.list> 0442 )")); 0443 0444 QCOMPARE(int(data.type()), int(CosValue::Index::Object)); 0445 QCOMPARE(int(get(data, "Alpha Stops").type()), int(CosValue::Index::Object)); 0446 QCOMPARE(int(get(data, "Alpha Stops", "Stops List").type()), int(CosValue::Index::Object)); 0447 auto& stop = get_as<CosValue::Index::Object>(data, "Alpha Stops", "Stops List", "Stop-0"); 0448 auto& color_arr = get_as<CosValue::Index::Array>(stop, "Stops Alpha"); 0449 COS_VALUE(get(color_arr, 0), Number, 0); 0450 COS_VALUE(get(color_arr, 1), Number, 0.5); 0451 COS_VALUE(get(color_arr, 2), Number, 0.6); 0452 auto stops = get_gradient_stops<GradientStopAlpha>(data); 0453 QCOMPARE(stops.size(), 2); 0454 QCOMPARE(stops[0].offset, 0); 0455 QCOMPARE(stops[0].value, 0.6); 0456 QCOMPARE(stops[1].offset, 1); 0457 QCOMPARE(stops[1].value, 0.5); 0458 } 0459 0460 void test_get_alpha_at_2() 0461 { 0462 GradientStops<double> stops; 0463 stops.push_back({0, 0.5, 0.6}); 0464 stops.push_back({1, 0.5, 0.5}); 0465 int index = 0; 0466 QCOMPARE(qRound(255 * stops.value_at(0, index)), qRound(255 * 0.6)); 0467 QCOMPARE(index, 0); 0468 QCOMPARE(qRound(255 * stops.value_at(1, index)), qRound(255 * 0.5)); 0469 QCOMPARE(index, 2); 0470 index = 0; 0471 QCOMPARE(qRound(255 * stops.value_at(0.5, index)), qRound(255 * 0.55)); 0472 QCOMPARE(index, 0); 0473 } 0474 0475 void test_gradient_2c2a() 0476 { 0477 auto aegrad = parse_gradient_xml(QString(R"( 0478 <?xml version='1.0'?> 0479 <prop.map version='4'> 0480 <prop.list> 0481 <prop.pair> 0482 <key>Gradient Color Data</key> 0483 <prop.list> 0484 <prop.pair> 0485 <key>Alpha Stops</key> 0486 <prop.list> 0487 <prop.pair> 0488 <key>Stops List</key> 0489 <prop.list> 0490 <prop.pair> 0491 <key>Stop-0</key> 0492 <prop.list> 0493 <prop.pair> 0494 <key>Stops Alpha</key> 0495 <array> 0496 <array.type> 0497 <float/> 0498 </array.type> 0499 <float>0</float> 0500 <float>0.5</float> 0501 <float>0.6</float> 0502 </array> 0503 </prop.pair> 0504 </prop.list> 0505 </prop.pair> 0506 <prop.pair> 0507 <key>Stop-1</key> 0508 <prop.list> 0509 <prop.pair> 0510 <key>Stops Alpha</key> 0511 <array> 0512 <array.type> 0513 <float/> 0514 </array.type> 0515 <float>1</float> 0516 <float>0.5</float> 0517 <float>0.5</float> 0518 </array> 0519 </prop.pair> 0520 </prop.list> 0521 </prop.pair> 0522 </prop.list> 0523 </prop.pair> 0524 <prop.pair> 0525 <key>Stops Size</key> 0526 <int type='unsigned' size='32'>2</int> 0527 </prop.pair> 0528 </prop.list> 0529 </prop.pair> 0530 <prop.pair> 0531 <key>Color Stops</key> 0532 <prop.list> 0533 <prop.pair> 0534 <key>Stops List</key> 0535 <prop.list> 0536 <prop.pair> 0537 <key>Stop-0</key> 0538 <prop.list> 0539 <prop.pair> 0540 <key>Stops Color</key> 0541 <array> 0542 <array.type> 0543 <float/> 0544 </array.type> 0545 <float>0</float> 0546 <float>0.5</float> 0547 <float>0.1</float> 0548 <float>0.2</float> 0549 <float>0.3</float> 0550 <float>0.4</float> 0551 </array> 0552 </prop.pair> 0553 </prop.list> 0554 </prop.pair> 0555 <prop.pair> 0556 <key>Stop-1</key> 0557 <prop.list> 0558 <prop.pair> 0559 <key>Stops Color</key> 0560 <array> 0561 <array.type> 0562 <float/> 0563 </array.type> 0564 <float>1</float> 0565 <float>0.5</float> 0566 <float>0.7</float> 0567 <float>0.8</float> 0568 <float>0.9</float> 0569 <float>1</float> 0570 </array> 0571 </prop.pair> 0572 </prop.list> 0573 </prop.pair> 0574 </prop.list> 0575 </prop.pair> 0576 <prop.pair> 0577 <key>Stops Size</key> 0578 <int type='unsigned' size='32'>2</int> 0579 </prop.pair> 0580 </prop.list> 0581 </prop.pair> 0582 </prop.list> 0583 </prop.pair> 0584 <prop.pair> 0585 <key>Gradient Colors</key> 0586 <string>1.0</string> 0587 </prop.pair> 0588 </prop.list> 0589 </prop.map> 0590 )")); 0591 0592 auto grad = aegrad.to_qt(); 0593 QCOMPARE(grad.size(), 2); 0594 QCOMPARE(grad[0].first, 0); 0595 QCOMPARE(grad[1].first, 1); 0596 QCOMPARE(grad[0].second, QColor::fromRgbF(0.1, 0.2, 0.3, 0.6)); 0597 QCOMPARE(grad[1].second, QColor::fromRgbF(0.7, 0.8, 0.9, 0.5)); 0598 } 0599 }; 0600 0601 QTEST_GUILESS_MAIN(TestCase) 0602 #include "test_aep_gradient_xml.moc" 0603 0604 0605