File indexing completed on 2024-10-20 04:17:38
0001 // SPDX-FileCopyrightText: Lukas Sommer <sommerluk@gmail.com> 0002 // SPDX-License-Identifier: BSD-2-Clause OR MIT 0003 0004 // First included header is the public header of the class we are testing; 0005 // this forces the header to be self-contained. 0006 #include "csscolor.h" 0007 0008 #include "genericcolor.h" 0009 #include "helperconversion.h" 0010 #include <helperposixmath.h> 0011 #include <optional> 0012 #include <qcontainerfwd.h> 0013 #include <qdebug.h> 0014 #include <qglobal.h> 0015 #include <qhash.h> 0016 #include <qlist.h> 0017 #include <qobject.h> 0018 #include <qrgb.h> 0019 #include <qstring.h> 0020 #include <qstringliteral.h> 0021 #include <qtest.h> 0022 #include <qtestcase.h> 0023 #include <qtestdata.h> 0024 0025 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) 0026 #include <qtmetamacros.h> 0027 #else 0028 #include <qobjectdefs.h> 0029 #include <qstring.h> 0030 #endif 0031 0032 namespace PerceptualColor 0033 { 0034 class TestCssColor : public QObject 0035 { 0036 Q_OBJECT 0037 0038 public: 0039 explicit TestCssColor(QObject *parent = nullptr) 0040 : QObject(parent) 0041 { 0042 } 0043 0044 private Q_SLOTS: 0045 void initTestCase() 0046 { 0047 // Called before the first test function is executed 0048 } 0049 0050 void cleanupTestCase() 0051 { 0052 // Called after the last test function was executed 0053 } 0054 0055 void init() 0056 { 0057 // Called before each test function is executed 0058 } 0059 0060 void cleanup() 0061 { 0062 // Called after every test function 0063 } 0064 0065 void testParseHexColor() 0066 { 0067 QCOMPARE( // 0068 CssColor::parseHexColor(QString()).has_value(), 0069 false); 0070 QCOMPARE( // 0071 CssColor::parseHexColor(QStringLiteral("#")).has_value(), 0072 false); 0073 QCOMPARE( // 0074 CssColor::parseHexColor(QStringLiteral("#1")).has_value(), 0075 false); 0076 QCOMPARE( // 0077 CssColor::parseHexColor(QStringLiteral("#12")).has_value(), 0078 false); 0079 QCOMPARE( // 0080 CssColor::parseHexColor(QStringLiteral("#12345")).has_value(), 0081 false); 0082 QCOMPARE( // 0083 CssColor::parseHexColor(QStringLiteral("#1234567")).has_value(), 0084 false); 0085 QCOMPARE( // 0086 CssColor::parseHexColor(QStringLiteral("#123456789")).has_value(), 0087 false); 0088 QCOMPARE( // 0089 CssColor::parseHexColor(QStringLiteral("123")).has_value(), 0090 false); 0091 QCOMPARE( // 0092 CssColor::parseHexColor(QStringLiteral("1234")).has_value(), 0093 false); 0094 QCOMPARE( // 0095 CssColor::parseHexColor(QStringLiteral("123456")).has_value(), 0096 false); 0097 QCOMPARE( // 0098 CssColor::parseHexColor(QStringLiteral("12345678")).has_value(), 0099 false); 0100 QCOMPARE( // 0101 CssColor::parseHexColor(QStringLiteral("#123")).value_or(42), 0102 0xff112233); 0103 QCOMPARE( // 0104 CssColor::parseHexColor(QStringLiteral("#1234")).value_or(42), 0105 0x44112233); 0106 QCOMPARE( // 0107 CssColor::parseHexColor(QStringLiteral("#123456")).value_or(42), 0108 0xff123456); 0109 QCOMPARE( // 0110 CssColor::parseHexColor(QStringLiteral("#12345678")).value_or(42), 0111 0x78123456); 0112 QCOMPARE( // 0113 CssColor::parseHexColor(QStringLiteral("#abcdef78")).value_or(42), 0114 0x78abcdef); 0115 QCOMPARE( // 0116 CssColor::parseHexColor(QStringLiteral("#AbCdeF78")).value_or(42), 0117 0x78abcdef); 0118 } 0119 0120 void testParseNamedColor() 0121 { 0122 QCOMPARE(CssColor::parseNamedColor(QString()).has_value(), false); 0123 QCOMPARE(CssColor::parseNamedColor( // 0124 QStringLiteral("invalid")) 0125 .has_value(), 0126 false); 0127 QCOMPARE(CssColor::parseNamedColor( // 0128 QStringLiteral("aliceblue")) 0129 .value_or(42), 0130 0xfff0f8ff); 0131 QCOMPARE(CssColor::parseNamedColor( // 0132 QStringLiteral("AliceBlue")) 0133 .value_or(42), 0134 0xfff0f8ff); 0135 QCOMPARE(CssColor::parseNamedColor( // 0136 QStringLiteral("AliceBlueX")) 0137 .has_value(), 0138 false); 0139 QCOMPARE(CssColor::parseNamedColor( // 0140 QStringLiteral("XAliceBlue")) 0141 .has_value(), 0142 false); 0143 QCOMPARE(CssColor::parseNamedColor( // 0144 QStringLiteral("transparent")) 0145 .value_or(42), 0146 0x00000000); 0147 QCOMPARE(CssColor::parseNamedColor( // 0148 QStringLiteral("TransParent")) 0149 .value_or(42), 0150 0x00000000); 0151 } 0152 0153 void testParseArgumentPercentNumberNone() 0154 { 0155 // Empty value 0156 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0157 QString(), 0158 255, 0159 0) 0160 .has_value(), 0161 false); 0162 0163 // none 0164 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0165 QStringLiteral("none"), 0166 255, 0167 0) 0168 .value_or(42), 0169 0); 0170 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0171 QStringLiteral("none"), 0172 255, 0173 1) 0174 .value_or(42), 0175 1); 0176 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0177 QStringLiteral("none"), 0178 255, 0179 255) 0180 .value_or(42), 0181 255); 0182 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0183 QStringLiteral(" none"), 0184 255, 0185 255) 0186 .value_or(42), 0187 255); 0188 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0189 QStringLiteral("none "), 0190 255, 0191 255) 0192 .value_or(42), 0193 255); 0194 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0195 QStringLiteral("none"), 0196 0, 0197 0) 0198 .value_or(42), 0199 0); 0200 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0201 QStringLiteral("none"), 0202 -1, 0203 0) 0204 .value_or(42), 0205 0); 0206 0207 // Number 0208 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0209 QStringLiteral("56"), 0210 255, 0211 0) 0212 .value_or(42), 0213 56); 0214 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0215 QStringLiteral("56"), 0216 2, 0217 -1) 0218 .value_or(42), 0219 56); 0220 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0221 QStringLiteral(" 56"), 0222 255, 0223 0) 0224 .value_or(42), 0225 56); 0226 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0227 QStringLiteral("56 "), 0228 255, 0229 0) 0230 .value_or(42), 0231 56); 0232 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0233 QStringLiteral("56.0"), 0234 2, 0235 -1) 0236 .value_or(42), 0237 56); 0238 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0239 QStringLiteral("56,0"), 0240 255, 0241 0) 0242 .has_value(), 0243 false); 0244 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0245 QStringLiteral("56e1"), 0246 2, 0247 -1) 0248 .value_or(42), 0249 560); 0250 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0251 QStringLiteral("56.0e1"), 0252 2, 0253 -1) 0254 .value_or(42), 0255 560); 0256 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0257 QStringLiteral("56.0e-1"), 0258 2, 0259 -1) 0260 .value_or(42), 0261 5.6); 0262 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0263 QStringLiteral("56.0E-1"), 0264 2, 0265 -1) 0266 .value_or(42), 0267 5.6); 0268 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0269 QStringLiteral("-56.0e-1"), 0270 2, 0271 -1) 0272 .value_or(42), 0273 -5.6); 0274 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0275 QStringLiteral("-56 e1"), 0276 255, 0277 0) 0278 .has_value(), 0279 false); 0280 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0281 QStringLiteral("-56"), 0282 255, 0283 0) 0284 .value_or(42), 0285 -56); 0286 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0287 QStringLiteral("- 56"), 0288 255, 0289 0) 0290 .has_value(), 0291 false); 0292 0293 // Percent 0294 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0295 QStringLiteral("50 %"), 0296 300, 0297 0) 0298 .has_value(), 0299 false); 0300 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0301 QStringLiteral("50%"), 0302 300, 0303 0) 0304 .value_or(42), 0305 150); 0306 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0307 QStringLiteral("50%"), 0308 400, 0309 -1) 0310 .value_or(42), 0311 200); 0312 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0313 QStringLiteral(" 50%"), 0314 200, 0315 0) 0316 .value_or(42), 0317 100); 0318 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0319 QStringLiteral("50% "), 0320 200, 0321 0) 0322 .value_or(42), 0323 100); 0324 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0325 QStringLiteral("50.0%"), 0326 200, 0327 -1) 0328 .value_or(42), 0329 100); 0330 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0331 QStringLiteral("50,0%"), 0332 200, 0333 0) 0334 .has_value(), 0335 false); 0336 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0337 QStringLiteral("50e1%"), 0338 200, 0339 -1) 0340 .value_or(42), 0341 1000); 0342 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0343 QStringLiteral("50.0e1%"), 0344 200, 0345 -1) 0346 .value_or(42), 0347 1000); 0348 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0349 QStringLiteral("50.0e-1%"), 0350 200, 0351 -1) 0352 .value_or(42), 0353 10); 0354 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0355 QStringLiteral("50.0E-1%"), 0356 200, 0357 -1) 0358 .value_or(42), 0359 10); 0360 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0361 QStringLiteral("-50.0e-1%"), 0362 200, 0363 -1) 0364 .value_or(42), 0365 -10); 0366 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0367 QStringLiteral("-50 e1%"), 0368 255, 0369 0) 0370 .has_value(), 0371 false); 0372 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0373 QStringLiteral("-50%"), 0374 200, 0375 0) 0376 .value_or(42), 0377 -100); 0378 QCOMPARE(CssColor::parseArgumentPercentNumberNone( // 0379 QStringLiteral("- 50%"), 0380 200, 0381 0) 0382 .has_value(), 0383 false); 0384 } 0385 0386 void testValidateArguments() 0387 { 0388 QCOMPARE(CssColor::validateArguments( // 0389 QStringList({QStringLiteral("1"), // 0390 QStringLiteral("2"), 0391 QStringLiteral("3")})) 0392 .value(), 0393 QStringList({QStringLiteral("1"), // 0394 QStringLiteral("2"), 0395 QStringLiteral("3")})); 0396 QCOMPARE(CssColor::validateArguments( // 0397 QStringList({QStringLiteral(" 1"), // 0398 QStringLiteral("2 "), 0399 QStringLiteral(" 3 ")})) 0400 .value(), 0401 QStringList({QStringLiteral("1"), // 0402 QStringLiteral("2"), 0403 QStringLiteral("3")})); 0404 QCOMPARE(CssColor::validateArguments( // 0405 QStringList({QStringLiteral("1 1"), // 0406 QStringLiteral("2"), 0407 QStringLiteral("3")})) 0408 .has_value(), 0409 false); 0410 QCOMPARE(CssColor::validateArguments( // 0411 QStringList({QStringLiteral("1,"), // 0412 QStringLiteral("2"), 0413 QStringLiteral("3")})) 0414 .has_value(), 0415 false); 0416 QCOMPARE(CssColor::validateArguments( // 0417 QStringList({QStringLiteral("1/"), // 0418 QStringLiteral("2"), 0419 QStringLiteral("3")})) 0420 .has_value(), 0421 false); 0422 } 0423 0424 void testParseAllFunctionArguments() 0425 { 0426 QCOMPARE(CssColor::parseAllFunctionArguments( // 0427 QStringLiteral("1 2 3"), 0428 CssColor::FunctionSyntax::StandardSyntax, 0429 4) 0430 .value_or(QStringList()), 0431 QStringList({QStringLiteral("1"), // 0432 QStringLiteral("2"), 0433 QStringLiteral("3"), 0434 QStringLiteral("none")})); 0435 QCOMPARE(CssColor::parseAllFunctionArguments( // 0436 QStringLiteral("1 2 3"), 0437 CssColor::FunctionSyntax::BothSyntaxes, 0438 4) 0439 .value_or(QStringList()), 0440 QStringList({QStringLiteral("1"), // 0441 QStringLiteral("2"), 0442 QStringLiteral("3"), 0443 QStringLiteral("none")})); 0444 QCOMPARE(CssColor::parseAllFunctionArguments( // 0445 QStringLiteral("1 2 3"), 0446 CssColor::FunctionSyntax::LegacySyntax, 0447 4) 0448 .has_value(), 0449 false); 0450 QCOMPARE(CssColor::parseAllFunctionArguments( // 0451 QStringLiteral("1 2 3"), 0452 CssColor::FunctionSyntax::StandardSyntax, 0453 3) 0454 .has_value(), 0455 false); 0456 QCOMPARE(CssColor::parseAllFunctionArguments( // 0457 QStringLiteral("1 2 3"), 0458 CssColor::FunctionSyntax::StandardSyntax, 0459 4) 0460 .value_or(QStringList()), 0461 QStringList({QStringLiteral("1"), // 0462 QStringLiteral("2"), 0463 QStringLiteral("3"), 0464 QStringLiteral("none")})); 0465 QCOMPARE(CssColor::parseAllFunctionArguments( // 0466 QStringLiteral("1, 2, 3"), 0467 CssColor::FunctionSyntax::StandardSyntax, 0468 3) 0469 .has_value(), 0470 false); 0471 QCOMPARE(CssColor::parseAllFunctionArguments( // 0472 QStringLiteral("1, 2, 3"), 0473 CssColor::FunctionSyntax::LegacySyntax, 0474 4) 0475 .value_or(QStringList()), 0476 QStringList({QStringLiteral("1"), // 0477 QStringLiteral("2"), 0478 QStringLiteral("3"), 0479 QStringLiteral("none")})); 0480 QCOMPARE(CssColor::parseAllFunctionArguments( // 0481 QStringLiteral("1, 2, 3"), 0482 CssColor::FunctionSyntax::BothSyntaxes, 0483 4) 0484 .value_or(QStringList()), 0485 QStringList({QStringLiteral("1"), // 0486 QStringLiteral("2"), 0487 QStringLiteral("3"), 0488 QStringLiteral("none")})); 0489 QCOMPARE(CssColor::parseAllFunctionArguments( // 0490 QStringLiteral("1 2 3 / 4"), 0491 CssColor::FunctionSyntax::StandardSyntax, 0492 4) 0493 .value_or(QStringList()), 0494 QStringList({QStringLiteral("1"), // 0495 QStringLiteral("2"), 0496 QStringLiteral("3"), 0497 QStringLiteral("4")})); 0498 QCOMPARE(CssColor::parseAllFunctionArguments( // 0499 QStringLiteral("1 2 3 / 4"), 0500 CssColor::FunctionSyntax::BothSyntaxes, 0501 4) 0502 .value_or(QStringList()), 0503 QStringList({QStringLiteral("1"), // 0504 QStringLiteral("2"), 0505 QStringLiteral("3"), 0506 QStringLiteral("4")})); 0507 QCOMPARE(CssColor::parseAllFunctionArguments( // 0508 QStringLiteral("1 2 3 / 4"), 0509 CssColor::FunctionSyntax::LegacySyntax, 0510 4) 0511 .has_value(), 0512 false); 0513 QCOMPARE(CssColor::parseAllFunctionArguments( // 0514 QStringLiteral("1, 2, 3 / 4"), 0515 CssColor::FunctionSyntax::LegacySyntax, 0516 4) 0517 .has_value(), 0518 false); 0519 QCOMPARE(CssColor::parseAllFunctionArguments( // 0520 QStringLiteral("1 2 / 3"), 0521 CssColor::FunctionSyntax::StandardSyntax, 0522 4) 0523 .has_value(), 0524 false); 0525 QCOMPARE(CssColor::parseAllFunctionArguments( // 0526 QStringLiteral("1 2 / 3 4"), 0527 CssColor::FunctionSyntax::StandardSyntax, 0528 4) 0529 .has_value(), 0530 false); 0531 QCOMPARE(CssColor::parseAllFunctionArguments( // 0532 QStringLiteral("1 2"), 0533 CssColor::FunctionSyntax::StandardSyntax, 0534 4) 0535 .has_value(), 0536 false); 0537 QCOMPARE(CssColor::parseAllFunctionArguments( // 0538 QStringLiteral("1 2 3 4"), 0539 CssColor::FunctionSyntax::StandardSyntax, 0540 4) 0541 .has_value(), 0542 false); 0543 QCOMPARE(CssColor::parseAllFunctionArguments( // 0544 QStringLiteral("1 2 3 4 5"), 0545 CssColor::FunctionSyntax::StandardSyntax, 0546 4) 0547 .has_value(), 0548 false); 0549 QCOMPARE(CssColor::parseAllFunctionArguments( // 0550 QStringLiteral("1, 2, 3, 4"), 0551 CssColor::FunctionSyntax::LegacySyntax, 0552 4) 0553 .value_or(QStringList()), 0554 QStringList({QStringLiteral("1"), // 0555 QStringLiteral("2"), 0556 QStringLiteral("3"), 0557 QStringLiteral("4")})); 0558 QCOMPARE(CssColor::parseAllFunctionArguments( // 0559 QStringLiteral("1, 2, 3, 4, 5"), 0560 CssColor::FunctionSyntax::LegacySyntax, 0561 4) 0562 .has_value(), 0563 false); 0564 } 0565 0566 #ifndef MSVC_DLL 0567 void testParseAbsoluteColorFunction_data() 0568 { 0569 QTest::addColumn<QString>("function"); 0570 QTest::addColumn<ColorModel>("model"); 0571 QTest::addColumn<CssColor::CssPredefinedRgbColorSpace>("rgbColorSpace"); 0572 QTest::addColumn<double>("first"); 0573 QTest::addColumn<double>("second"); 0574 QTest::addColumn<double>("third"); 0575 QTest::addColumn<double>("forth"); 0576 QTest::addColumn<double>("alpha1"); 0577 0578 QTest::newRow("rgb(1 2 3)") // 0579 << QStringLiteral("rgb(1 2 3)") // 0580 << ColorModel::Rgb1 // 0581 << CssColor::CssPredefinedRgbColorSpace::Srgb // 0582 << 1. / 255. << 2. / 255. << 3. / 255. << 0. // 0583 << 1.; 0584 QTest::newRow("rgba(1 2 3)") // 0585 << QStringLiteral("rgba(1 2 3)") // 0586 << ColorModel::Invalid // 0587 << CssColor::CssPredefinedRgbColorSpace::Invalid // 0588 << 0. << 0. << 0. << 0. // 0589 << 0.; 0590 QTest::newRow("rgb(1 2 3 / 0.5)") // 0591 << QStringLiteral("rgb(1 2 3 / 0.5)") // 0592 << ColorModel::Rgb1 // 0593 << CssColor::CssPredefinedRgbColorSpace::Srgb // 0594 << 1. / 255. << 2. / 255. << 3. / 255. << 0. // 0595 << 0.5; 0596 QTest::newRow("rgb(1 2 / 3)") // 0597 << QStringLiteral("rgb(1 2 / 3)") // 0598 << ColorModel::Invalid // 0599 << CssColor::CssPredefinedRgbColorSpace::Invalid // 0600 << 0. << 0. << 0. << 0. // 0601 << 0.; 0602 QTest::newRow("rgb(1, 2, 3, 0.5)") // 0603 << QStringLiteral("rgb(1, 2, 3, 0.5)") // 0604 << ColorModel::Rgb1 // 0605 << CssColor::CssPredefinedRgbColorSpace::Srgb // 0606 << 1. / 255. << 2. / 255. << 3. / 255. << 0. // 0607 << 0.5; 0608 QTest::newRow("rgba(1, 2, 3, 0.5)") // 0609 << QStringLiteral("rgba(1, 2, 3, 0.5)") // 0610 << ColorModel::Rgb1 // 0611 << CssColor::CssPredefinedRgbColorSpace::Srgb // 0612 << 1. / 255. << 2. / 255. << 3. / 255. << 0. // 0613 << 0.5; 0614 QTest::newRow("rgb(100% 50% 0% / 0.5)") // 0615 << QStringLiteral("rgb(100% 50% 0% / 0.5)") // 0616 << ColorModel::Rgb1 // 0617 << CssColor::CssPredefinedRgbColorSpace::Srgb // 0618 << 1. << 0.5 << 0. << 0. // 0619 << 0.5; 0620 QTest::newRow("rgb(100% 50% 0% / 50%)") // 0621 << QStringLiteral("rgb(100% 50% 0% / 50%)") // 0622 << ColorModel::Rgb1 // 0623 << CssColor::CssPredefinedRgbColorSpace::Srgb // 0624 << 1. << 0.5 << 0. << 0. // 0625 << 0.5; 0626 QTest::newRow("rgb(100% 50% 0% / none)") // 0627 << QStringLiteral("rgb(100% 50% 0% / none)") // 0628 << ColorModel::Rgb1 // 0629 << CssColor::CssPredefinedRgbColorSpace::Srgb // 0630 << 1. << 0.5 << 0. << 0. // 0631 << 1.; 0632 QTest::newRow("rgb(100% 50% 0% / )") // 0633 << QStringLiteral("rgb(100% 50% 0% / )") // 0634 << ColorModel::Invalid // 0635 << CssColor::CssPredefinedRgbColorSpace::Invalid // 0636 << 0. << 0. << 0. << 0. // 0637 << 0.; 0638 QTest::newRow("rgb(100% 50% 0%)") // 0639 << QStringLiteral("rgb(100% 50% 0%)") // 0640 << ColorModel::Rgb1 // 0641 << CssColor::CssPredefinedRgbColorSpace::Srgb // 0642 << 1. << 0.5 << 0. << 0. // 0643 << 1.; 0644 QTest::newRow("rgb(none 50% 0%)") // 0645 << QStringLiteral("rgb(none 50% 0%)") // 0646 << ColorModel::Rgb1 // 0647 << CssColor::CssPredefinedRgbColorSpace::Srgb // 0648 << 0. << 0.5 << 0. << 0. // 0649 << 1.; 0650 0651 QTest::newRow("color(srgb 100% 50% 0% / 0.5)") // 0652 << QStringLiteral("color(srgb 100% 50% 0% / 0.5)") // 0653 << ColorModel::Rgb1 // 0654 << CssColor::CssPredefinedRgbColorSpace::Srgb // 0655 << 1. << 0.5 << 0. << 0. // 0656 << 0.5; 0657 QTest::newRow("color(srgb 0.1 0.2 0.3 / 0.5)") // 0658 << QStringLiteral("color(srgb 0.1 0.2 0.3 / 0.5)") // 0659 << ColorModel::Rgb1 // 0660 << CssColor::CssPredefinedRgbColorSpace::Srgb // 0661 << 0.1 << 0.2 << 0.3 << 0. // 0662 << 0.5; 0663 0664 QTest::newRow("color(srgb-linear 100% 50% 0% / 0.5)") // 0665 << QStringLiteral("color(srgb-linear 100% 50% 0% / 0.5)") // 0666 << ColorModel::Rgb1 // 0667 << CssColor::CssPredefinedRgbColorSpace::SrgbLinear // 0668 << 1. << 0.5 << 0. << 0. // 0669 << 0.5; 0670 0671 QTest::newRow("color(display-p3 100% 50% 0% / 0.5)") // 0672 << QStringLiteral("color(display-p3 100% 50% 0% / 0.5)") // 0673 << ColorModel::Rgb1 // 0674 << CssColor::CssPredefinedRgbColorSpace::DisplayP3 // 0675 << 1. << 0.5 << 0. << 0. // 0676 << 0.5; 0677 0678 QTest::newRow("color(a98-rgb 100% 50% 0% / 0.5)") // 0679 << QStringLiteral("color(a98-rgb 100% 50% 0% / 0.5)") // 0680 << ColorModel::Rgb1 // 0681 << CssColor::CssPredefinedRgbColorSpace::A98Rgb // 0682 << 1. << 0.5 << 0. << 0. // 0683 << 0.5; 0684 0685 QTest::newRow("color(prophoto-rgb 100% 50% 0% / 0.5)") // 0686 << QStringLiteral("color(prophoto-rgb 100% 50% 0% / 0.5)") // 0687 << ColorModel::Rgb1 // 0688 << CssColor::CssPredefinedRgbColorSpace::ProphotoRgb // 0689 << 1. << 0.5 << 0. << 0. // 0690 << 0.5; 0691 0692 QTest::newRow("color(rec2020 100% 50% 0% / 0.5)") // 0693 << QStringLiteral("color(rec2020 100% 50% 0% / 0.5)") // 0694 << ColorModel::Rgb1 // 0695 << CssColor::CssPredefinedRgbColorSpace::Rec2020 // 0696 << 1. << 0.5 << 0. << 0. // 0697 << 0.5; 0698 0699 QTest::newRow("color(xyz 0.1 0.2 0.3 / 0.5)") // 0700 << QStringLiteral("color(xyz 0.1 0.2 0.3 / 0.5)") // 0701 << ColorModel::XyzD65 // 0702 << CssColor::CssPredefinedRgbColorSpace::Invalid // 0703 << 0.1 << 0.2 << 0.3 << 0. // 0704 << 0.5; 0705 QTest::newRow("color(xyz 10% 20% 30% / 50%)") // 0706 << QStringLiteral("color(xyz 10% 20% 30% / 50%)") // 0707 << ColorModel::XyzD65 // 0708 << CssColor::CssPredefinedRgbColorSpace::Invalid // 0709 << 0.1 << 0.2 << 0.3 << 0. // 0710 << 0.5; 0711 QTest::newRow("color(xyz-d65 0.1 0.2 0.3 / 0.5)") // 0712 << QStringLiteral("color(xyz-d65 0.1 0.2 0.3 / 0.5)") // 0713 << ColorModel::XyzD65 // 0714 << CssColor::CssPredefinedRgbColorSpace::Invalid // 0715 << 0.1 << 0.2 << 0.3 << 0. // 0716 << 0.5; 0717 QTest::newRow("color(xyz-d50 0.1 0.2 0.3 / 0.5)") // 0718 << QStringLiteral("color(xyz-d50 0.1 0.2 0.3 / 0.5)") // 0719 << ColorModel::XyzD50 // 0720 << CssColor::CssPredefinedRgbColorSpace::Invalid // 0721 << 0.1 << 0.2 << 0.3 << 0. // 0722 << 0.5; 0723 0724 QTest::newRow("hsl(0.1 0.2 0.3 / 0.5)") // 0725 << QStringLiteral("hsl(0.1 0.2 0.3 / 0.5)") // 0726 << ColorModel::Invalid // 0727 << CssColor::CssPredefinedRgbColorSpace::Invalid // 0728 << 0. << 0. << 0. << 0. // 0729 << 0.; 0730 QTest::newRow("hsl(3 10% 20% / 0.5)") // 0731 << QStringLiteral("hsl(3 10% 20% / 0.5)") // 0732 << ColorModel::Hsl360_1_1 // 0733 << CssColor::CssPredefinedRgbColorSpace::Srgb // 0734 << 3. << 0.1 << 0.2 << 0. // 0735 << 0.5; 0736 QTest::newRow("hsla(3, 10%, 20%, 0.5)") // 0737 << QStringLiteral("hsla(3, 10%, 20%, 0.5)") // 0738 << ColorModel::Hsl360_1_1 // 0739 << CssColor::CssPredefinedRgbColorSpace::Srgb // 0740 << 3. << 0.1 << 0.2 << 0. // 0741 << 0.5; 0742 QTest::newRow("hwb(3 10% 20% / 0.5)") // 0743 << QStringLiteral("hwb(3 10% 20% / 0.5)") // 0744 << ColorModel::Hwb360_1_1 // 0745 << CssColor::CssPredefinedRgbColorSpace::Srgb // 0746 << 3. << 0.1 << 0.2 << 0. // 0747 << 0.5; 0748 QTest::newRow("hwb(3 none 20% / 0.5)") // 0749 << QStringLiteral("hwb(3 none 20% / 0.5)") // 0750 << ColorModel::Hwb360_1_1 // 0751 << CssColor::CssPredefinedRgbColorSpace::Srgb // 0752 << 3. << 0. << 0.2 << 0. // 0753 << 0.5; 0754 QTest::newRow("hwb(none 10% 20% / 0.5)") // 0755 << QStringLiteral("hwb(none 10% 20% / 0.5)") // 0756 << ColorModel::Hwb360_1_1 // 0757 << CssColor::CssPredefinedRgbColorSpace::Srgb // 0758 << 0. << 0.1 << 0.2 << 0. // 0759 << 0.5; 0760 0761 QTest::newRow("oklab(0.1 0.2 0.3 / 0.5)") // 0762 << QStringLiteral("oklab(0.1 0.2 0.3 / 0.5)") // 0763 << ColorModel::OklabD65 // 0764 << CssColor::CssPredefinedRgbColorSpace::Invalid // 0765 << 0.1 << 0.2 << 0.3 << 0. // 0766 << 0.5; 0767 QTest::newRow("oklab(30% 50% 150% / 0.5)") // 0768 << QStringLiteral("oklab(30% 50% 150% / 0.5)") // 0769 << ColorModel::OklabD65 // 0770 << CssColor::CssPredefinedRgbColorSpace::Invalid // 0771 << 0.3 << 0.2 << 0.6 << 0. // 0772 << 0.5; 0773 0774 QTest::newRow("lab(0.1 0.2 0.3 / 0.5)") // 0775 << QStringLiteral("lab(0.1 0.2 0.3 / 0.5)") // 0776 << ColorModel::CielabD50 // 0777 << CssColor::CssPredefinedRgbColorSpace::Invalid // 0778 << 0.1 << 0.2 << 0.3 << 0. // 0779 << 0.5; 0780 QTest::newRow("lab(30% 50% 150% / 0.5)") // 0781 << QStringLiteral("lab(30% 50% 150% / 0.5)") // 0782 << ColorModel::CielabD50 // 0783 << CssColor::CssPredefinedRgbColorSpace::Invalid // 0784 << 30. << 62.5 << 187.5 << 0. // 0785 << 0.5; 0786 0787 QTest::newRow("oklch(0.1 0.2 0.3 / 0.5)") // 0788 << QStringLiteral("oklch(0.1 0.2 0.3 / 0.5)") // 0789 << ColorModel::OklchD65 // 0790 << CssColor::CssPredefinedRgbColorSpace::Invalid // 0791 << 0.1 << 0.2 << 0.3 << 0. // 0792 << 0.5; 0793 QTest::newRow("oklch(0.1 0.2 0.75turn / 0.5)") // 0794 << QStringLiteral("oklch(0.1 0.2 0.75turn / 0.5)") // 0795 << ColorModel::OklchD65 // 0796 << CssColor::CssPredefinedRgbColorSpace::Invalid // 0797 << 0.1 << 0.2 << 270. << 0. // 0798 << 0.5; 0799 QTest::newRow("oklch(30% 50% 150 / 0.5)") // 0800 << QStringLiteral("oklch(30% 50% 150 / 0.5)") // 0801 << ColorModel::OklchD65 // 0802 << CssColor::CssPredefinedRgbColorSpace::Invalid // 0803 << 0.3 << 0.2 << 150. << 0. // 0804 << 0.5; 0805 0806 QTest::newRow("lch(0.1 0.2 0.3 / 0.5)") // 0807 << QStringLiteral("lch(0.1 0.2 0.3 / 0.5)") // 0808 << ColorModel::CielchD50 // 0809 << CssColor::CssPredefinedRgbColorSpace::Invalid // 0810 << 0.1 << 0.2 << 0.3 << 0. // 0811 << 0.5; 0812 0813 QTest::newRow("lch(0.1 0.2 0.75turn / 0.5)") // 0814 << QStringLiteral("lch(0.1 0.2 0.75turn / 0.5)") // 0815 << ColorModel::CielchD50 // 0816 << CssColor::CssPredefinedRgbColorSpace::Invalid // 0817 << 0.1 << 0.2 << 270. << 0. // 0818 << 0.5; 0819 QTest::newRow("lch(30% 50% 0.8 / 0.5)") // 0820 << QStringLiteral("lch(30% 50% 0.8 / 0.5)") // 0821 << ColorModel::CielchD50 // 0822 << CssColor::CssPredefinedRgbColorSpace::Invalid // 0823 << 30. << 75. << 0.8 << 0. // 0824 << 0.5; 0825 QTest::newRow("lch(30% 50% 0.8% / 0.5)") // 0826 << QStringLiteral("lch(30% 50% 0.8% / 0.5)") // 0827 << ColorModel::Invalid // 0828 << CssColor::CssPredefinedRgbColorSpace::Invalid // 0829 << 0. << 0. << 0. << 0. // 0830 << 0.; 0831 } 0832 0833 void testParseAbsoluteColorFunction() 0834 { 0835 QFETCH(QString, function); 0836 QFETCH(ColorModel, model); 0837 QFETCH(CssColor::CssPredefinedRgbColorSpace, rgbColorSpace); 0838 QFETCH(double, first); 0839 QFETCH(double, second); 0840 QFETCH(double, third); 0841 QFETCH(double, forth); 0842 QFETCH(double, alpha1); 0843 0844 const auto temp = CssColor::parseAbsoluteColorFunction(function); 0845 QCOMPARE(temp.model, model); 0846 QCOMPARE(temp.rgbColorSpace, rgbColorSpace); 0847 QCOMPARE(temp.color.first, first); 0848 QCOMPARE(temp.color.second, second); 0849 QCOMPARE(temp.color.third, third); 0850 QCOMPARE(temp.color.fourth, forth); 0851 QCOMPARE(temp.alpha1, alpha1); 0852 } 0853 #endif 0854 0855 void testParseArgumentPercentNoneTo1() 0856 { 0857 QVERIFY(!CssColor::parseArgumentPercentNoneTo1( // 0858 QString()) 0859 .has_value()); 0860 QVERIFY(!CssColor::parseArgumentPercentNoneTo1( // 0861 QStringLiteral("0")) 0862 .has_value()); 0863 QVERIFY(!CssColor::parseArgumentPercentNoneTo1( // 0864 QStringLiteral("1")) 0865 .has_value()); 0866 QVERIFY(!CssColor::parseArgumentPercentNoneTo1( // 0867 QStringLiteral("1.")) 0868 .has_value()); 0869 QVERIFY(!CssColor::parseArgumentPercentNoneTo1( // 0870 QStringLiteral("1 %")) 0871 .has_value()); 0872 QCOMPARE(CssColor::parseArgumentPercentNoneTo1( // 0873 QStringLiteral("1%")) 0874 .value(), 0875 0.01); 0876 QCOMPARE(CssColor::parseArgumentPercentNoneTo1( // 0877 QStringLiteral("100%")) 0878 .value(), 0879 1); 0880 QCOMPARE(CssColor::parseArgumentPercentNoneTo1( // 0881 QStringLiteral("200%")) 0882 .value(), 0883 2); 0884 QCOMPARE(CssColor::parseArgumentPercentNoneTo1( // 0885 QStringLiteral("-200%")) 0886 .value(), 0887 -2); 0888 QCOMPARE(CssColor::parseArgumentPercentNoneTo1( // 0889 QStringLiteral("0%")) 0890 .value(), 0891 0); 0892 QCOMPARE(CssColor::parseArgumentPercentNoneTo1( // 0893 QStringLiteral("none")) 0894 .value(), 0895 0); 0896 } 0897 0898 void testParseArgumentHueNoneTo360() 0899 { 0900 QCOMPARE(CssColor::parseArgumentHueNoneTo360( // 0901 QStringLiteral("none")) 0902 .value_or(42), 0903 0.); 0904 0905 QVERIFY(!CssColor::parseArgumentHueNoneTo360( // 0906 QString()) 0907 .has_value()); 0908 0909 QCOMPARE(CssColor::parseArgumentHueNoneTo360( // 0910 QStringLiteral("0")) 0911 .value_or(42), 0912 0.); 0913 QCOMPARE(CssColor::parseArgumentHueNoneTo360( // 0914 QStringLiteral("-5")) 0915 .value_or(42), 0916 355.); 0917 QCOMPARE(CssColor::parseArgumentHueNoneTo360( // 0918 QStringLiteral("5")) 0919 .value_or(42), 0920 5.); 0921 QCOMPARE(CssColor::parseArgumentHueNoneTo360( // 0922 QStringLiteral("500")) 0923 .value_or(42), 0924 140.); 0925 0926 QVERIFY(!CssColor::parseArgumentHueNoneTo360( // 0927 QStringLiteral("1 deg")) 0928 .has_value()); 0929 QVERIFY(!CssColor::parseArgumentHueNoneTo360( // 0930 QStringLiteral("deg")) 0931 .has_value()); 0932 QCOMPARE(CssColor::parseArgumentHueNoneTo360( // 0933 QStringLiteral("0deg")) 0934 .value_or(42), 0935 0.); 0936 QCOMPARE(CssColor::parseArgumentHueNoneTo360( // 0937 QStringLiteral("-5deg")) 0938 .value_or(42), 0939 355.); 0940 QCOMPARE(CssColor::parseArgumentHueNoneTo360( // 0941 QStringLiteral("5deg")) 0942 .value_or(42), 0943 5.); 0944 QCOMPARE(CssColor::parseArgumentHueNoneTo360( // 0945 QStringLiteral("500deg")) 0946 .value_or(42), 0947 140.); 0948 0949 QVERIFY(!CssColor::parseArgumentHueNoneTo360( // 0950 QStringLiteral("1 grad")) 0951 .has_value()); 0952 QVERIFY(!CssColor::parseArgumentHueNoneTo360( // 0953 QStringLiteral("grad")) 0954 .has_value()); 0955 QCOMPARE(CssColor::parseArgumentHueNoneTo360( // 0956 QStringLiteral("0grad")) 0957 .value_or(42), 0958 0.); 0959 QCOMPARE(CssColor::parseArgumentHueNoneTo360( // 0960 QStringLiteral("-5grad")) 0961 .value_or(42), 0962 355.5); 0963 QCOMPARE(CssColor::parseArgumentHueNoneTo360( // 0964 QStringLiteral("5grad")) 0965 .value_or(42), 0966 4.5); 0967 QCOMPARE(CssColor::parseArgumentHueNoneTo360( // 0968 QStringLiteral("500grad")) 0969 .value_or(42), 0970 90.); 0971 0972 QVERIFY(!CssColor::parseArgumentHueNoneTo360( // 0973 QStringLiteral("1 rad")) 0974 .has_value()); 0975 QVERIFY(!CssColor::parseArgumentHueNoneTo360( // 0976 QStringLiteral("rad")) 0977 .has_value()); 0978 QCOMPARE(CssColor::parseArgumentHueNoneTo360( // 0979 QStringLiteral("0rad")) 0980 .value_or(42), 0981 0.); 0982 QCOMPARE(CssColor::parseArgumentHueNoneTo360( // 0983 QStringLiteral("-1rad")) 0984 .value_or(42), 0985 -1. / (2 * pi) * 360 + 360); 0986 QCOMPARE(CssColor::parseArgumentHueNoneTo360( // 0987 QStringLiteral("1rad")) 0988 .value_or(42), 0989 1. / (2 * pi) * 360); 0990 QCOMPARE(CssColor::parseArgumentHueNoneTo360( // 0991 QStringLiteral("9rad")) 0992 .value_or(42), 0993 9. / (2 * pi) * 360 - 360); 0994 0995 QVERIFY(!CssColor::parseArgumentHueNoneTo360( // 0996 QStringLiteral("1 turn")) 0997 .has_value()); 0998 QVERIFY(!CssColor::parseArgumentHueNoneTo360( // 0999 QStringLiteral("turn")) 1000 .has_value()); 1001 QCOMPARE(CssColor::parseArgumentHueNoneTo360( // 1002 QStringLiteral("0turn")) 1003 .value_or(42), 1004 0.); 1005 QCOMPARE(CssColor::parseArgumentHueNoneTo360( // 1006 QStringLiteral("-0.5turn")) 1007 .value_or(42), 1008 180.); 1009 QCOMPARE(CssColor::parseArgumentHueNoneTo360( // 1010 QStringLiteral("-1turn")) 1011 .value_or(42), 1012 0.); 1013 QCOMPARE(CssColor::parseArgumentHueNoneTo360( // 1014 QStringLiteral("0.25turn")) 1015 .value_or(42), 1016 90.); 1017 QCOMPARE(CssColor::parseArgumentHueNoneTo360( // 1018 QStringLiteral("0.5turn")) 1019 .value_or(42), 1020 180.); 1021 QCOMPARE(CssColor::parseArgumentHueNoneTo360( // 1022 QStringLiteral("1turn")) 1023 .value_or(42), 1024 0); 1025 QCOMPARE(CssColor::parseArgumentHueNoneTo360( // 1026 QStringLiteral("1.25turn")) 1027 .value_or(42), 1028 90); 1029 1030 QVERIFY(!CssColor::parseArgumentHueNoneTo360( // 1031 QStringLiteral("1%")) 1032 .has_value()); 1033 } 1034 1035 #ifndef MSVC_DLL 1036 void testParse_data() 1037 { 1038 QTest::addColumn<QString>("function"); 1039 QTest::addColumn<ColorModel>("model"); 1040 QTest::addColumn<CssColor::CssPredefinedRgbColorSpace>("rgbColorSpace"); 1041 QTest::addColumn<double>("first"); 1042 QTest::addColumn<double>("second"); 1043 QTest::addColumn<double>("third"); 1044 QTest::addColumn<double>("forth"); 1045 QTest::addColumn<double>("alpha1"); 1046 1047 QTest::newRow("") // 1048 << QString() // 1049 << ColorModel::Invalid // 1050 << CssColor::CssPredefinedRgbColorSpace::Invalid // 1051 << 0. << 0. << 0. << 0. // 1052 << 0.; 1053 QTest::newRow("rgb(1 2 3)") // 1054 << QStringLiteral("rgb(1 2 3)") // 1055 << ColorModel::Rgb1 // 1056 << CssColor::CssPredefinedRgbColorSpace::Srgb // 1057 << 1. / 255. << 2. / 255. << 3. / 255. << 0. // 1058 << 1.; 1059 QTest::newRow("rgb(1 2 3);") // 1060 << QStringLiteral("rgb(1 2 3)") // 1061 << ColorModel::Rgb1 // 1062 << CssColor::CssPredefinedRgbColorSpace::Srgb // 1063 << 1. / 255. << 2. / 255. << 3. / 255. << 0. // 1064 << 1.; 1065 QTest::newRow("#010203") // 1066 << QStringLiteral("#010203") // 1067 << ColorModel::Rgb1 // 1068 << CssColor::CssPredefinedRgbColorSpace::Srgb // 1069 << 1. / 255. << 2. / 255. << 3. / 255. << 0. // 1070 << 1.; 1071 QTest::newRow(" #010203 ") // 1072 << QStringLiteral(" #010203 ") // 1073 << ColorModel::Rgb1 // 1074 << CssColor::CssPredefinedRgbColorSpace::Srgb // 1075 << 1. / 255. << 2. / 255. << 3. / 255. << 0. // 1076 << 1.; 1077 QTest::newRow("aliceblue") // 1078 << QStringLiteral("aliceblue") // 1079 << ColorModel::Rgb1 // 1080 << CssColor::CssPredefinedRgbColorSpace::Srgb // 1081 << 240. / 255. << 248. / 255. << 1. << 0. // 1082 << 1.; 1083 QTest::newRow(" aliceblue ") // 1084 << QStringLiteral(" aliceblue ") // 1085 << ColorModel::Rgb1 // 1086 << CssColor::CssPredefinedRgbColorSpace::Srgb // 1087 << 240. / 255. << 248. / 255. << 1. << 0. // 1088 << 1.; 1089 } 1090 1091 void testParse() 1092 { 1093 QFETCH(QString, function); 1094 QFETCH(ColorModel, model); 1095 QFETCH(CssColor::CssPredefinedRgbColorSpace, rgbColorSpace); 1096 QFETCH(double, first); 1097 QFETCH(double, second); 1098 QFETCH(double, third); 1099 QFETCH(double, forth); 1100 QFETCH(double, alpha1); 1101 1102 const auto temp = CssColor::parse(function); 1103 QCOMPARE(temp.model, model); 1104 QCOMPARE(temp.rgbColorSpace, rgbColorSpace); 1105 QCOMPARE(temp.color.first, first); 1106 QCOMPARE(temp.color.second, second); 1107 QCOMPARE(temp.color.third, third); 1108 QCOMPARE(temp.color.fourth, forth); 1109 QCOMPARE(temp.alpha1, alpha1); 1110 } 1111 #endif 1112 1113 #ifndef MSVC_DLL 1114 void testGenerateCss() 1115 { 1116 QHash<ColorModel, GenericColor> hash; 1117 hash.insert(ColorModel::OklchD65, GenericColor(0.5, 0.2, 10)); 1118 QCOMPARE(CssColor::generateCss(hash, 1, 3).value(0), // 1119 QStringLiteral("oklch(0.50 0.20 10)")); 1120 QCOMPARE(CssColor::generateCss(hash, 0.5, 3).value(0), // 1121 QStringLiteral("oklch(0.50 0.20 10 / 50%)")); 1122 const auto roundtrip = CssColor::parse( // 1123 CssColor::generateCss(hash, 0.5, 3).value(0)); 1124 QCOMPARE(roundtrip.alpha1, 0.5); 1125 QCOMPARE(roundtrip.model, ColorModel::OklchD65); 1126 QCOMPARE(roundtrip.rgbColorSpace, // 1127 CssColor::CssPredefinedRgbColorSpace::Invalid); 1128 QCOMPARE(roundtrip.color.first, 0.5); 1129 QCOMPARE(roundtrip.color.second, 0.2); 1130 QCOMPARE(roundtrip.color.third, 10); 1131 QCOMPARE(roundtrip.color.fourth, 0); 1132 } 1133 #endif 1134 }; 1135 1136 } // namespace PerceptualColor 1137 1138 QTEST_MAIN(PerceptualColor::TestCssColor) 1139 1140 // The following “include” is necessary because we do not use a header file: 1141 #include "testcsscolor.moc"