File indexing completed on 2024-12-01 07:26:58

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 "colorwheelimage.h"
0007 
0008 #include "rgbcolorspacefactory.h"
0009 #include <qcolor.h>
0010 #include <qglobal.h>
0011 #include <qimage.h>
0012 #include <qobject.h>
0013 #include <qsharedpointer.h>
0014 #include <qsize.h>
0015 #include <qtest.h>
0016 #include <qtestcase.h>
0017 #include <qwidget.h>
0018 
0019 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0020 #include <qtmetamacros.h>
0021 #else
0022 #include <qobjectdefs.h>
0023 #include <qstring.h>
0024 #endif
0025 
0026 class TestColorWheelSnippetClass : public QWidget
0027 {
0028     Q_OBJECT
0029 public:
0030     // A constructor that is clazy-conform
0031     explicit TestColorWheelSnippetClass(QWidget *parent = nullptr)
0032         : QWidget(parent)
0033     {
0034     }
0035     void testSnippet01()
0036     {
0037         //! [ColorWheelImage HiDPI usage]
0038         auto myColorSpace = PerceptualColor::RgbColorSpaceFactory::createSrgb();
0039         PerceptualColor::ColorWheelImage test{myColorSpace};
0040         // The function setImageSize() expects an int
0041         // value. static_cast<int> will round down, which
0042         // is the desired behaviour here. (Rounding up
0043         // would mean one more pixel, and on some Qt
0044         // styles this would fail.)
0045         test.setImageSize(static_cast<int>(100 * devicePixelRatioF()));
0046         test.setBorder(5 * devicePixelRatioF());
0047         test.setWheelThickness(10 * devicePixelRatioF());
0048         test.setDevicePixelRatioF(devicePixelRatioF());
0049         QImage myImage = test.getImage();
0050         //! [ColorWheelImage HiDPI usage]
0051         Q_UNUSED(myImage)
0052     }
0053 };
0054 
0055 namespace PerceptualColor
0056 {
0057 class RgbColorSpace;
0058 
0059 class TestColorWheelImage : public QObject
0060 {
0061     Q_OBJECT
0062 
0063 public:
0064     explicit TestColorWheelImage(QObject *parent = nullptr)
0065         : QObject(parent)
0066     {
0067     }
0068 
0069 private:
0070     QSharedPointer<RgbColorSpace> colorSpace = RgbColorSpaceFactory::createSrgb();
0071 
0072 private Q_SLOTS:
0073     void initTestCase()
0074     {
0075         // Called before the first test function is executed
0076     }
0077 
0078     void cleanupTestCase()
0079     {
0080         // Called after the last test function was executed
0081     }
0082 
0083     void init()
0084     {
0085         // Called before each test function is executed
0086     }
0087 
0088     void cleanup()
0089     {
0090         // Called after every test function
0091     }
0092 
0093     void testConstructor()
0094     {
0095         ColorWheelImage test(colorSpace);
0096     }
0097 
0098     void testImageSize()
0099     {
0100         ColorWheelImage test(colorSpace);
0101         QCOMPARE(test.getImage().size(), QSize(0, 0));
0102         test.setImageSize(5);
0103         QCOMPARE(test.getImage().size(), QSize(5, 5));
0104         test.setImageSize(500);
0105         QCOMPARE(test.getImage().size(), QSize(500, 500));
0106     }
0107 
0108     void testDevicePixelRatioF()
0109     {
0110         ColorWheelImage test(colorSpace);
0111         test.setImageSize(100);
0112         // Image size is as described.
0113         QCOMPARE(test.getImage().size(), QSize(100, 100));
0114         // Default devicePixelRatioF is 1
0115         QCOMPARE(test.getImage().devicePixelRatio(), 1);
0116         // Testing with a (non-integer) scale factor
0117         test.setDevicePixelRatioF(1.5);
0118         // Image size remains unchanged.
0119         QCOMPARE(test.getImage().size(), QSize(100, 100));
0120         // Default devicePixelRatioF is 1.5
0121         QCOMPARE(test.getImage().devicePixelRatio(), 1.5);
0122     }
0123 
0124     void testBorderOdd()
0125     {
0126         ColorWheelImage test(colorSpace);
0127         test.setImageSize(99);
0128         // Default border is zero: no transparent border.
0129         QVERIFY2(test.getImage().pixelColor(49, 0).alpha() > 0, "Verify that pixel top center is not transparent.");
0130         QVERIFY2(test.getImage().pixelColor(49, 98).alpha() > 0, "Verify that pixel bottom center is not transparent.");
0131         QVERIFY2(test.getImage().pixelColor(0, 49).alpha() > 0, "Verify that pixel left is not transparent.");
0132         QVERIFY2(test.getImage().pixelColor(98, 49).alpha() > 0, "Verify that pixel right is not transparent.");
0133         test.setBorder(1);
0134         // Now, the pixels should become transparent.
0135         QCOMPARE(test.getImage().pixelColor(49, 0).alpha(), 0);
0136         QCOMPARE(test.getImage().pixelColor(49, 98).alpha(), 0);
0137         QCOMPARE(test.getImage().pixelColor(0, 49).alpha(), 0);
0138         QCOMPARE(test.getImage().pixelColor(98, 49).alpha(), 0);
0139     }
0140 
0141     void testBorderEven()
0142     {
0143         ColorWheelImage test(colorSpace);
0144         test.setImageSize(100);
0145         // Default border is zero: no transparent border.
0146         QVERIFY2(test.getImage().pixelColor(49, 0).alpha() > 0, "Verify that pixel top center is not transparent.");
0147         QVERIFY2(test.getImage().pixelColor(50, 0).alpha() > 0, "Verify that pixel top center is not transparent.");
0148         QVERIFY2(test.getImage().pixelColor(49, 99).alpha() > 0, "Verify that pixel bottom center is not transparent.");
0149         QVERIFY2(test.getImage().pixelColor(50, 99).alpha() > 0, "Verify that pixel bottom center is not transparent.");
0150         QVERIFY2(test.getImage().pixelColor(0, 49).alpha() > 0, "Verify that pixel left is not transparent.");
0151         QVERIFY2(test.getImage().pixelColor(0, 50).alpha() > 0, "Verify that pixel left is not transparent.");
0152         QVERIFY2(test.getImage().pixelColor(99, 49).alpha() > 0, "Verify that pixel right is not transparent.");
0153         QVERIFY2(test.getImage().pixelColor(99, 50).alpha() > 0, "Verify that pixel right is not transparent.");
0154         test.setBorder(1);
0155         // Now, the pixels should become transparent.
0156         QCOMPARE(test.getImage().pixelColor(49, 0).alpha(), 0);
0157         QCOMPARE(test.getImage().pixelColor(50, 0).alpha(), 0);
0158         QCOMPARE(test.getImage().pixelColor(49, 99).alpha(), 0);
0159         QCOMPARE(test.getImage().pixelColor(50, 99).alpha(), 0);
0160         QCOMPARE(test.getImage().pixelColor(0, 49).alpha(), 0);
0161         QCOMPARE(test.getImage().pixelColor(0, 50).alpha(), 0);
0162         QCOMPARE(test.getImage().pixelColor(99, 49).alpha(), 0);
0163         QCOMPARE(test.getImage().pixelColor(99, 50).alpha(), 0);
0164     }
0165 
0166     void testCache()
0167     {
0168         ColorWheelImage test(colorSpace);
0169         test.setImageSize(50); // Set a non-zero image size
0170         QVERIFY2(test.m_image.isNull(), "Verify that instantiation is done with empty cache.");
0171         test.setBorder(5);
0172         QVERIFY2(test.m_image.isNull(), "Verify that setting border does not trigger re-calculation.");
0173         Q_UNUSED(test.getImage());
0174         QVERIFY2(!test.m_image.isNull(), "Verify that getImage() triggers re-calculation.");
0175         test.setBorder(5);
0176         QVERIFY2(!test.m_image.isNull(),
0177                  "Verify that setBorder() does not erase the cache"
0178                  " if the value that was set is the same than before.");
0179     }
0180 
0181     void testCornerCases()
0182     {
0183         ColorWheelImage test(colorSpace);
0184         test.setImageSize(50); // Set a non-zero image size
0185         QVERIFY2(!test.getImage().isNull(),
0186                  "Verify that there is no crash and the returned image is not "
0187                  "null.");
0188         test.setBorder(10);
0189         QVERIFY2(!test.getImage().isNull(),
0190                  "Verify that there is no crash and the returned image is not "
0191                  "null.");
0192         test.setBorder(25);
0193         QVERIFY2(!test.getImage().isNull(),
0194                  "Verify that there is no crash and the returned image is not "
0195                  "null.");
0196         test.setBorder(100);
0197         QVERIFY2(!test.getImage().isNull(),
0198                  "Verify that there is no crash and the returned image is not "
0199                  "null.");
0200         test.setBorder(5);
0201         QVERIFY2(!test.getImage().isNull(),
0202                  "Verify that there is no crash and the returned image is not "
0203                  "null.");
0204         test.setWheelThickness(0);
0205         QVERIFY2(!test.getImage().isNull(),
0206                  "Verify that there is no crash and the returned image is not "
0207                  "null.");
0208         test.setWheelThickness(10);
0209         QVERIFY2(!test.getImage().isNull(),
0210                  "Verify that there is no crash and the returned image is not "
0211                  "null.");
0212         test.setWheelThickness(25);
0213         QVERIFY2(!test.getImage().isNull(),
0214                  "Verify that there is no crash and the returned image is not "
0215                  "null.");
0216         test.setWheelThickness(100);
0217         QVERIFY2(!test.getImage().isNull(),
0218                  "Verify that there is no crash and the returned image is not "
0219                  "null.");
0220         test.setWheelThickness(10);
0221         QVERIFY2(!test.getImage().isNull(),
0222                  "Verify that there is no crash and the returned image is not "
0223                  "null.");
0224     }
0225 
0226     void testVeryThickWheel()
0227     {
0228         ColorWheelImage test(colorSpace);
0229         test.setImageSize(51); // Set a non-zero image size
0230         test.setWheelThickness(100);
0231         // The wheel is so thick that even in the middle, there should be
0232         // a fully opaque pixel.
0233         QCOMPARE(test.getImage().pixelColor(25, 25).alpha(), 255);
0234     }
0235 
0236     void testVeryBigBorder()
0237     {
0238         ColorWheelImage test(colorSpace);
0239         const int myImageSize = 51;
0240         test.setImageSize(myImageSize); // Set a non-zero image size
0241         test.setWheelThickness(5);
0242         // Set a border that is bigger than half of the image size
0243         test.setBorder(myImageSize / 2 + 1);
0244         // The border is so big that the hole image should be transparent.
0245         for (int x = 0; x < myImageSize; ++x) {
0246             for (int y = 0; y < myImageSize; ++y) {
0247                 QCOMPARE(test.getImage().pixelColor(x, y).alpha(), 0);
0248             }
0249         }
0250     }
0251 
0252     void testDevicePixelRatioFForExtremeCases()
0253     {
0254         ColorWheelImage test(colorSpace);
0255         // Testing with a (non-integer) scale factor
0256         test.setDevicePixelRatioF(1.5);
0257         // Test with fully transparent image (here, the border is too big
0258         // for the given image size)
0259         test.setImageSize(20);
0260         test.setBorder(30);
0261         QCOMPARE(test.getImage().devicePixelRatio(), 1.5);
0262     }
0263 
0264     void testSnippet01()
0265     {
0266         TestColorWheelSnippetClass mySnippets;
0267         mySnippets.testSnippet01();
0268     }
0269 };
0270 
0271 } // namespace PerceptualColor
0272 
0273 QTEST_MAIN(PerceptualColor::TestColorWheelImage)
0274 
0275 // The following “include” is necessary because we do not use a header file:
0276 #include "testcolorwheelimage.moc"