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