1 | #include <memory> |
2 | |
3 | #include <QtTest/QTest> |
4 | #include <QtCore/QDebug> |
5 | #include <QImage> |
6 | |
7 | #include <poppler-qt6.h> |
8 | |
9 | // Unit tests for rendering axial shadings without full opacity |
10 | class TestStrokeOpacity : public QObject |
11 | { |
12 | Q_OBJECT |
13 | public: |
14 | explicit TestStrokeOpacity(QObject *parent = nullptr) : QObject(parent) { } |
15 | private slots: |
16 | void checkStrokeOpacity_data(); |
17 | void checkStrokeOpacity(); |
18 | }; |
19 | |
20 | void TestStrokeOpacity::checkStrokeOpacity_data() |
21 | { |
22 | QTest::addColumn<int>(name: "backendType" ); |
23 | |
24 | QTest::newRow(dataTag: "splash" ) << (int)Poppler::Document::SplashBackend; |
25 | QTest::newRow(dataTag: "qpainter" ) << (int)Poppler::Document::QPainterBackend; |
26 | } |
27 | |
28 | void TestStrokeOpacity::checkStrokeOpacity() |
29 | { |
30 | QFETCH(int, backendType); |
31 | |
32 | std::unique_ptr<Poppler::Document> doc = Poppler::Document::load(TESTDATADIR "/unittestcases/stroke-alpha-pattern.pdf" ); |
33 | QVERIFY(doc != nullptr); |
34 | |
35 | doc->setRenderBackend((Poppler::Document::RenderBackend)backendType); |
36 | |
37 | // BUG: For some reason splash gets the opacity wrong when antialiasing is switched off |
38 | if (backendType == (int)Poppler::Document::SplashBackend) { |
39 | doc->setRenderHint(hint: Poppler::Document::Antialiasing, on: true); |
40 | } |
41 | |
42 | const auto page = std::unique_ptr<Poppler::Page>(doc->page(index: 0)); |
43 | QVERIFY(page != nullptr); |
44 | |
45 | // Render (at low resolution and with cropped marging) |
46 | QImage image = page->renderToImage(xres: 36, yres: 36, x: 40, y: 50, w: 200, h: 230); |
47 | |
48 | // The actual tests start here |
49 | |
50 | // Allow a tolerance. |
51 | int tolerance; |
52 | auto approximatelyEqual = [&tolerance](QRgb c0, const QColor &c1) { |
53 | return std::abs(x: qAlpha(rgb: c0) - c1.alpha()) <= tolerance && std::abs(x: qRed(rgb: c0) - c1.red()) <= tolerance && std::abs(x: qGreen(rgb: c0) - c1.green()) <= tolerance && std::abs(x: qBlue(rgb: c0) - c1.blue()) <= tolerance; |
54 | }; |
55 | |
56 | // At the lower left of the test document is a square with an axial shading, |
57 | // which should be rendered with opacity 0.25. |
58 | // Check that with a sample pixel |
59 | auto pixel = image.pixel(x: 70, y: 160); |
60 | |
61 | // Splash and QPainter backends implement shadings slightly differently, |
62 | // hence we cannot expect to get precisely the same colors. |
63 | tolerance = 2; |
64 | QVERIFY(approximatelyEqual(pixel, QColor(253, 233, 196, 255))); |
65 | |
66 | // At the upper left of the test document is a stroked square with an axial shading. |
67 | // This is implemented by filling a clip region defined by a stroke outline. |
68 | // Check whether the backend really only renders the stroke, not the region |
69 | // surrounded by the stroke. |
70 | auto pixelUpperLeftInterior = image.pixel(x: 70, y: 70); |
71 | |
72 | tolerance = 0; |
73 | QVERIFY(approximatelyEqual(pixelUpperLeftInterior, Qt::white)); |
74 | |
75 | // Now check whether that stroke is semi-transparent. |
76 | // Bug https://gitlab.freedesktop.org/poppler/poppler/-/issues/178 |
77 | auto pixelUpperLeftOnStroke = image.pixel(x: 70, y: 20); |
78 | |
79 | tolerance = 2; |
80 | QVERIFY(approximatelyEqual(pixelUpperLeftOnStroke, QColor(253, 233, 196, 255))); |
81 | |
82 | // At the upper right there is a semi-transparent stroked red square |
83 | // a) Make sure that the color is correct. |
84 | auto pixelUpperRightOnStroke = image.pixel(x: 130, y: 20); |
85 | |
86 | tolerance = 0; |
87 | QVERIFY(approximatelyEqual(pixelUpperRightOnStroke, QColor(246, 196, 206, 255))); |
88 | |
89 | // b) Make sure that it is really stroked, not filled |
90 | auto pixelUpperRightInterior = image.pixel(x: 130, y: 50); |
91 | QVERIFY(approximatelyEqual(pixelUpperRightInterior, Qt::white)); |
92 | } |
93 | |
94 | QTEST_GUILESS_MAIN(TestStrokeOpacity) |
95 | |
96 | #include "check_stroke_opacity.moc" |
97 | |